git checkout: одна команда с тремя ролями

Обновлено 31 июля 2026 г.

git checkout делает три разные вещи: переключает ветки, достаёт файлы из коммита и ставит тебя прямо на коммит без ветки. Одно имя на три несвязанные задачи, отсюда и путаница вокруг него.

В git 2.23 (2019) роли развели по двум командам с говорящими именами: git switch ходит по веткам, git restore восстанавливает файлы. Сам checkout оставили, он работает как работал и никуда не денется. Но ответы на форумах, старые статьи и внутренние инструкции написаны через него, так что разбирать его придётся ещё долго.

Роль первая: ветки

$ git checkout feature-x
Switched to branch 'feature-x'

$ git checkout -b feature-x
Switched to a new branch 'feature-x'

Сегодня то же самое пишут как git switch feature-x и git switch -c feature-x. Вывод одинаковый, отличается только имя команды.

Роль вторая: файлы

git checkout -- report.txt возвращает файл к тому виду, который лежит в индексе (staging area); если ты ничего в индекс не клал, это вид из последнего коммита. git checkout HEAD~1 -- report.txt достаёт версию из предпоследнего коммита и заодно кладёт её в индекс. Современная запись - git restore report.txt и git restore --source=HEAD~1 report.txt, причём вторая правит только файл и индекс не трогает.

Здесь стоит притормозить. Это самая опасная форма команды:

$ git checkout -- report.txt
$ git status
On branch main
nothing to commit, working tree clean

Ни вопроса, ни списка того, что уехало. Правки, которых git ни разу не видел, восстанавливать неоткуда: их нет ни в коммите, ни в индексе, ни в git stash. Перед такой командой полезно глянуть git diff.

Роль третья: коммит без ветки

$ git checkout 610d731
Note: switching to '610d731'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

Это detached HEAD: HEAD смотрит на коммит напрямую, минуя имя ветки. Явная новая запись того же - git switch --detach 610d731, а вернуться обратно можно через git switch -.

Частые ошибки

Имя ветки и имя файла легко перепутать местами. Если в репозитории есть и ветка report.txt, и файл report.txt, то git checkout report.txt молча переключит ветку, а не тронет файл. Два дефиса решают спор: всё, что стоит после --, git считает именем файла.

Файл, которого нет ни в одном коммите, вернуть нечем: error: pathspec 'notes.txt' did not match any file(s) known to git. Проверь имя и то, что файл вообще попадал в историю.

Где это в учебнике

Глава 5. Ветки: параллельные версии проекта