Ответ 1
Команда checkout
различает два случая (ну, на самом деле "много", но пусть начнутся только с двумя:-)):
- "Я хочу, чтобы я получил ветку & rsquo;; здесь имя ветки": например,
git checkout branch
. - "Я хочу посмотреть на какую-то конкретную ревизию и выйти из любой ветки, вот идентификатор ветки, который не является именем ветки": например,
git checkout 6240c5c
.
(Лично я думаю, что они должны использовать разные имена команд, но это только я. С другой стороны, это устранит всю странность, описанную ниже.)
Теперь скажите, что вы хотите первого. Это проще всего написать, просто набрав имя ветки, без части refs/heads/
.
Если вы хотите последний, вы можете указать ревизию любым из методов, перечисленных в gitrevisions, за исключением любого метода, который приводит к в "попадание на ветку".
По какой-либо причине выбранный здесь алгоритм - он документально подтвержден на странице в разделе <branch>
- это: Если вы написали имя, которое при добавлении refs/heads/
к нему называет ветку, git checkout
поместит вас в эту ветку. Если вы укажете @{-N}
или -
, он будет искать N-ю старшую ветвь в рефлекторе HEAD
(с -
значением @{-1}
). В противном случае он выбирает второй метод, предоставляя вам "отключенную HEAD". Это верно, даже если имя указано в gitrevisions для избежания двусмысленности, т.е. heads/xyz
, когда есть другой xyz
. (Но: вы можете добавить --detach
, чтобы избежать случая "получить на ветке", даже если он в противном случае попал бы в ветвь.)
Это также противоречит разрешающим правилам, перечисленным в документе gitrevisions. Чтобы продемонстрировать это (хотя это трудно увидеть), я сделал тег и ветку с тем же именем, derp2
:
$ git checkout derp2
warning: refname 'derp2' is ambiguous.
Previous HEAD position was ...
Switched to branch 'derp2'
Это помещало меня в ветку, а не отделяя и переходила к помеченной ревизии.
$ git show derp2
warning: refname 'derp2' is ambiguous.
...
Это показало мне помеченную версию, как говорит gitrevisions.
Односторонняя заметка: "получение на ветке" действительно означает "размещение символической ссылки на имя ветки в файл с именем HEAD
в каталоге git". Символическая ссылка - это буквальный текст ref:
(с конечным пространством), за которым следует полное имя ветки, например refs/heads/derp2
. Кажется некорректным, что git checkout
требует имя без части refs/heads/
, чтобы добавить часть ref: refs/heads/
, но git для вас.:-) Для этого может быть какая-то историческая причина: изначально, чтобы быть символической ссылкой, файл HEAD
был фактически символической ссылкой на файл ветки, который всегда был файлом. В наши дни, частично из-за Windows и частично только благодаря эволюции кода, у нее есть эта буквальная строка ref:
, и ссылки могут стать "упакованы" и, следовательно, в любом случае недоступны как отдельный файл.
В противоположном случае "отдельная HEAD" на самом деле означает "помещение необработанного SHA-1 в файл HEAD
". Помимо наличия числового значения в этом файле, git продолжает вести себя так же, как когда "на ветке" : добавление нового коммита все еще работает, а новый фиксатор - текущий коммит. Слияния все равно могут быть выполнены, а родители слияния являются текущими и подлежащими объединению фиксациями. Файл HEAD
обновляется каждым новым фиксатором, как это происходит. 1 В любой момент вы можете создать новую метку ветки или метки, указывающую на текущую фиксацию, чтобы вызвать новую цепочку коммитов сохраняются в будущем сборке мусора даже после отключения "отсоединенной головки"; или вы можете просто отключиться и позволить новым коммитам, если таковые имеются, вытащиться с обычной сборкой мусора. (Обратите внимание, что HEAD
reflog предотвратит это в течение некоторого времени, по умолчанию, по умолчанию, 30 дней.)
[ 1 Если вы "на ветке" , происходит такое же автоматическое обновление, это происходит только с веткой, на которую ссылается HEAD
. То есть, если вы находитесь в ветке B
, и вы добавляете новую фиксацию, HEAD
все еще говорит ref: refs/heads/B
, но теперь код фиксации, который вы получаете с помощью git rev-parse B
, - это новый комманд, который вы только что добавили. Вот как ветки "растут": новые коммиты добавляются, а "на ветке" заставляют ссылку на ветку автоматически двигаться вперед. Аналогично, когда в этом состоянии "отсоединенного HEAD" новые коммиты добавили причину HEAD
для автоматического перемещения вперед.]
Для полноты, здесь может быть список других вещей git checkout
, которые я мог бы добавить в различные отдельные команды, если бы у меня были такие полномочия:
- проверьте конкретную версию некоторого пути (путей), записывая через индекс:
git checkout revspec -- path ...
- создать новую ветку:
git checkout -b newbranch
(плюс опции дляgit branch
) - создайте новую ветку, которая, если и когда вы сделаете фиксацию на ней, будет корневой фиксацией:
git checkout --orphan
(это помещает вас в "ветвь", которая еще не существует, т.е. записываетref: refs/heads/branch-name
вHEAD
, но не создает ветвьbranch-name
, это также означает, чтоmaster
- неродившаяся ветвь в новом репозитории) - создать или воссоздать конфликт слияния или слияния:
git checkout -m ...
- разрешить конфликт слияния, выбирая одну или другую "сторону" слияния:
git checkout --ours
,git checkout --theirs
- интерактивно выбирает патчи между объектами репозитория и файлами дерева работ, аналогичными
git add --patch
:git checkout --patch