修复冲突后git rebase

时间:2016-12-15 18:48:54

标签: git git-rebase

有时我在重新定位和修复冲突后遇到这个问题。 我做了git add .,我会运行git rebase --continue

但是,我有时会收到此消息

Applying: xxxxxx
No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else  
already introduced the same changes; you might want to skip this patch.

我从未理解为什么会这样。所以,我最后才开始git rebase --skip继续。任何人都可以告诉我为什么Git没有意识到我修复了冲突?

1 个答案:

答案 0 :(得分:3)

并不是说Git没有意识到你已经解决了冲突,因为Git的作者认为这是一个很好的安全设备。

这种情况发生在您正在挑选的提交时 - 记住git rebase是,无论是有效还是实际,只是大量重复的挑选 - 一个不完全相同的变化/ em>,但非常相似,这是您在提交的提交中已经发生的变更。

例如,假设原始工作是这样的:

...--o--*           <-- origin/develop
         \
          A--B--C   <-- develop

此处ABC是您提交的三次提交。提交*是您第一次开始时develop的位置,origin/develop仍会记住它。

在提交A中,您修复了文件a中的内容,并更新了README.txt文件。在B中,您修复了文件b中的内容,但忘记更新README.txt。在提交C中,您记得更新README.txt,以便您这样做。

现在其他人做了更改并将其推送到您的上游服务器,因此您git fetch 他们的工作:

...--o--*--D--E     <-- origin/develop
         \
          A--B--C   <-- develop

然后在新git rebase上继续develop origin/develop。通常, ABC添加到新提交A'B'和{{1}所以,如果一切顺利,你最终会得到:

C'

新的...--o--*--D--E <-- origin/develop \ \ \ A'-B'-C' <-- develop \ A--B--C [abandoned] 提交只是原件的A'-B'-C'份。

Git非常聪明,如果您的提交git cherry-pick引入完全相同的更改同样位于AD,Git将只是 E:它会跳过它并只复制AB。但是假设C&#34;等于&#34; {@ 1}}在这个意义上,或者 - 为了论证而说第二种情况是正确的 - A是完全独立的并且被复制得很好。但是,它不是D 也不是 A&#34;等于&#34; B,而是总和C,&#34;等于&#34; E。也就是说,你和他们做了相同的修复,但他们记得在一次提交中修复了B+C ...并且他们对文件的更改存在一些轻微的拼写错误E - 或者文件README.txt被重新格式化或者其他内容,让Git无法按原样应用您的更改。

当Git试图挑选提交b来制作b时,你手动进入并解决Git抱怨的b问题。然后你B已解决的文件。但现在您的文件B'与上游git add完全匹配。虽然这是有目的的 - 但在所有文件b之后没有任何关系 - Git 并不知道您已经验证了这一点。 Git认为也许你只是跑b看看他们的版本是什么。这将提取他们的 b并假装所有内容都已解决,并在其他情况下保持相同的情况。 1

因此,由于这将完全删除你的提交git checkout HEAD -- b,Git会给你这个警告。如果正确的事情 现在完全放弃您的提交b,那么您应该运行B,然后跳过B

Git现在会尝试应用您的git rebase --skip来修复B。这将无需任何操作,因为他们已经在提交C中执行了此操作。你的Git将再次看到解决后 - 或许甚至自动,这一次 - 冲突,没有什么可以承诺。 Git会怀疑它是否可能出错,并让你运行README.txt以确认这是正确的。

一旦完成,事实证明只需要复制D,并且您实际上最终得到:

git rebase --skip

但Git希望非常确定从复制中省略A...--o--*--D--E <-- origin/develop \ \ \ A' <-- develop \ A--B--C [abandoned] 是正确的,因为它相对容易实现运行B时忘记C

1 如果您意识到Git没有拥有良好的内置git add命令,这可能会更有意义。相反,rebase将提交转换为补丁,然后尝试应用补丁,就好像有人邮寄给你。然后,Git将无法判断您是否忘记了根本不应用补丁。