Skip to content
Quasar Tools Logo

'Is Not a Valid Branch Name' Git Error Explained

"Is not a valid branch name" in Git explained: what causes it, which characters are forbidden, rules for every platform, and how to fix or rename a branch fast.

DH
Tutorials & How-Tos11 min read2,600 words

Git's "is not a valid branch name" error is precise — the name you supplied violates one or more of Git's refname rules. The fix is almost always a one-line change once you know which character or pattern triggered it. This guide covers the full set of Git naming restrictions, the most common causes with exact fixes, how to rename a branch that already exists, and how to enforce valid naming across your whole team before anyone hits the error in the first place.

14+Forbidden patternsper Git refname spec
1 cmdTo rename a branchgit branch -m old new
0Hard length limitbut 50–72 chars recommended

What the error means

When Git reports `fatal: 'some-name' is not a valid branch name`, it means the string you passed as a branch name violates Git's refname specification — the set of rules governing what constitutes a valid reference name in a Git repository. Git uses the same rules for branch names, tag names, and remote tracking names, because all of them are stored as references in the `.git/refs/` directory.

The validation happens before any object is written. Git runs your proposed name through `check_refname_format()` internally and aborts with the error if the name fails. This means you see the error immediately when running `git checkout -b`, `git branch`, or `git switch -c` — there is no partial state to clean up.

Where the error appears

  • `git checkout -b branch-name` — creating a new branch and switching to it
  • `git branch branch-name` — creating a new branch without switching
  • `git switch -c branch-name` — the modern equivalent of checkout -b
  • `git push origin branch-name` — pushing to a remote with an invalid local name
  • CI/CD scripts — when a branch name is constructed programmatically from a ticket ID or commit message

Note

The full Git error message quotes the exact name that failed: `fatal: 'my feature branch' is not a valid branch name`. The quoted value is the literal string Git received — including any spaces, special characters, or shell-expanded values. This makes it easier to identify exactly which character caused the problem.

Git branch naming rules

Git's refname specification (defined in `git-check-ref-format` man page) describes a precise set of characters and patterns that are forbidden. Learning the rules once prevents all future naming errors — there are no ambiguous cases once you know the full list.

