Ошибка Git «is not a valid branch name» точна: предложенное вами имя нарушает одно или несколько правил refname. Исправление почти всегда сводится к правке одной строки, когда известно, какой символ или шаблон её вызвал. Это руководство охватывает полный набор ограничений именования Git, самые частые причины с точными исправлениями, безопасное переименование уже существующей ветки и внедрение валидных имён во всей команде до того, как кто-то столкнётся с ошибкой.
Что означает ошибка
Когда Git сообщает `fatal: 'some-name' is not a valid branch name`, это значит, что переданная строка имени ветки нарушает спецификацию refname Git — набор правил, определяющих, что является допустимым именем ссылки в репозитории Git. Git применяет одни и те же правила к именам веток, тегов и remote-отслеживающих имён, потому что все они хранятся как ссылки в каталоге `.git/refs/`.
Валидация происходит до записи какого-либо объекта. Git прогоняет предложенное имя через `check_refname_format()` внутри и прерывается с ошибкой, если имя не проходит. Значит, вы увидите ошибку сразу при выполнении `git checkout -b`, `git branch` или `git switch -c` — никакого частичного состояния чистить не нужно.
Где возникает ошибка
- `git checkout -b branch-name` - создание новой ветки и переключение на неё
- `git branch branch-name` - создание новой ветки без переключения
- `git switch -c branch-name` - современный эквивалент checkout -b
- `git push origin branch-name` - отправка в remote с невалидным локальным именем
- Скрипты CI/CD - когда имя ветки строится программно из ID задачи или сообщения коммита
Note
Правила именования веток в Git
Спецификация refname Git (описана в man-странице `git-check-ref-format`) определяет точный набор запрещённых символов и шаблонов. Разобрав правила один раз, вы предотвратите все будущие ошибки именования — неоднозначных случаев нет, когда известен полный список.
Явно запрещённые символы и последовательности
- Пробел (ASCII 0x20) - самая частая ошибка; используйте вместо него `-` или `_`.
- Тильда `~` - используется в нотации reflog (`branch~2` означает два коммита до вершины).
- Циркумфлекс `^` - используется в нотации ревизий (`branch^` означает родительский коммит).
- Двоеточие `:` - используется в нотации refspec при fetch (`refs/heads/main:refs/heads/main`).
- Знак вопроса `?` - glob-символ подстановки в шаблонах ref.
- Звёздочка `*` - glob-символ подстановки в шаблонах ref.
- Открывающая скобка `[` - открывает glob-набор символов.
- Обратный слэш `\\` - разделитель путей в Windows; запрещён во избежание кроссплатформенных проблем.
- Двойная точка `..` - используется в нотации диапазонов (`main..feature`).
- Последовательность @{ - сокращённая нотация reflog (`branch@{1}` — запись reflog).
Позиционные и структурные правила
- Не может начинаться с точки (`.`) - конвенция скрытых файлов; `.hidden` — недопустимое начало.
- Не может заканчиваться точкой (`.`) - двусмысленно с расширением `.lock` и нотацией файловых расширений.
- Не может заканчиваться на `.lock` - Git использует суффикс `.lock` для lock-файлов; любой компонент пути, заканчивающийся на `.lock`, запрещён.
- Не может начинаться с дефиса (`-`) - конфликтует с разбором опций командной строки.
- Не может содержать подряд идущие точки (`..`) - конфликт с нотацией диапазонов (см. выше).
- Не может быть единственным символом `@` - сокращение для `HEAD`.
- Не может содержать управляющие символы - ASCII-символы ниже 0x20 и DEL (0x7F) запрещены.
- Не может быть пустым - пустая строка не является валидным именем.
# ✓ 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 nameTip
Частые причины и исправления
Большинство появлений этой ошибки вызвано небольшим числом повторяющихся шаблонов. У каждого есть конкретная причина и конкретное однострочное исправление.
Пробелы из скопированных названий задач
Самый частый триггер — копирование названия задачи или story прямо в имя ветки. «Add user login form» превращается в `git checkout -b Add user login form`, Git видит три отдельных аргумента и отклоняет имя ветки `Add`. Исправление: замените каждый пробел дефисом. Многие команды автоматизируют это алиасом или скриптом `branch-from-ticket`, который преобразует название перед передачей в Git. Генератор slug-ов превращает любой текст в чистый slug с дефисами, пригодный для имён веток.
Спецсимволы в интерполяции переменных CI/CD
CI-пайплайны часто строят имена веток из переменных окружения — заголовков PR, сообщений коммитов или ID задач Jira. Если какое-то из этих значений содержит спецсимвол (двоеточие в ID Jira вроде `PROJECT:123` или слэш в semver-теге вроде `v1.0.0/rc.1`), интерполированное имя ветки провалится. Исправление: очищайте ввод перед использованием в качестве имени ветки. Замените неалфанумерные символы дефисами и уберите дефисы и точки в начале и конце.
Точка в конце или суффикс .lock
Имя ветки, оканчивающееся точкой (`feature.`) или на `.lock` (`release.lock`), отклоняется, потому что Git резервирует эти шаблоны для lock-файлов. Ошибка обычно появляется, когда разработчик случайно ставит точку в конце имени или когда скрипт добавляет `.lock` к сгенерированному имени. Исправление: уберите точку в конце или замените `.lock` валидным суффиксом вроде `-locked` или `-pending`.
| Невалидный шаблон | Пример | Исправление |
|---|---|---|
| Пробел | feature/add login | feature/add-login |
| Двойная точка | feat..login | feat/login |
| Тильда | hotfix~v2 | hotfix-v2 |
| Двоеточие | PROJECT:123 | PROJECT-123 |
| Точка в конце | release. | release |
| Заканчивается на .lock | fix.lock | fix-pending |
| Начинается с дефиса | -bugfix | bugfix |
| @ с последующей { | user@{branch} | user-branch |
| Обратный слэш | feature\\login | feature/login |
Валидатор конвенций имён веток
Проверяйте имена веток Git по полной спецификации refname и конвенции вашей команды — локально в браузере, мгновенная обратная связь, без настройки.
Как переименовать невалидную ветку
В редких случаях — особенно со старыми версиями Git или ветками, созданными сторонними инструментами, — невалидное имя ветки может уже попасть в репозиторий. Современный Git блокирует это при создании, но если вы унаследовали репозиторий с проблемным именем ветки, вот как это исправить.
Переименуйте локальную ветку
Выполните `git branch -m old-name new-name`, чтобы переименовать ветку в локальном репозитории. Флаг `-m` перемещает (переименовывает) ссылку ветки, не затрагивая историю коммитов. Если старое имя содержит символы, усложняющие кавычки в вашей оболочке, возьмите его в одинарные кавычки: `git branch -m 'old name with spaces' new-valid-name`.
Отправьте новое имя в remote
После локального переименования отправьте новую ветку в remote: `git push origin new-valid-name`. Это создаст новую ветку на remote. Если старая ветка уже была отправлена, коллегам следует обновить локальную отслеживающую ссылку через `git fetch --prune` после того, как вы удалите старую remote-ветку.
Удалите старую remote-ветку
Удалите старую remote-ветку: `git push origin --delete old-name`. В GitHub, GitLab и Bitbucket ветки можно переименовать и через веб-интерфейс в списке веток — это безопаснее, когда старое имя содержит символы, которые трудно передать через CLI без экранирования.
Обновите открытые pull request-ы
Если у переименованной ветки были открытые PR, большинство платформ (GitHub, GitLab) автоматически обновляют ссылку базовой ветки PR при переименовании через веб-интерфейс. Если переименовали через CLI, проверьте открытые PR и при необходимости вручную обновите ссылку head-ветки. Запуски CI против старого имени ветки тоже придётся перезапустить с новым именем.
Warning
Правила именования по платформам
Собственные правила refname Git — база. Платформы хостинга накладывают дополнительные ограничения сверху: имя, прошедшее локальную валидацию Git, всё ещё может не пройти при push в GitHub или GitLab. Понимание платформенных правил избавляет от разочарования, когда имя работает локально, но проваливается на remote.
Дополнительные ограничения GitHub
GitHub отклоняет имена веток, оканчивающиеся на `.lock` в любом компоненте пути (не только в последнем сегменте), имена с подряд идущими точками в любой позиции и имена, содержащие нулевой байт. GitHub также ограничивает длину имени ветки 255 байтами. Веб-интерфейс GitHub дополнительно обрезает пробелы в начале и конце имён, созданных через интерфейс.
Дополнительные ограничения GitLab
GitLab добавляет ограничения для шаблонов защищённых веток: имена с подстановочными символами `*` зарезервированы под правила защищённых веток и не могут использоваться как буквальные имена веток. GitLab также резервирует имена, совпадающие с его внутренним namespacing вроде `protected` и `refs`. Имена веток длиннее 255 символов отклоняются. Валидация имён в пайплайне GitLab CI отделена от валидации refname Git — ошибки интерполяции переменных CI проявляются как сбои пайплайна, а не как ошибки Git.
Особенности файловой системы Windows
В Windows каталог `.git/refs/heads/` хранит каждую ветку как файл. Значит, действуют все ограничения имён файлов Windows: имена не могут содержать `<`, `>`, `"`, `|`, `?` или `*`; имена не могут заканчиваться пробелом или точкой; а имена нечувствительны к регистру на NTFS. Нечувствительность к регистру особенно важна в смешанных командах: `Feature/Login` и `feature/login` — одна и та же ветка в Windows, но разные в Linux и macOS.
| Правило | Ядро Git | GitHub | GitLab | Файловая система Windows |
|---|---|---|---|---|
| Без пробелов | ✓ | ✓ | ✓ | ✓ |
| Без суффикса .lock | ✓ | ✓ любой компонент | ✓ | ✓ |
| Без двойных точек | ✓ | ✓ | ✓ | ✓ |
| Без начального дефиса | ✓ | ✓ | ✓ | ✓ |
| Максимум 255 байт | ✗ (без лимита) | ✓ | ✓ | Лимит пути ОС |
| Нечувствительность к регистру | ✗ | ✗ | ✗ | ✓ (NTFS) |
| Без * как буквального имени | ✓ | ✓ | ✓ зарезервировано | N/A |
Командные конвенции именования веток
Валидность — это минимум, а не максимум. Имя ветки может быть валидным по правилам Git и при этом оставаться неясным, непоследовательным или непригодным в рабочем процессе команды. Устоявшиеся конвенции добавляют предсказуемость поверх технической валидности: каждый участник команды может прочитать имя ветки и сразу понять её цель, охват и жизненный цикл.
Конвенция Gitflow
Gitflow использует пять типов веток: `main` (продакшен), `develop` (интеграция), `feature/описание`, `release/версия` и `hotfix/описание`. Имена веток строятся из категории-префикса, слэша и описания с дефисами. Release-ветки включают номер версии (`release/1.4.0`). Эту конвенцию хорошо поддерживают большинство GUI-клиентов Git и CI-инструменты, распознающие префиксы как категории веток.
GitHub Flow и trunk-based конвенции
GitHub Flow использует более простую структуру: `main` плюс короткоживущие feature-ветки с описательными именами (`add-oauth-login`, `fix-pagination-bug`). Trunk-based-разработка аналогично использует `main` плюс очень короткоживущие ветки, мержащиеся за часы. Оба подхода предпочитают короткие имена в нижнем регистре с дефисами без категорийных префиксов — предполагается, что имена веток временные, а контекст несут заголовок и описание PR.
Конвенции с ссылкой на задачу
Многие команды добавляют в имя ветки ссылку на задачу: `JIRA-1234-fix-login-bug` или `feat/GH-456-add-dark-mode`. ID задачи обеспечивает трассируемость между веткой и исходным рабочим элементом. Строя такие имена программно, всегда очищайте часть с описанием задачи — в названиях задач часто встречаются двоеточия, слэши и другие символы, ломающие правила именования Git.
Имена веток, как и сообщения коммитов, — это документация. Последовательная конвенция именования превращает список веток в читаемый changelog текущей работы.
Профилактика невалидных имён веток
Исправление отдельных ошибок — реактивный подход. Лучше предотвращать создание невалидных имён изначально: через инструменты валидации, интеграции с редакторами и CI-проверки, отлавливающие проблемы до того, как они помешают команде.
Pre-push-хуки Git
Скрипт `.git/hooks/pre-push` выполняется перед любым `git push` и может проверить текущее имя ветки по конвенции команды. Если имя не проходит, хук завершается ненулевым кодом и прерывает push с пояснительным сообщением. Используйте фреймворк `pre-commit`, чтобы равномерно распространять хуки по команде: отдельные файлы `.git/hooks/` не коммитятся в репозиторий, а `.pre-commit-config.yaml` — коммитится.
Валидация имён в CI-пайплайне
Добавьте шаг валидации имени ветки в начало CI-пайплайна. В GitHub Actions используйте ранний шаг job-а, проверяющий имя ветки по regex-шаблону и валиящий workflow при несовпадении. Это ловит имена, технически валидные по Git, но нарушающие конвенцию команды: без типового префикса, слишком длинные или без ссылки на задачу. Валидатор конвенций имён веток применяет ту же логику локально в браузере — удобно проверять имя до создания ветки.
- Валидируйте локально до создания: используйте Валидатор конвенций имён веток, чтобы проверять имена по правилам Git и командным конвенциям.
- Используйте скрипт создания веток: небольшая shell-функция, принимающая ID задачи и описание и выдающая корректно отформатированное имя ветки, полностью устраняет ручные ошибки именования.
- Добавьте pre-push-хук: проверяет имя ветки при каждом push — последняя линия обороны до того, как невалидное имя попадёт на remote.
- Линтьте в CI: шаг GitHub Actions или GitLab CI, проверяющий имя ветки в каждом PR, не даёт слиться нарушениям конвенции.
- Документируйте конвенцию в CONTRIBUTING.md: члены команды, знающие правила, ошибаются реже тех, кто угадывает по примерам.
Tip
Key takeaways
- Git проверяет имена веток по спецификации refname и сразу отклоняет имена с пробелами, `..`, `~`, `^`, `:`, `?`, `*`, `[`, `\\`, `@{`, а также имена, начинающиеся/оканчивающиеся точкой или начинающиеся с дефиса.
- Самая частая причина — копирование названия задачи с пробелами прямо в команду `git checkout -b`: заменяйте пробелы дефисами, прежде чем использовать название как имя ветки.
- Проверяйте имя командой `git check-ref-format --branch name` в терминале или через Валидатор конвенций имён веток в браузере.
- Чтобы переименовать существующую ветку: `git branch -m old-name new-name` локально, затем отправьте новое имя и удалите старую remote-ветку командой `git push origin --delete old-name`.
- Правила платформ расширяют базу Git: GitHub и GitLab отклоняют `.lock` в любом компоненте пути, а NTFS в Windows делает имена веток нечувствительными к регистру — всегда используйте нижний регистр, чтобы избежать кроссплатформенных коллизий.
- Предотвращайте ошибки системно: pre-push-хук Git, шаг валидации в CI-пайплайне и задокументированная конвенция именования веток в репозитории.
- Самая безопасная кроссплатформенная конвенция: `тип/нижний-регистр-с-дефисами` (например, `feat/add-login-form`, `fix/null-pointer-auth`).