Git rebase: 冲突一直阻碍进展

125

我有一个名为v4的git分支,昨天是从主分支(master)创建的。主分支发生了一些更改,我想将这些更改合并到v4分支中。所以,在v4分支上,我尝试从主分支进行rebase操作,但是有一个文件会导致问题:一个只包含版本号的单行文本文件。这个文件是app/views/common/version.txt,在rebase之前其内容如下:

v1.4-alpha-02

我正在做的事情是:

> git rebase master
First, rewinding head to replay your work on top of it...
Applying: new version, new branch
error: patch failed: app/views/common/version.txt:1
error: app/views/common/version.txt: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging app/views/common/version.txt
CONFLICT (content): Merge conflict in app/views/common/version.txt
Failed to merge in the changes.
Patch failed at 0001 new version, new branch

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

version.txt现在看起来像这样:

<<<<<<< HEAD:app/views/common/version.txt
v1.4-alpha-02
=======
v1.4-alpha-01
>>>>>>> new version, new branch:app/views/common/version.txt

所以,我整理了一下,现在看起来是这样的:

v1.4-alpha-02

然后我尝试继续:首先我尝试提交:

> git commit -a -m "merged"
# Not currently on any branch.
nothing to commit (working directory clean)

没有找到解决方法。所以,我正在尝试添加这个文件:

git add app/views/common/version.txt

没有回应。我猜没有消息就是好消息。所以,我继续尝试:

> git rebase --continue
Applying: new version, new branch
No changes - did you forget to use 'git add'?

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

在这个时候,我已经兜了很多圈子了,头都撞到桌子上了。

这里到底是怎么回事?我哪里做错了吗?有人能给我指点一下吗?

编辑 - 为unutbu

我按照你的建议更改了文件,但仍然遇到了相同的错误:

> git rebase master
First, rewinding head to replay your work on top of it...
Applying: new version, new branch
error: patch failed: app/views/common/version.txt:1
error: app/views/common/version.txt: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging app/views/common/version.txt
CONFLICT (content): Merge conflict in app/views/common/version.txt
Failed to merge in the changes.
Patch failed at 0001 new version, new branch

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

12
谢谢你提出这个问题。我也遇到了完全相同的问题。 - Archan Mishra
6
希望您能确认一些答案,这将是很好的。 - holms
3
@MaxWilliams,我认为你(和我一样)误解了@unutbu的建议:1)首先运行git rebase master 并让它失败_;2)然后编辑version.txt,使它在那一点上看起来应该是这样,并保存编辑;3)接着你执行 git add .../version.txt;4)然后你执行 git rebase --continue(不要'commit'!) 如果rebase --continue在这里成功,它已经被提交了(这里不需要git commit!),所以剩下要做的就是git push(如果你使用远程仓库)。希望这有帮助,如果我理解得对的话:) - 干杯! - sdaau
@MaxWilliams,你是否得到了这个问题的答案:https://www.ruby-forum.com/topic/187288 (如果有人先回答了,我会立即删除这条留言!!) - atw
6个回答

107

我在进行rebase时遇到了类似的问题。我的问题是由于我的一个提交只更改了一个文件,在解决冲突时,我放弃了这个提交引入的更改。我通过跳过相应的提交(git rebase --skip)来解决了我的问题。

你可以在测试库中重现这个问题。首先创建该代码库。

$ mkdir failing-merge
$ cd failing-merge
$ git init
Initialized empty Git repository in $HOME/failing-merge/.git/

然后在主分支中提交version.txt的原始内容。

$ echo v1.4-alpha-02 > version.txt
$ git add version.txt
$ git commit -m initial
[master (root-commit) 2eef0a5] initial
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 version.txt

创建v4分支并更改version.txt的内容。

$ git checkout -b v4
Switched to a new branch 'v4'
$ echo v1.4-alpha-03 > version.txt
$ git add version.txt
$ git commit -m v4
[v4 1ef8c9b] v4
 1 files changed, 1 insertions(+), 1 deletions(-)

回到 master 分支并修改 version.txt 的内容,以便在 rebase 过程中产生冲突。

$ git checkout master
Switched to branch 'master'
$ echo v1.4-alpha-04 > version.txt
$ git add version.txt
$ git commit -m master
[master 7313eb3] master
 1 files changed, 1 insertions(+), 1 deletions(-)

切换回v4分支并尝试rebase。像计划的那样,在version.txt中出现冲突。

$ git checkout v4
Switched to branch 'v4'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: v4
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging version.txt
CONFLICT (content): Merge conflict in version.txt
Recorded preimage for 'version.txt'
Failed to merge in the changes.
Patch failed at 0001 v4

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".
$ cat version.txt
<<<<<<< HEAD
v1.4-alpha-04
=======
v1.4-alpha-03
>>>>>>> v4

我们通过选择version.txt文件的master分支来解决冲突。然后我们将该文件添加到版本库并尝试继续进行变基操作。

$ echo v1.4-alpha-04 > version.txt
$ git add version.txt
$ git rebase --continue 
Applying: v4
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.

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

它失败了!让我们看看 git 认为在我们的仓库中有哪些更改。

$ git status
# Not currently on any branch.
nothing to commit (working directory clean)
啊啊,没有变化。如果您仔细阅读之前的错误信息,git已经告诉我们了并建议使用git rebase --skip。他告诉我们:“如果没有留下任何内容可以暂存,那么很有可能其他东西已经引入了相同的更改;您可能想跳过此补丁。”因此,我们只需跳过提交,重置操作就成功了。
$ git rebase --skip
HEAD is now at 7313eb3 master

