我在feature/my-branch
上签出并运行git merge dev
.添加到文件的冲突标记包括:
<<<<<<< HEAD
let foo = "foo"
let bar = "bar"
||||||| merged common ancestors
let baz = "baz"
let bar = "bar"
=======
let baz = "baz"
let qux = "qux"
>>>>>>> dev
然后我跑git mergetool
.我p4mergetool
设置为我的合并工具,它似乎正在工作。我的.gitconfig
:
[merge]
tool = p4mergetool
conflictstyle = diff3
[mergetool "p4mergetool"]
cmd = /Applications/p4merge.app/Contents/Resources/launchp4merge $PWD/$BASE $PWD/$REMOTE $PWD/$LOCAL $PWD/$MERGED
trustExitCode = true
git mergetool
自动将上述冲突(工具中显示的 0 个冲突)解决为:
let foo = "foo"
let qux = "qux"
这是有道理的:即使 HEAD 和 dev 存在冲突,我们也可以看到一个分支更新了一行,另一个分支更新了另一行。因此,我们可能可以假设我们想要什么。
我的问题是:
- 有没有办法专门运行/配置
git-mergetool
或p4mergetool
,以免做出此假设并且仍然显示冲突? 我是否需要运行这两个命令:
git merge dev git mergetool
让这个冲突自动解决这个问题? 即产生输出:
let foo = "foo" let qux = "qux"
换句话说:是否有一个 git 合并策略/参数,我可以用来简单地运行merge
命令来生成:
let foo = "foo"
let qux = "qux"
这是有道理的:即使 HEAD 和 dev 存在冲突,我们也可以看到一个分支更新了一行,另一个分支更新了另一行。因此,我们可能可以假设我们想要什么。
这是完全正确的。
- 有没有办法专门运行/配置
git-mergetool
或p4mergetool
,以不做出此假设并且仍然显示冲突?
git mergetool
没有做出假设,因此我们可以得出结论,p4mergetool
一定是做这件事的人。 我没有p4mergetool
,所以我不知道它是否有配置旋钮来改变这一点。
- 我需要运行这两个命令吗?
是的:Git 自己的合并有点愚蠢,只是注意到,天哪,左侧的这个更改范围相邻(触摸)或重叠右侧的其他更改范围,所以让我们称之为冲突并让用户处理它。 在这种情况下,左侧更改(从 baz 到 foo)发生在右侧更改(bar 到 qux)之前,因此两个范围在边缘接触,Git 本身声明了冲突。 如果中间有一条线,git merge
会自行合并更改,而不会将其称为冲突。
(请注意,使用-X ours
或-X theirs
将通过放弃一方的更改并仅使用另一方的更改来解决冲突。 再一次,你甚至永远不会达到让p4mergetool
做自己的事情的地步。
git mergetool
所做的是提取三个文件——合并基文件、左文件、本地文件或--ours
文件,以及某个文件的右版本、远程版本或--theirs
版本——并在这三个文件上运行其他一些非 Git 程序。 当该程序完成后,git mergetool
可以信任其退出代码来决定工具本身是否正确合并了文件,或者运行一些文件比较,或者直接询问您:文件的工作树副本现在是正确的合并副本吗?
如果工作树副本现在是正确的最终结果(或者至少git mergetool
相信这一点),则git mergetool
运行git add
,这标志着冲突已解决。1否则,冲突就会留在原地。
(我倾向于只在我的编辑器中解决合并冲突。
1如果文件的任何非零索引插槽中有任何副本,则文件将取消合并。如果文件有一个副本,则合并该文件,位于插槽 0 中 - 正常的插槽编号。 除了使用 Git 的一些低级诊断式命令(真的是git ls-index --stage
),你实际上看不到这些暂存槽号,但git status
调用未合并的文件,并告诉你它是在所有三个槽中(UU
)还是在左边或右边(分别为UD
和DU
)。 我不确定git status
对插槽 1 中的文件有何看法,该文件将代表具有重命名/重命名冲突的文件的合并基本副本。
通常我们只是使用git add
或git rm
来覆盖编号较高的插槽。 在极少数情况下,希望将已解决的文件还原到冲突状态,git checkout -m
可以做到这一点。