git rebase -i与壁球无法分离HEAD

时间:2014-08-29 03:56:22

标签: git git-rebase

使用最新的git(2.1.0.24),每当我尝试git rebase -isquash某些提交时,壁球就不能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
| ...

4 个答案:

答案 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的文件,也会发生这种情况:

  1. 您不会在git status中看到更改。
  2. 您可能习惯于git rebase为您自动存储所有更改,但似乎无法处理这些更改(从Git 2.21开始,在后续发行说明中没有提及更改)。

如果您想确认,可以list such files,但是错误消息应该已经使您警惕某些奇怪的事情,因为它将显示git status中未出现的文件名。