在 git 变基冲突中找不到 `HEAD`?

Can't find `HEAD` in git rebase conflict?

我正在尝试变基以压缩提交,但我遇到了冲突:

<username>:~/path/to/director$git rebase -i HEAD~6
error: could not apply 0111a7a... <commit message>

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Could not apply 0111a7acsadd9a9d98a9003a560a390a50a22afa3af546f42101... <full commit message>

然后,我执行以下操作来查找冲突:

find . -name "*.py" -exec egrep ".*HEAD.*" {} \;

因为我知道我只更改了 python 个文件,所以我使用 *.py 通配符。然而,没有结果显示!有没有办法准确找到问题所在?

git statusgit diff 都是干净的。

通常 git status 应该向您显示一个冲突的文件。您不应该搜索 HEAD,而应该搜索 <<<<<<======>>>>>>.

既然你说 git status 是干净的,那么你的提交可能已经变空了。您可以使用

检查提交中的内容
git show 0111a7a

如果你的提交已经变成空的,你应该跳过它,使用

git rebase --skip

在回答下面的问题之前,我想说明一件事:如果您只想将一系列提交压缩成一个提交,最简单的方法通常就是将 git reset --soft 与单个所需的提交结合起来.请参阅 this answer by Chris Johnsen and this answer by VonC,并注意 VonC 的最后一段要点。


我们无法确定发生了什么,因为您没有向我们展示足够的信息,但这是一个常见的场景,其中 git rebase 告诉您它无法应用某些提交,但也有git status 未显示任何修改。这与您的情况不一样(您将自己的提交变基到自己的 HEAD~6,这使得这种可能性降低),但我们还是看得不够多来自您的信息,所以我将此作为示例。

假设您正在对一系列两个或多个提交进行变基。第一个修复文本文件第 3 行单词 word 的拼写。第二次和任何后续提交对其他文件进行其他操作。这些更改是在分支 bran 上进行的,但从那时起您 运行 git fetch and/or 决定将它们移动到分支 master 或其他任何地方。

与此同时,有人 修复了该文本文件第 3 行 word 一词的拼写,以及 word 一词的拼写 spelling 在第 12 行。因此,您的修复是他们修复的一个子集。这不是 完全相同的 修正——你只修正了一个词,他们修正了两个——但是你的修正不能应用,因为词 word 已经在文本文件。

Git 不能1 明白这个就OK了。由您决定是否不再需要您的修复,虽然它与您正在重新定位的 "upstream" 修复不同。 在这种情况下(但在其他情况下则不然)您应该跳过提交。

这是发生这种情况的示例会话:

$ * abda13a (master) fix two words
| * 9e7ed64 (HEAD, bran) add a file
| * 144d5a6 fix one word
|/  
* ac7be27 initial

让我们看一下提交 144d5a6:

$ git show bran^
commit 144d5a66949cdd40fd92b0846d5b0ce00ebcdd8c
Author: [redacted]
Date:   [redacted]

    fix one word

diff --git a/README.txt b/README.txt
index c37e4c4..983e649 100644
--- a/README.txt
+++ b/README.txt
@@ -1,6 +1,6 @@
 This readme file
 has at least one
-wurd
+word
 that is
 misspelled.
 There may be

现在让我们看一下 master 的最高提交:

$ git show master
commit abda13a47f5b5d968a09eedaf5cc573ba35a3dee
Author: [redacted]
Date:   [redacted]

    fix two words

diff --git a/README.txt b/README.txt
index c37e4c4..867d98f 100644
--- a/README.txt
+++ b/README.txt
@@ -1,6 +1,6 @@
 This readme file
 has at least one
-wurd
+word
 that is
 misspelled.
 There may be
@@ -9,7 +9,7 @@ words, since
 the point of
 this file
 is to allow someone
-to fix the speeling
+to fix the spelling
 of any
 of the misspelled
 words.

现在让我们将当前分支(即 bran)变基到 master,但以交互方式:

$ git rebase -i master
[the editor comes up with both commits selected as `pick`]
[I exit the editor with the same `pick`s]
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

    git commit --allow-empty

Otherwise, please use 'git reset'
rebase in progress; onto abda13a
You are currently rebasing branch 'bran' on 'abda13a'.

nothing to commit, working directory clean
Could not apply 144d5a66949cdd40fd92b0846d5b0ce00ebcdd8c... fix one word

(这是 git 2.3.7,顺便说一句;旧版本甚至没有注意到 cherry-pick 已经变空了,只是抱怨无法应用提交。这不是我很清楚为什么它也建议 git reset;目前没有必要。但是,git 2.3.7 现在已经过时了;我应该升级。)


1这个其实还要看其他的。在 git 2.3.7 中,它现在已经足够智能,可以检测 非交互式 变基的这种情况。使用上面的初始设置:

$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: fix one word
Using index info to reconstruct a base tree...
M   README.txt
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Applying: add a file
$ git log --oneline --graph --decorate --all
* c8f1815 (HEAD, bran) add a file
* abda13a (master) fix two words
* ac7be27 initial

在这种情况下,非交互式 rebase 发现我的 "fix one word" 与 "fix two words" 是多余的并简单地跳过它,因此 bran 上的最终提交顺序是实际上只是剩下的一个提交, "fix two words" 在 master 上作为其父项。