Skip to main content
RunBook Academy

Git, CI/CD & GitOpsVIII · BranchingBranching

Branch naming and organization — patterns that signal intent to the team

Intermediate⏱ ~16 mingit

What you'll learn

  • Recognise the conventional prefixes (feature/, bugfix/, release/, hotfix/) and what each one signals about lifetime and merge target
  • Apply slash-namespaces in branch names and understand how they map to the refs/heads/ directory
  • Read a branch name and infer the merge strategy, review requirements, and deletion window without checking the branch contents
  • Choose between long-lived trunk-based branches and short-lived feature branches based on team size and release cadence
  • Recognise the failure modes of poor naming (no naming convention, ambiguous prefixes, ticket-id-only names)

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

A branch name is the smallest possible unit of project documentation. Before a reviewer opens the diff, before CI runs the tests, before the merge button is offered, the branch name is the only information the team has about a line of work. A name like feature/iam-rotation carries four signals: the kind of work (feature), the area of the system (iam), the specific change (rotation), and an implicit merge target (the trunk). A name like wip or test or john-branch carries none of those signals and forces the reviewer to read the commit log to find out. In production, the branch name is the cheapest piece of documentation the team can write. The discipline is to write names that document themselves.

Conventional prefixes

Four prefixes cover the vast majority of branch lifetimes in a production workflow:

  • feature/<name> — A new capability or non-urgent change. Created from the trunk (typically main), merged back via a pull request, deleted after merge. Lifetime: days to weeks.
  • bugfix/<name> — A bug fix that does not need to ship immediately. Created from the trunk, merged via a PR with a test plan attached, deleted after merge. Lifetime: hours to days.
  • release/<name> — A stabilisation branch cut from the trunk when a release candidate is being prepared. Accepts only bug fixes and version bumps; new features are forbidden. Lifetime: days to weeks, until the release ships.
  • hotfix/<name> — An emergency fix that must ship immediately, bypassing the normal release cadence. Created from a tagged release commit, merged back to both the trunk and the release branch, deleted after merge. Lifetime: hours.
# Conventional names
git switch -c feature/iam-key-rotation
git switch -c bugfix/cert-renewal-fails-on-renew
git switch -c release/v1.4.0
git switch -c hotfix/prod-503-ingress

The signal each name carries:

PrefixSourceMerge targetLifetime
feature/trunktrunk via PRdays-weeks
bugfix/trunktrunk via PRhours-days
release/trunk at cut pointtrunk after shipdays-weeks
hotfix/tagged releasetrunk + release branchhours

A reviewer who sees feature/iam-key-rotation knows it is a new capability that should land via PR into main and can be deleted after the merge. The same reviewer who sees hotfix/prod-503 knows it is an emergency change that may have skipped the ordinary review cadence and must be scrutinised carefully. The prefix is a routing rule.

flowchart LR
    A["main"] --> B["feature/iam-rotation"]
    B --> C["PR into main"]
    C --> D["merged"]
    A --> E["release/v1.4.0"]
    E --> F["bugfix/cert-renewal"]
    F --> G["PR into release/v1.4.0"]
    G --> H["shipped"]
    I["v1.3.0 tag"] --> J["hotfix/prod-503"]
    J --> K["merged into main + v1.3.1 tag"]

The diagram shows the four conventional flows. feature/ and bugfix/ branches return to main; release/ branches accept bugfixes and ship; hotfix/ branches fork from a tag and merge back to both the trunk and the live release.

Slash-namespaces and ref storage

A branch name with slashes is not just a convention; it is a hierarchical ref name that maps directly to the directory layout under .git/refs/heads/:

git branch -a
#   feature/iam-rotation
#   hotfix/prod-503
#   release/v1.4.0

On disk:

ls "$GIT_DIR/refs/heads"
# feature
# hotfix
# main
# release

ls "$GIT_DIR/refs/heads/feature"
# iam-rotation

ls "$GIT_DIR/refs/heads/release"
# v1.4.0

The slash becomes a directory separator. A branch named feature/iam-rotation is a file at .git/refs/heads/feature/iam-rotation; a branch named feature/iam/key-rotation would be a file at .git/refs/heads/feature/iam/key-rotation. The hierarchy is real, and git branch --list 'feature/*' exploits it to match every branch under the feature/ namespace.

The hierarchy can be as deep as the team finds useful. Common patterns:

# Flat: one level of prefix
feature/iam-rotation
bugfix/cert-renewal

# Two-level: subsystem grouping
feature/iam/key-rotation
feature/network/policy-update
bugfix/storage/s3-permission-denied

# Three-level: subsystem + component
feature/iam/keys/rotation-cron
bugfix/network/policy/egress-block

The deeper the hierarchy, the more the namespace can be matched with glob patterns. --list 'feature/iam/*' returns every feature branch in the IAM subsystem; --list 'release/v*' returns every release branch whose name starts with v.

