TL; DR: видимо, вам придется обманывать. Я не рекомендую делать это, но покажу, как это будет работать, ниже.
В последней проверке я не могу переключиться с 4.1 на 4.1.1, возможно, потому что HEAD уже находится в коммите ...
Более или менее, да. Точнее сказать, что «переключение» с 4.1 на 4.1.1 вообще ничего не переключает, потому что 4.1 и 4.1.1 - это один и тот же коммит. Git использует ярлык и вообще ничего не пишет, потому что ничего не нужно писать. Ну, это, кроме:
есть ли какой-то способ принудительно "отключить HEAD в N", в отличие от проверки основной ветви в этом случае, а затем проверки тега.
«Отсоединение в / от», о котором сообщает git status
, основано на следе из крошки, оставленном позади в HEAD
reflog . Когда вы запускаете git checkout <em>X</em>
для некоторых X и обновлений Git HEAD
, Git сначала сохраняет текущее значение HEAD
в reflog для HEAD
вместе с комментарием , такой как этот:
8858448bb4 HEAD@{0}: checkout: moving from pu to master
(pu
- это ветвь "предлагаемого обновления" или "раскладки" в репозитории Git для самого Git, поэтому приведенная выше запись является результатом того, что я сделал git checkout pu
, который создал pu
из origin/pu
и дал ему значение 8265814db9543fbaf50c4db8133671ce64dc1ae4
, а затем git checkout master
. Движение от мастера к вновь созданному pu
сделало HEAD@{1}
, чей комментарий checkout: moving from master to pu
.)
Когда HEAD
отсоединен, git status
делает, чтобы получить root права через reflog для HEAD
, чтобы попытаться найти ветку или тэг, которые вы явно извлекли, прежде чем приступить к выполнению какого-либо коммита, на котором вы сейчас находитесь. , Если фиксация detached-HEAD, в которой вы сейчас находитесь, совпадает со значением этой ветви или имени тега, вы detached at <em>Y</em>
, где Y происходит из комментария. Если коммит с отсоединенной HEAD у вас сейчас не не соответствует (или, возможно, не @{0}
), git status
сообщает detached from <em>Y</em>
вместо detached at <em>Y</em>
.
Так что, если бы вы могли обновить журнал изменений, вы могли бы git status
сообщить о чем-то новом. Очевидный способ сделать это - git update-ref
, но я попробовал это. Вот что случилось. Сначала мы настроим ситуацию:
$ git checkout v2.18.0
[snip]
HEAD is now at 53f9a3e157 Git 2.18
$ git tag haha
$ git checkout haha
HEAD is now at 53f9a3e157 Git 2.18
$ git reflog | head -1
53f9a3e157 HEAD@{0}: checkout: moving from master to v2.18.0
и, конечно, git status
сообщает "отсоединено в v2.18.0". Итак:
$ git update-ref -m "moving from v2.18.0 to haha" HEAD HEAD
$ git reflog | head -1
53f9a3e157 HEAD@{0}: checkout: moving from master to v2.18.0
Увы, git update-ref
также взял ярлык и не удосужился обновить reflog. (Возможно, git checkout haha
действительно вызывал код обновления reflog, но , чтобы воспользовался ярлыком.) Итак, пришло время обманывать - обратите внимание, что я не советую, чтобы кто-то действительно делал this! - зная, что обновление журнала HEAD просто добавляет строку к .git/logs/HEAD
:
$ ed .git/logs/HEAD
16108
$t$
$s/from master to v2.18.0/from v2.18.0 to haha/
w
16281
q
$ git reflog | head -2
53f9a3e157 HEAD@{0}: checkout: moving from v2.18.0 to haha
53f9a3e157 HEAD@{1}: checkout: moving from master to v2.18.0
$ git status
HEAD detached at haha
nothing to commit, working tree clean
Команда $t$
дублировала последнюю строку; затем $s/from master to v2.18.0/from v2.18.0 to haha/
заменил комментарий новым комментарием. Итак, теперь git status
сообщает, о чем мы хотим сообщить.
Совершенно очевидно, что ошибка git update-ref
закорачивает обновление. Это также может быть важной или полезной оптимизацией, но если это так, должен быть какой-то флаг, чтобы включить оптимизацию или принудительно обновить обновление, основываясь на том, какой параметр по умолчанию считается более важным. Ошибка не будет иметь значения, за исключением всего этого git status
полагается на reflog вещь.