如何解决由于在分支中删除文件而引起的合并冲突?

286

我创建了一个名为dialog的分支,现在当我试图将其与master分支合并时,发生了两个冲突。我不知道如何解决CONFLICT(delete/modify)。你能告诉我该怎么做吗?

$ git checkout master
$ git merge dialog
CONFLICT (delete/modify): res/layout/dialog_item.xml deleted in dialog and modified in HEAD. Version HEAD of res/layout/dialog_item.xml left in tree.
Auto-merging src/com/DialogAdapter.java
CONFLICT (content): Merge conflict in src/DialogAdapter.java
Automatic merge failed; fix conflicts and then commit the result.

我已经打开了src/DialogAdapter.java,解决了冲突,并执行了git add src/DialogAdapter.java。还需要做什么?


您可以在 Stack Overflow 上阅读此帖子:- 如何解决 Git 中的合并冲突? 接受的答案引用了 git 手册 - heavyd
5个回答

357

冲突信息:

CONFLICT (delete/modify): res/layout/dialog_item.xml在"dialog"分支中被删除,并且在你将要合并到的HEAD分支中被修改

这意味着res/layout/dialog_item.xml文件在你正在合并的“dialog”分支中被删除,但是在HEAD分支(即你要合并到的分支)中被修改。

所以你需要决定是否:

  • 使用 "git rm res/layout/dialog_item.xml" 命令删除该文件

或者

  • 接受HEAD的版本(也许需要编辑),使用 "git add res/layout/dialog_item.xml" 命令添加该文件

然后用 "git commit" 命令完成合并。

请注意,Git会警告你正在创建一个合并提交,如果这不是你想要的(罕见情况),可以取消操作。这可能是过去情况较少时的遗留问题。


27
尝试了前者('git rm…'),但是出现了“需要合并”和“rm '...'”等信息,我很难理解。如果我尝试提交,就会再次出现https://dev59.com/NnnZa4cB1Zd3GeqPmiYX。 - Jesse Glick
18
不用管那条评论的后半部分。Git 的输出看起来有点令人担忧,但似乎是无害的。 - Jesse Glick
5
有没有一种批量的方法?我手头有一个项目,它依赖于我不想保留的外部内容。因此,有许多文件在上游被修改了,而我想无论如何都要在我的分支中将它们删除,这样我才能进行变基操作。一个一个地删除非常繁琐。 - mlt
2
@mit:你可以使用 git ls-files --stage 和/或 git status --porcelain 和/或 git diff-files <something> 来获取更改文件的列表,并编写脚本来删除它们或接受你的或他们的版本。 - Jakub Narębski
1
@Honey:CONFLICT消息包括哪个分支上的哪个更改的描述。您可以稍后使用git statusgit diff --cc进行检查。还有git log --merge可能会有所帮助... - Jakub Narębski
显示剩余3条评论

112

我通常只运行git mergetool,它会提示我是保留已修改的文件还是删除它。在我看来,这是最快的方法,因为它只需要一条命令而不是每个文件都需要多次操作。

如果你有许多被删除的文件在一个特定的子目录中,并且你想通过删除这些文件来解决所有问题,你可以这样做:

yes d | git mergetool -- the/subdirectory

当你运行mergetool时,会出现提示信息,其中提供了选项d来选择删除每个文件,你也可以使用m来保留修改后的文件。

Use (m)odified or (d)eleted file, or (a)bort?

2
我尝试过这个,但是出现了“此消息显示是因为未配置'merge.tool'”的错误。添加-t emerge参数(稍后运行git config --global merge.tool emerge)解决了我的问题。 - Steve Almond
@SteveAlmond 您说得对。我的回答假设合并工具已经配置好了,但并不是每个人都这样做。感谢您补充背景信息。 - void.pointer

12

如果您在Windows上使用Git Gui,

  1. 中止合并操作
  2. 确保您位于目标分支上
  3. 从资源管理器中删除冲突文件
  4. 在Git Gui中重新扫描更改(F5)
  5. 注意到冲突文件已被删除
  6. 从提交菜单中选择【Stage Changed Files To Commit】(Ctrl-I)
  7. 输入类似于“删除冲突文件”的提交注释
  8. 进行提交 (ctrl-enter)
  9. 现在,如果您重新启动合并操作,它应该会(希望如此)正常工作。

1
我遇到了类似的问题,但在我的情况下,这是一个我既不拥有也没有写入权限的项目上的拉取请求。以下步骤可能会有所帮助:
  1. 将冲突的文件添加到本地。(res/layout/dialog_item.xml
  2. 删除这些文件的全部内容,然后提交并推送它们。
  3. 冲突警告将弹出,通过接受空文件来解决冲突。
  4. 从本地删除这些文件(dialog),然后推送到远程(master)(git rm path)。 现在,您将看到冲突已解决。

我很想知道为什么这个有效,但它确实有效哈哈 - undefined
发生在我身上,基本上解决方法是一样的:
  1. 创建/添加了一个本地冲突的文件,为空。
  2. 提交/推送该文件。
  3. 变基并接受他们的更改(基本上获取远程的内容)。
  4. 强制推送。
  5. 删除文件。
  6. 提交/推送。
然后它就起作用了。
- undefined

1
您有2个冲突:
  • res/layout/dialog_item.xml在一个分支中被更改,而在另一个分支中被删除
  • src/DialogAdapter.java在两个分支中都有更改
第二个冲突您已经解决了。剩下的是决定是要删除res/layout/dialog_item.xml还是保留它。如果选择删除,则使用git rm命令。如果要保留,则使用git add命令。然后执行git commit
要重现此冲突,请执行以下操作:
mkdir a
cd a
git init
echo a > a && echo b > b && git add . && git commit -m c1
git checkout -b f
echo af > a && rm b && git add -A && git commit -m cf
git checkout master
echo am > a && echo bm > b && git add -A && git commit -m cm
git merge f || true

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