Explicitly forbidden characters and sequences

  • Space (ASCII 0x20) — the most common mistake; use `-` or `_` instead.
  • Tilde `~` — used in reflog notation (`branch~2` means two commits before the tip).
  • Caret `^` — used in revision notation (`branch^` means the parent commit).
  • Colon `:` — used in fetch refspec notation (`refs/heads/main:refs/heads/main`).
  • Question mark `?` — glob wildcard character in ref patterns.
  • Asterisk `*` — glob wildcard character in ref patterns.
  • Open bracket `[` — glob character set opener.
  • Backslash `\` — path separator on Windows; forbidden to avoid cross-platform issues.
  • Double dot `..` — used in range notation (`main..feature`).
  • @{ sequence — reflog shorthand notation (`branch@{1}` is a reflog entry).

Positional and structural rules

  • Cannot start with a dot (`.`) — hidden files convention; `.hidden` is not a valid start.
  • Cannot end with a dot (`.`) — ambiguous with `.lock` extension and file extension notation.
  • Cannot end with `.lock` — Git uses `.lock` suffix for lock files; any path component ending in `.lock` is forbidden.
  • Cannot start with a hyphen (`-`) — conflicts with command-line option parsing.
  • Cannot contain consecutive dots (`..`) — range notation conflict (see above).
  • Cannot be the single character `@` — shorthand for `HEAD`.
  • Cannot contain control characters — ASCII characters below 0x20 and DEL (0x7F) are forbidden.
  • Cannot be empty — an empty string is not a valid name.
valid and invalid examples
bash
# ✓ Valid branch names
git checkout -b feature/add-login
git checkout -b fix/null-pointer-123
git checkout -b release/v2.1.0
git checkout -b chore_update-deps
git checkout -b users/alice/experiment

# ✗ Invalid — contains a space
git checkout -b "my feature"
# fatal: 'my feature' is not a valid branch name

# ✗ Invalid — double dot
git checkout -b feature..login
# fatal: 'feature..login' is not a valid branch name

# ✗ Invalid — ends with .lock
git checkout -b release.lock
# fatal: 'release.lock' is not a valid branch name

# ✗ Invalid — starts with hyphen
git checkout -b -hotfix
# fatal: '-hotfix' is not a valid branch name

Tip

Run `git check-ref-format --branch your-proposed-name` to test any name before creating a branch. It exits with code 0 if the name is valid and code 1 if it is not — useful in scripts and pre-commit hooks. For a browser-based check with team convention support, use the [Branch Name Convention Validator](/tools/data/validators/branch-name-convention-validator).

Common causes and fixes

Most occurrences of this error come from a small number of repeating patterns. Each has a specific cause and a specific one-line fix.

Spaces from copy-pasted ticket titles

The most common trigger is copying a ticket or story title directly into the branch name. "Add user login form" becomes `git checkout -b Add user login form`, which Git sees as three separate arguments and rejects the branch name `Add`. Fix: replace every space with a hyphen. Many teams automate this with a `branch-from-ticket` alias or script that transforms the title before passing it to Git. The Slug Generator converts any text into a clean hyphen-separated slug suitable for branch names.

Special characters in CI/CD variable interpolation

CI pipelines often construct branch names from environment variables — PR titles, commit messages, or Jira ticket IDs. If any of those values contains a special character (a colon in a Jira ID like `PROJECT:123`, or a slash in a semver tag like `v1.0.0/rc.1`), the interpolated branch name will fail. Fix: sanitise the input before using it as a branch name. Replace non-alphanumeric characters with hyphens and strip any leading or trailing hyphens and dots.

Trailing dot or .lock suffix

A branch name that ends with a dot (`feature.`) or ends with `.lock` (`release.lock`) fails because Git reserves these patterns for lock files. This error typically appears when a developer types a name ending with a period by accident, or when a script appends `.lock` as part of a generated name. Fix: remove the trailing dot, or replace `.lock` with a valid suffix like `-locked` or `-pending`.

Invalid patternExampleFix
Spacefeature/add loginfeature/add-login
Double dotfeat..loginfeat/login
Tildehotfix~v2hotfix-v2
ColonPROJECT:123PROJECT-123
Trailing dotrelease.release
Ends with .lockfix.lockfix-pending
Starts with hyphen-bugfixbugfix
@ followed by {user@{branch}user-branch
Backslashfeature\loginfeature/login

Branch Name Convention Validator

Validate Git branch names against the full refname spec and your team's convention — browser-local, instant feedback, no setup required.

Open tool

How to rename an invalid branch

In rare cases — particularly with older Git versions or branches created via third-party tools — you might end up with an invalid branch name already committed to your repository. Modern Git prevents this at creation time, but if you inherit a repository with a problematic branch name, here is how to fix it.

1

Rename the local branch

Run `git branch -m old-name new-name` to rename the branch in your local repository. The `-m` flag moves (renames) the branch reference without touching the commit history. If the old name contains characters that make quoting tricky in your shell, use single quotes around it: `git branch -m 'old name with spaces' new-valid-name`.

2

Push the new name to the remote

After renaming locally, push the new branch to the remote: `git push origin new-valid-name`. This creates the new branch on the remote. If the old branch was already pushed, teammates should update their local tracking reference with `git fetch --prune` after you delete the old remote branch.

3

Delete the old remote branch

Remove the old remote branch: `git push origin --delete old-name`. On GitHub, GitLab, and Bitbucket, you can also rename branches through the web UI under the branch list — this is the safer option when the old name contains characters that are difficult to pass through the CLI without escaping.

4

Update any open pull requests

If the renamed branch had open pull requests, most platforms (GitHub, GitLab) automatically update the PR's base branch reference when you rename through the web UI. If you renamed via CLI, check your open PRs and update the head branch reference manually if needed. Any CI runs against the old branch name will also need to be re-triggered against the new name.

Warning

Do not rename a branch that is currently the default branch (`main` or `master`) without first updating your repository settings. Renaming the default branch without updating the remote HEAD pointer will cause `git clone` to check out the wrong branch by default for all subsequent clones.

Platform-specific naming rules

Git's own refname rules are the baseline. Remote hosting platforms apply additional restrictions on top — a name that passes Git's local validation may still fail on push to GitHub or GitLab. Understanding the platform-specific rules prevents the frustration of a name that works locally but fails remotely.

GitHub additional restrictions

GitHub rejects branch names that end with `.lock` at any path component (not just the final segment), branch names that contain consecutive dots at any position, and names that contain a null byte. GitHub also enforces a maximum branch name length of 255 bytes. The GitHub web interface additionally strips leading and trailing whitespace from branch names created through the UI.

GitLab additional restrictions

GitLab adds restrictions for protected branch patterns — names containing `*` wildcards are reserved for protected branch rules and cannot be used as literal branch names. GitLab also reserves branch names matching its internal namespacing like `protected` and `refs`. Branch names longer than 255 characters are rejected. The GitLab CI pipeline name validation is separate from the Git refname validation — CI variable interpolation errors appear as pipeline failures rather than Git errors.

Windows filesystem considerations

On Windows, the `.git/refs/heads/` directory stores each branch as a file. This means all Windows filename restrictions apply: names cannot contain `<`, `>`, `"`, `|`, `?`, or `*`; names cannot end with a space or period; and names are case-insensitive on NTFS. The case-insensitivity issue is particularly important in mixed teams — `Feature/Login` and `feature/login` are the same branch on Windows but different branches on Linux and macOS.