What a good branch name documents

The four properties a good branch name carries, in priority order:

  1. Lifetime. Is this a feature, a bug fix, a release, or a hotfix? The prefix answers this question and tells the reviewer the expected merge target and deletion window.
  2. Area. Which subsystem does this touch? The first path component after the prefix (iam, network, storage) scopes the change and lets CI run only the relevant test suite.
  3. Specific change. What is the change in plain English? The remaining path components describe what the change is. A name like iam-rotation is descriptive; a name like fix-bug is not.
  4. Ticket reference. What tracking-system entry is this change tied to? The trailing path component (often a JIRA key like INFRA-1234 or a GitHub issue number) links the branch to the issue tracker.
# All four properties in one name
feature/iam/key-rotation-INFRA-1234

# Three properties (no ticket)
bugfix/storage/s3-permission-denied

# Two properties (no subsystem grouping)
hotfix/prod-503

# One property (just a prefix)
feature/wip

The last example is the failure mode: a prefix with no documentation. The reviewer cannot scope the change, cannot link it to a ticket, and cannot predict the merge target.

Patterns for trunk-based versus feature-branch workflows

The branch naming convention interacts with the team’s branching strategy. Two ends of the spectrum:

  • Trunk-based development. Most work happens on the trunk itself, behind feature flags. Branches are short-lived (hours), names are minimal (eng-name/initials), and the merge target is always the trunk. The discipline is “branch per change, merge within the day”.

  • Feature-branch workflow. Each significant change lives on its own branch until reviewed. Names are descriptive (feature/<area>/<change>-<ticket>), branches live for days or weeks, and the merge target is the trunk via a PR. The discipline is “branch per PR, merge when reviewed”.

# Trunk-based naming: short-lived, minimal
git switch -c jdoe/flag-iam-rotation
git switch -c jdoe/cleanup-cert-handling

# Feature-branch naming: long-lived, descriptive
git switch -c feature/iam/key-rotation-INFRA-1234
git switch -c bugfix/network/policy-update-INFRA-1235

Trunk-based naming is faster to write but requires the team to have strong feature-flag discipline to keep the trunk shippable. Feature-branch naming is slower to write but allows the trunk to be protected by branch protection and required reviews. The choice depends on team size, release cadence, and the cost of a broken trunk — not on personal preference.

Production discipline

  1. Adopt a documented prefix convention. The first ticket in the team’s onboarding doc should be “the branch prefixes we use and what they mean”. Without documentation, the convention is folklore and is followed inconsistently.
  2. Include a ticket ID in the branch name when one exists. The ticket ID is the link from the commit to the discussion, the acceptance criteria, and the closing record. A branch without a ticket ID is a branch whose rationale is not recorded anywhere outside the commit message.
  3. Scope CI on the prefix. CI that detects the prefix (feature/iam/*) can run the IAM test suite only, not the full battery. The naming convention is the routing key.
  4. Delete branches after merge. A feature/ branch that has been merged into the trunk is a branch whose work is in the trunk and whose existence serves no purpose. The git-cicd-gitops-viii-02 lifecycle lesson covers the safe deletion pattern.

Cross-course references

  • Ansible for Production Sysadmins - Part XXXVIII (Review) uses feature/<area>/<change>-<ticket> as the standard Ansible repository convention. The prefix is matched by the Ansible lint configuration to scope playbook reviews.
  • GitOps with Argo CD - Part IV (AppSources) discusses slash-namespaces in the context of multi-source applications, where each source has its own branch prefix and the controller uses the prefix to route sync policies.
  • Terraform for Production Sysadmins - Part XII (State) draws the analogy between branch prefixes and Terraform module prefixes: both are routing keys that signal which test suite, review cadence, and deletion window apply.

Quiz

Knowledge check · 4 questions

  1. Q1. A branch named `hotfix/prod-503-ingress` is opened. Which of the following statements is correct?

  2. Q2. A branch named `feature/iam/key-rotation-INFRA-1234` is stored on disk as a single file at `.git/refs/heads/feature/iam/key-rotation-INFRA-1234`.

  3. Q3. What four properties does a good branch name carry, and what is the failure mode when a name carries none of them?

  4. Q4. Recommend a branch naming convention for an infrastructure team and defend it against two common objections.

    An infrastructure team of 12 engineers has been using ad-hoc branch names (`wip`, `test`, `john-fix`, `INFRA-1234`) for 18 months. The on-call rotation reports that incident postmortems frequently cannot link a production change to a named branch because the branch was named ambiguously. The team lead asks for a recommended convention. Two senior engineers object: one says 'conventions slow us down', the other says 'the JIRA ID alone is enough, the prefix is noise'.

Passing score: 75%. Answers are checked in this browser.