`git merge`能否将每个更改(相对于一个共同的祖先)显示为合并冲突?

3
假设我们有一个名为common_ancestor (master)的文件。
ok
ok
ok
ok
ok

从那里开始,我们更改并提交master

ok
change not ok (looking back)
ok
ok
ok
latest change
ok

现在我们有了更好的想法,查看 common_ancestor 并将其更改为
ok
ok
ok
This is a really good change
ok
ok

并在一个新分支dev中提交。由于我需要一些来自master的开发,我想将dev合并到master,但我想为每个更改决定是否保留。我尝试过:

git checkout master
git merge dev --no-ff --no-commit

但我没有得到我预期的结果。我正在寻找的是像这样的东西:

ok
<<<<HEAD
change not ok (looking back)
====
>>>> HASH
ok
ok
<<<<HEAD
====
This is a really good change
>>>> HASH
ok
<<<<HEAD
latest change
====
>>>> HASH

在可见冲突标记的地方(请参见此处)。

编辑:我所看到的是,git merge dev --no-ff --no-commit没有突出显示更改 - @VonC解释了为什么没有冲突标记可见(因为没有冲突!)。


也许是 https://dev59.com/DW435IYBdhLWcg3wvy6_ 的重复。 - Dunno
3个回答

2
正如@VonC所指出的,将两个版本之间的差异视为冲突是不正确的。因此他回答了我的问题。为了达到我的目标,我使用了
git difftool -t=kdiff3 dev master

还有其中的合并工具。在kdiff3中,每个差异都会被突出显示,你可以选择想要保留的每行版本。

此外,这里有一个视频教程。


是的,kdiff3在这里很有用。一旦合并完成(但未提交),您可以在任何修改过的文件上使用git diff,并且如果需要,kdiff3将允许您完成合并。 - VonC

2
在您的情况下,将dev合并到master只会简单地执行以下操作:
  • dev中的更改“这是一个非常好的更改”添加到master中。
  • 保留master中引入的更改“change not ok (looking back)”。
这是因为这些更改不是在文件的相同位置进行的:没有在同一行进行的并发修改。这意味着没有冲突。
如果您想在合并之后(但在合并提交之前)查看,请设置自定义合并驱动程序
[merge "verify"]
        name = merge and verify driver
        driver = ./merge-and-verify-driver %A %O %B

你可以在.gitattributes文件中将该驱动程序与你的文件关联起来。
*.R merge=merge and verify driver

使用merge-and-verify-driver.sh脚本,该脚本总是返回1,以表示存在冲突,即使合并实际上已经解决了冲突(在这种情况下没有冲突)。
#!/bin/bash
git merge-file "${1}" "${2}" "${3}"
exit 1

注意:如果有冲突,您将获得更多信息:
git config --global merge.conflictstyle diff3

查看并发修改的示例:https://dev59.com/KFkT5IYBdhLWcg3wPtQv#38989749 - VonC
我现在理解了缺失的冲突标记。如果我的所有文件都是.R文件怎么办?我如何告诉git,对于特定的文件,我想要“先审核”?如果我正确理解了你链接中的答案,他们在git属性中指定了一个文件扩展名。类似git merge --verify dev这样的自定义命令是否可行?(如果问题很蠢,请原谅 - 我对git还很陌生。) - Christoph
@Christoph 在 .gitattribute 中,你可以将自定义合并驱动程序与文件类别关联起来(如 https://gist.github.com/dpwright/2657379 中所示)。我已编辑了我的答案。 - VonC
但是,我的所有.R文件都需要“审核”,也就是说,我不能决定是否要查看合并吗?(背景:在大多数情况下,git确切地做到了我想要的 - 如果我让git变得更糟糕/更慢,那将是非常糟糕的) - Christoph
@Christoph 实际上,使用该合并驱动程序时,将发生合并,而不是合并提交。这为您提供了在添加和提交所有内容之前仅审查所需文件的机会。 - VonC
@Christoph,只是为了明确:合并不会在每个文件处停止。它将合并所有文件,然后在“失败”(退出1)时停止。然后,git状态将指示是否存在任何冲突。如果没有冲突,您可以查看您想要的文件。 - VonC

0
我想将dev合并到master,但我想针对每个更改决定是否保留。

这需要进行交互式变基:
git branch dev_rebase dev
git checkout dev_rebase
git rebase -i master

从那里开始吧。查看 git help rebase 并寻找“交互模式”应该会给你一些想法。只需删除您想要跳过的行(提交),如果需要编辑文件,则使用edit

如果出现严重错误,dev 将保持不变,在任何情况下。

# if happy:

git checkout master
git merge --no-ff dev_rebase

# for good measure:

git checkout dev
git rebase master

我担心我没有足够长的时间使用git:你该怎么做?当我在git bash中输入您的命令时,会打开一个奇怪的编辑器(MINGW64),我感到很迷惑。请参见编辑... - Christoph
在那个编辑器中,git 列出了所有提交记录(从主分支到当前分支的最新提交)。如果你只是退出它,git 将重放所有提交记录,你将回到起点。魔法在于编辑该文件 - 你可以删除行(这些提交将被跳过),你可以重新排序它们(提交将按不同的顺序应用),或者你可以将命令 pick 替换为其他内容,比如 editgit help rebase 会更详细地解释它。 - AnoE
我认为你的方法不同,因为rebase也会为你执行合并操作 - 请看下面我的回答以及我最终所做的。如果我错了,请告诉我,我会再次查看它。 - Christoph

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