RuleGit coreGitHubGitLabWindows filesystem
No spaces
No .lock suffix✓ any component
No double dots
No leading hyphen
Max 255 bytes✗ (no limit)OS path limit
Case-insensitive✓ (NTFS)
No * as literal name✓ reservedN/A

Branch naming conventions by team

Valid is the floor, not the ceiling. A branch name can be valid according to Git's rules while still being unclear, inconsistent, or unusable in your team's workflow. Established conventions add predictability on top of technical validity — every team member can read a branch name and immediately understand its purpose, scope, and lifecycle.

Gitflow convention

Gitflow uses five branch types: `main` (production), `develop` (integration), `feature/description`, `release/version`, and `hotfix/description`. Branch names use the category as a prefix followed by a forward slash and a hyphen-separated description. Release branches include the version number (`release/1.4.0`). This convention is well-supported by most Git GUI clients and CI tools, which recognise the prefixes as branch categories.

GitHub Flow and trunk-based conventions

GitHub Flow uses a simpler structure: `main` plus short-lived feature branches named descriptively (`add-oauth-login`, `fix-pagination-bug`). Trunk-based development similarly uses `main` plus very short-lived branches that are merged within hours. Both approaches prefer short, lowercase, hyphen-separated names without category prefixes — the assumption is that branch names are temporary and the PR title and description carry the context.

Ticket-reference conventions

Many teams prefix branch names with a ticket reference: `JIRA-1234-fix-login-bug` or `feat/GH-456-add-dark-mode`. The ticket ID provides traceability between the branch and the originating work item. When constructing these names programmatically, always sanitise the ticket description portion — ticket titles frequently contain colons, slashes, and other characters that break Git naming rules.

Branch names, like commit messages, are documentation. A consistent naming convention turns your branch list into a readable changelog of work in progress.

Conventional Commits community

Preventing invalid branch names

Fixing individual errors is reactive. The better approach is to prevent invalid names from being created in the first place — through validation tools, editor integrations, and CI checks that catch problems before they disrupt the team.

Pre-push Git hooks

A `.git/hooks/pre-push` script runs before any `git push` and can validate the current branch name against your team's convention. If the name fails, the hook exits with a non-zero code and aborts the push with an explanatory message. Use the `pre-commit` framework to distribute hooks consistently across the team — individual `.git/hooks/` files are not committed to the repository, but a `.pre-commit-config.yaml` is.

CI pipeline name validation

Add a branch name validation step at the start of your CI pipeline. For GitHub Actions, use an early job step that checks the branch name against a regex pattern and fails the workflow if it does not match. This catches names that are technically valid according to Git but violate your team's convention — branch names without a type prefix, names that are too long, or names without a ticket reference. The Branch Name Convention Validator applies this same logic locally in your browser, useful for checking a name before you create the branch.

  • Validate locally before creating: Use the Branch Name Convention Validator to check names against both Git rules and team conventions.
  • Use a branch creation script: A small shell function that takes a ticket ID and description and produces a correctly-formatted branch name eliminates manual naming errors entirely.
  • Add a pre-push hook: Validates the branch name on every push — the last defensive line before an invalid name reaches the remote.
  • Lint in CI: A GitHub Actions or GitLab CI step that validates the branch name on every PR prevents convention violations from being merged.
  • Document the convention in CONTRIBUTING.md: Team members who know the rules make fewer mistakes than those guessing from examples.

Tip

When constructing branch names from external data (ticket titles, commit messages, or API responses), always sanitise before using. A reliable pattern: lowercase the string, replace any sequence of non-alphanumeric characters with a single hyphen, strip leading and trailing hyphens, and truncate to 72 characters. The result is always a valid Git branch name and follows the most common team conventions.

