使用最新的git(2.1.0.24
),每当我尝试git rebase -i
到squash
某些提交时,壁球就不能detach HEAD
状态。我希望它可以压缩提交并按照我的预期把我放回我的分支。没有未暂存的文件,工作树中的更改或存储中的任何内容。为什么要这样做?
> [master] » git rebase -i HEAD~3
(我压制了一些提交)......
pick c9e9b62 Fixes super important bug #123.
squash c0dc9f9 wip
pick 5385a37 wip2
# Rebase fb83e59..5385a37 onto fb83e59
(然后它给了我)
Note: checking out 'c9e9b62'.
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 performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at c9e9b62... Fixes super-important bug #123.
could not detach HEAD
它似乎成功改变了,但由于某种原因不能让我回到分支机构。
> [c9e9b62] » git rebase --continue
No rebase in progress?
在rebase尝试之前的git graph log:
* 5385a37 (HEAD, master) wip2
* c0dc9f9 wip
* c9e9b62 Fixes super-important bug #123.
* ff80ed9 random commit msg
* 1f407d5 random commit msg
...
* ef106db random commit msg
* 6c244ef Merge branch 'sentences'
|\
| * a641cbf (origin/sentences) random commit msg
| * bfe8eae random commit msg
| ...
在rebase尝试之后git graph log:
* c9e9b62 (HEAD) Fixes super-important bug #123.
* ff80ed9 random commit msg
* 1f407d5 random commit msg
...
* ef106db random commit msg
* 6c244ef Merge branch 'sentences'
|\
| * a641cbf (origin/sentences) random commit msg
| * bfe8eae random commit msg
| ...
答案 0 :(得分:10)
消息could not detach HEAD
来自交互式rebase脚本,特别是在这里:
GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
output git checkout $onto || die_abort "could not detach HEAD"
git update-ref ORIG_HEAD $orig_head
do_rest
这里的好奇部分是git checkout $onto
步骤似乎已成功:在失败之前,你得到了:
HEAD is now at c9e9b62... Fixes super-important bug #123.
作为输出,来自此处发生的git checkout
。然后,在显然成功之后,git checkout
显然已经退出非零,好像它已经失败了。这调用die_abort
终止了rebase尝试。
现在,结帐后挂钩的documentation claims
不能影响 git checkout 的结果。
但是,在来源中,靠近switch_branches
的底部,我们有:
ret = post_checkout_hook(old.commit, new->commit, 1);
free(path_to_free);
return ret || writeout_error;
其中post_checkout_hook
运行post-checkout挂钩并获取其退出代码。所以git checkout
似乎有两种方法可以在这里返回失败状态:写入树时出错(例如,磁盘已经填满),或者你有一个post-checkout挂钩,它正在退出非-零。后者似乎更有可能。 (并且,我对此进行了测试,实际上它确实导致结帐“失败”。由于源使用||
,因此钩子中的任何非零退出都会变为git checkout
本身的退出状态1。 )
你有结账后挂钩吗?如果是这样,它会做什么?
(目前还不清楚哪个是错误的,文档或git checkout
命令,但至少有一个是错误的。我可能会说文档,应该说更像“不能影响文件git checkout
将写入,但可以使命令本身返回失败状态“。)
答案 1 :(得分:0)
正如之前的评论所暗示的那样,也许你有一个后检验钩子,它正在进行非零退出。我有一个基于if开关的最后一个命令可能有不同的退出:
if false
command-that-exits-with 0
else
command-that-exists-with 5
# hook will exit with 5
end
# EOF
即使条件不满意我的剧本仍然很开心。事实上:
$ .git/hooks/post-checkout
doing stuff!
$ echo $?
5
我在剧本的末尾添加了exit 0
,等等。
答案 2 :(得分:0)
另一个可能的原因是,如果在提交中移动会产生一些不一致...例如。假设你有:
HASH2 change line in file b
HASH1 rename file a to b
当然HASH1
是最老的。如果您尝试在HASH1之前移动HASH2,您将获得could not detach HEAD
。
当然这里看起来很明显,但是在更长的现实生活中,多个提交和南瓜被重新定位,你可能会忽略这种不一致的情况!!
答案 3 :(得分:0)
如果还修改了marked assume-unchanged
or skip-worktree
的文件,也会发生这种情况:
git status
中看到更改。git rebase
为您自动存储所有更改,但似乎无法处理这些更改(从Git 2.21开始,在后续发行说明中没有提及更改)。如果您想确认,可以list such files,但是错误消息应该已经使您警惕某些奇怪的事情,因为它将显示git status
中未出现的文件名。