使用git merge解决冲突的单独提交

19

我想将一个大的专题分支合并到主分支,但我希望有一个单独的提交显示冲突解决的方式。目标是有一个提交显示“这些文件发生了冲突以及它们是如何冲突的”,下一个提交将显示“这些冲突是如何被解决的”。也就是说,“第一个提交将包含冲突标记”。

这样做的原因是,大的专题分支已经经过了审查和测试,主分支也经过了同样的步骤。在合并中,我们只想审查那些需要工作(冲突和其他合并工作)的部分。

到目前为止,我正在进行以下操作:

git checkout master
git checkout -b merge-from-topic
git merge topic

为了记录有冲突的文件,我使用一个临时文件:

git diff --name-only --diff-filter=U >conflicts.txt

首先,我会将那些带有冲突标记的文件添加到一个提交中:

xargs git add <conflicts.txt
git commit

然后我创建了另一个分支(用于审查目的),我想在其中进行冲突解决:

git checkout -b resolve-merge-from-topic

为了解决冲突,我尝试了

xargs git reset HEAD^ -- <conflicts.txt

然而,git mergetool 告诉我没有文件需要合并,尽管我的工作树中的文件有冲突标记。

我该如何恢复在 conflicts.txt 中列出的文件,以便可以在它们上面使用 git mergetool

我也愿意尝试其他方法来达到“冲突解决的单独提交”效果。


4
提醒我不要参与你的项目。合并提交本身应该足以证明必须进行的微调。如果你需要比git log -p所示更多的内容,你可以随时使用git diff sha_of_merge sha_of_merge^1git diff sha_of_merge sha_of_merge^2来查看相对于合并的两个父提交所引入的更改。换句话说,要使用git提供给你的工具,不要在你的仓库中添加不必要和有问题的东西。 - twalberg
2
我正在尝试“使用git提供的工具”,即mergetool。但似乎不可能。所有关于带选项的git日志的建议都需要评审人员进行侦查工作。 - vmj
可能git show #mergeCommit是答案,我在这里学到的https://haacked.com/archive/2014/02/21/reviewing-merge-commits/ 基本上它应该能够仅显示未包含在合并提交(源分支和目标分支)的任何“父”提交中的更改。 这基本上是冲突解决更改(hunks)。 我知道这不完全是您要求的内容,但也许目标是相同的 - 能够审查合并提交。 - LordMsz
3个回答

3

git merge会留下冲突标记。

通常情况下,您需要调用git mergetool(使用您喜欢的--tool)来解决冲突。大多数情况下,这将导致已暂存的更改您需要更改此内容(例如使用git reset)。

现在独立提交原始合并内容,并随后使用git add . && git commit -m 'resolutions'git commit -am 'resolutions'添加冲突解决方案。

请注意,这会使您在合并边界修订版本处得到“错误”的构建。

步骤如下:

git checkout -b be_merged       # start a temp branch for the merge (safety)

git merge --no-commit diverge   # initiate merge from a diverged branch
git status                      # shows conflicts
git mergetool                   # resolve them as always
git status                      # shows resolutions as staged
git reset                       # unstage the changes
git status                      # shows unstaged changes (good!)
git commit -m 'merge, conflicts pending'   # commit the merge
git commit -am 'conflicts resolved'        # commit the resolutions

2
对我来说似乎不起作用。在执行 'git reset' 后,所有修改过的文件都未被暂存,所有添加的文件都未被跟踪,因此接下来的 'git commit' 没有任何效果。最后的 'git commit -a' 只提交了修改过的文件,在提交中没有冲突标记的迹象,所有新文件都未被跟踪。 - vmj
顺便说一下,“破损”的构建是可以的。 - vmj
已更新问题以澄清,我实际上想要第一个提交中的冲突标记。 - vmj
如果第一次提交失败,因为没有要提交的内容,请添加--allow-empty来记录合并,但不做任何更改。 - Boyd Stephen Smith Jr.
--allow-empty这个参数可以规避这个问题,第一个提交应包含所有由“git merge”完成的工作,包括冲突标记。问题是关于恢复git-mergetool所需状态的。 - vmj

2
如果你真的坚持要获取合并历史记录,那么最好的方法是使用git-imerge。
据我所知,git imerge会给你一个选择,是否保留合并历史记录。
参考文献:
  1. http://softwareswirl.blogspot.de/2013/05/git-imerge-practical-introduction.html
作者博客中的一段摘录:
“git merge” 的痛苦
- 你需要解决一个大冲突,其中混杂了许多小更改。 (解决大冲突很难!) - 合并是全有或全无的: - 没有办法保存部分完成的合并,因此 - 你不能记录进度。 - 你不能暂时切换到另一个分支。 - 如果你犯了一个错误,你不能撤销部分合并。 - 如果你无法解决整个冲突,那么只能重新开始。 - 没有办法测试部分完成的合并——直到完全解决冲突代码才能构建。 - 与同事合作进行合并很困难。
这可能正是为什么你需要首先进行冲突提交的原因。
另一方面,不同的观点是:
在一个无关紧要的项目中,合并更改应尽可能保持最小化。之所以这样说是因为合并涉及到仓库中所有文件将会让你在未来遇到很大的问题。比如说,如果你正在生产分支上工作,而发布是从发布分支上进行的,当你需要将自己的分支与主分支合并时,分支维护者会试图将你的分支与他的分支合并。
现在,如果你的提交涉及到了所有文件,这将是非常糟糕的事情,因为合并很可能会有冲突(可能是你所做的冲突提交),所以维护者将有两个选择:
1. 自己合并 2. 拒绝合并,让你自己解决
很可能维护者会选择后者,因为这对他来说更容易。
因此,你将花费更多的时间来解决冲突,而不是做一些有生产价值的工作。
注意:
第二个观点仅适用于具有简单跨度的特征主题。当合并跨度较大的特征主题时,最好使用imerge并保留历史记录,这样您将拥有更小的提交,并且rebase将不会很痛苦。

这并没有提供问题的答案。如果要批评或请求作者澄清,请在他们的文章下留言。 - René Höhle
@Stony 抱歉之前回答不完整,我已经更新了更好的答案。 - Avinash R

1
这是一个非常糟糕的想法。您始终希望拥有稳定的代码库。为什么会将代码推送到冲突状态下呢?
如果您想查看如何解决冲突,请对文件进行差异比较并查看其历史记录。

1
我希望主分支中的代码库是稳定的,没错。但其他分支并不那么重要。 - vmj
6
通常,在解决冲突后提交合并时,Git 历史记录不会显示冲突的位置。因此,diff 只显示整个更改,而不是显示冲突。 - vmj
更新问题以(希望)澄清为什么我容忍合并分支中的构建错误。 - vmj
1
@vmj 你可以使用 -c--cc-m 选项之一来获取有关合并提交的不同/更好信息,例如 git log -pgit help log 可以提供更多信息。 - twalberg
2
那为什么不进行合并呢?将你的东西存储起来,创建一个名为“broken”的新分支。弹出你的存储,提交它,推送到主分支。永远不要进行合并。 - AntoineDeSaintExupery
主分支和话题分支在任何状态下都不应该被破坏,只有从话题分支合并后才会被破坏,在第二次提交后就不会被破坏了。第二次提交将是主分支下一个合并提交的父提交。 - vmj

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