警告:请注意,git rebase --skip会完全删除git尝试重演的提交。在我们的情况下,这应该没问题,因为git报告说这是一个空提交。如果您认为在重演完成后丢失了更改,则可以使用git reflog获取重演之前您的存储库的提交ID,并使用git reset --hard将您的存储库还原到那个状态(这是另一个具有破坏性的操作)。


4
感谢你抽出时间写了这篇详细的解释,Sylvain!这让事情更清晰了。我想我一直很担心跳过一个补丁可能会导致工作丢失:也就是说,该补丁涉及到所有受到rebase影响的文件,并非只有发生冲突的那个文件。那么,补丁只是单个文件上的单个合并吗? - Max Williams
3
不,一个patch包含了单个提交中修改的所有文件的差异。但是,当使用git rebase --skip命令时,你只能跳过单个提交。通常在跳过提交之前,我会使用git status来查看是否处于这种情况。 - Sylvain Defresne
1
我只是想回应Max的话,感谢你抽出时间写了一篇很好的解释——我终于明白为什么会发生这种情况了。我也不再害怕“rebase --skip”命令了 :)。 - Ben Dolman
1
警告 - 如果您在一个提交中有多个更改,则在执行git rebase --skip时可能会丢失工作。我刚刚这样做了。 - Chrissy H
除非您执行了 git reflog purgegit reflog delete,否则您仍然可以通过使用 git reflog 获取您的更改。尝试检出其中引用的不同提交,其中一个应该是在您开始整个 git rebase 之前的树状态。 - Sylvain Defresne
@SylvainDefresne,顺便问一下关于“很有可能其他东西已经引入了相同的更改”这句话,这里的“其他东西”具体是什么?这是Git的一个bug吗?(git rebase --skip可以避开这个问题,但并不能解决它。) - Pacerier

23

引自此处:http://wholemeal.co.nz/node/9

啥?!不,我没有忘记使用git add,我刚刚才做了...就在2秒前!

事实证明,由于补丁没有变化,Git怀疑出了问题。Git希望应用补丁,但文件保持不变。

错误消息并不是很直观,但它包含了答案。我们只需要告诉rebase跳过这个补丁。也不需要修复文件中的冲突标记。最终你将得到正在rebase上的分支的文件版本。

$ git rebase --skip

在使用了git mergetool并修复了更改后,我将它们添加并提交了。然后,在“当前未处于任何分支”状态下,我只需输入<code>git rebase --skip</code>,一切都解决了。谢谢! - geerlingguy
实际上,我认为是持续运行git mergetool,然后git rebase --continue,再运行git mergetool等一系列操作最终解决了我的问题。 - geerlingguy

6

将app/views/common/version.txt更改为

v1.4-alpha-01

在这个rebase的阶段,记住你正在解决合并冲突以展示非主分支的进展。

因此,在从中进行rebase时:

      A---B---C topic
     /
D---E---F---G master

为了

              A*--B*--C* topic
             /
D---E---F---G master

你需要解决的冲突是如何在主题分支上创建A*。

因此,在执行 git rebase --abort 命令后,应该执行以下命令:

git checkout topic
git rebase master
< make edits to resolve conflicts >
git add .
git rebase --continue

3
谢谢unutbu,我尝试了但没有成功:请查看原帖中的新编辑。谢谢。 - Max Williams

6
那个错误信息是由于你的git commit -a -m "merged"引起的。如果你只是修复了文件,然后运行git add 和git rebase --continue,那么它应该可以正常工作。git rebase --continue试图进行提交,但发现没有待提交的更改(因为你已经提交了它们)。

1
这似乎比跳过更合理,在一般情况下至少是如此。我很惊讶它没有被列为最佳答案。 - EmeraldD.
1
@EmeraldD.,不起作用。修复文件并运行git add <file>无法解决问题。git rebase --continue仍然报告“没有更改-您是否忘记使用'git add'?” - Pacerier

4

以下是一些想法:

  • 在开始变基之前,请确保您不处于变基或am的中间状态。执行:rm -rf .git/rebase-apply
  • 您提到的一点我不理解:“然后尝试继续:首先我尝试提交:”...为什么要提交? 在变基过程中,我认为您应该只在整理或“git rm”后添加“git add”,以丢弃更改或确认文件删除。也许那搞乱了一些东西?
  • 尝试合并而非变基
  • 尝试Ethan Rowe的一些想法

4

您看到的行为与典型的rebase不符。如果您已经将要快进的提交推送到远程,请考虑使用单独的分支进行此rebase。另外,git mergetool可帮助解决冲突并记得发出git add命令。

在这个最小化的示例中,rebase按预期工作。您能否提供一个展示您所看到行为的示例?

#!/bin/bash

cd /tmp
mkdir rebasetest
cd rebasetest
git init
echo 'v1.0' > version.txt
git add version.txt
git commit -m 'initial commit'
git checkout -b v4
echo 'v1.4-alpha-01' > version.txt
git add version.txt
git commit -m 'created v4'
git checkout master
git merge v4
echo 'v1.4-alpha-01-rc1' > version.txt
git add version.txt
git commit -m 'upped version on master to v1.4-alpha-01-rc1'
git checkout v4
echo 'v1.4-alpha-02' > version.txt
git add version.txt
git commit -m 'starting work on alpha-02'

git rebase master
echo 'v1.4-alpha-02' > version.txt
git add version.txt
git rebase --continue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接