Why it matters
A poorly named branch costs minutes on every PR review, makes auditing harder and breaks automation (CI regexes, management bots). A good convention means you can read the name and know the type of change, the ticket it points to and the area touched.
The standard pattern
<type>/<ticket>-<short-description>. Example:
feature/PROJ-123-add-user-login. The / separates the prefix;
some hosts (GitHub, GitLab) render it as a visual subfolder. Inside the slug, kebab-case
avoids issues with shells and URLs.
Common prefixes
- feature/: new functionality.
- fix/: non-urgent bug fix.
- hotfix/: fix going straight to production.
- release/: release preparation branch.
- chore/: maintenance, dependencies.
- docs/: documentation only.
- experiment/ or spike/: tests that may not reach main.
GitFlow vs trunk-based
GitFlow has long-lived branches (develop, main,
release/*). Trunk-based has main and short-lived branches that
merge in hours or days. Naming convention is the same; trunk-based just pushes branches
to live shorter.
Forbidden characters
Git doesn't allow spaces, double colons (::), question marks, asterisks,
brackets or tildes in branch names. Stick to [a-z0-9-_/.]. Extra slashes are
accepted but confuse humans. Avoid names longer than 50 characters.
Uppercase ticket
Ticket IDs usually go in uppercase (PROJ-123). The rest of the slug in
lowercase. Visually distinct: feature/PROJ-123-add-login. If your system
is case-insensitive (Windows defaults), all-lowercase also works.
Branch policies
In GitHub or GitLab you can enforce the convention with branch protection and actions
validating the name before accepting pushes. A regex like
^(feature|fix|hotfix|chore)\/[A-Z]{2,}-\d+-[a-z0-9-]+$ blocks
non-conforming pushes.
Delete merged branches
Configure auto-delete after merge in GitHub Settings. git fetch --prune
removes references to deleted remote branches. Without this, the repo ends up with
hundreds of zombie branches and autocomplete falls apart.