Key takeaways

  • Git validates branch names against its refname spec and immediately rejects names containing spaces, `..`, `~`, `^`, `:`, `?`, `*`, `[`, `\`, `@{`, or names starting/ending with a dot or starting with a hyphen.
  • The most common cause is copying a ticket title with spaces directly into a `git checkout -b` command — replace spaces with hyphens before using any title as a branch name.
  • Use `git check-ref-format --branch name` on the command line to test a name, or the Branch Name Convention Validator in the browser.
  • To rename an existing branch: `git branch -m old-name new-name` locally, then push the new name and delete the old remote branch with `git push origin --delete old-name`.
  • Platform rules extend Git's baseline: GitHub and GitLab reject `.lock` at any path component, and Windows NTFS makes branch names case-insensitive — always use lowercase to avoid cross-platform collisions.
  • Prevent errors systematically with a pre-push Git hook, a CI pipeline validation step, and a documented branch naming convention in your repository.
  • The safest cross-platform convention: `type/lowercase-with-hyphens` (e.g. `feat/add-login-form`, `fix/null-pointer-auth`).

Frequently Asked Questions

Git validates branch names against its refname specification and rejects any name containing forbidden characters or patterns. The most common triggers are spaces in the branch name, double dots (..), a tilde (~), a caret (^), a colon (:), a question mark (?), an asterisk (*), a backslash (\), or a name that starts or ends with a dot or slash. The error also fires if the name ends with .lock — a suffix Git reserves for lock files.

No. Spaces are explicitly forbidden in Git branch names. Git uses spaces as delimiters in many command outputs and cannot reliably disambiguate a branch name containing a space from two separate arguments. The standard replacement is a hyphen — `feature/user-profile` instead of `feature/user profile`. Underscores also work but hyphens are more widely adopted in open-source conventions. If your CI or CD platform has additional restrictions, check its documentation alongside Git's own refname rules.

Git allows letters (a–z, A–Z), digits (0–9), hyphens (-), underscores (_), forward slashes (/) for hierarchical namespaces (e.g. feature/login), and dots (.) within the name but not at the start or end. Most other characters are either forbidden or context-dependent. The safest convention is `lowercase-with-hyphens` or `type/lowercase-with-hyphens` (e.g. `feat/add-login-form`). Validate any unconventional branch name with the Branch Name Convention Validator before creating it.

Use `git branch -m old-name new-name` to rename a local branch. If the branch is already pushed to a remote, rename locally first, then push the new name with `git push origin new-name` and delete the old remote branch with `git push origin --delete old-name`. On GitHub, GitLab, and Bitbucket, you can also rename branches through the web UI — useful if the remote branch name itself contains characters that make CLI deletion awkward.

Older Git versions (before 2.x) had less strict local name validation and would sometimes allow creating a branch locally that was then rejected by the remote. Modern Git validates refnames at creation time, but edge cases can occur when names are constructed programmatically or passed through shell interpolation. Remote hosts like GitHub also apply additional restrictions (no consecutive dots, no names ending in .lock at any path component) that the local Git client does not enforce.

The combination @{ is forbidden in Git branch names because it is the syntax for the reflog shorthand — `branch@{n}` refers to the nth entry in a branch's reflog. Allowing @{ in a branch name would create an ambiguity between the branch itself and a reflog reference. This restriction is often encountered when developers try to use ticket IDs or timestamps that include the @ symbol followed by a brace in a branch name. Replace @ with a hyphen or remove it entirely.

Git itself is case-sensitive on Linux and macOS but case-insensitive on Windows filesystems, which means `Feature/Login` and `feature/login` are the same branch on Windows but different branches on Linux. Using lowercase throughout prevents confusing case-collision bugs when teams work across different operating systems. Most popular conventions (Gitflow, GitHub Flow, Trunk-Based Development) specify lowercase branch names, and most CI systems enforce it as a linting rule.

Git does not impose a hard character limit on branch names from the specification side, but practical limits exist. The underlying filesystem has path length constraints — on Windows, the default maximum path length is 260 characters, which includes the .git directory path and the refs/heads/ prefix. Long branch names also become impractical to type and read. Most teams enforce a soft limit of 50–72 characters as a convention. The Branch Name Convention Validator checks your name against both Git rules and configurable length limits.

ShareXLinkedIn

Related articles