手动创建带有冲突的Git合并标记,类似于差异。

4
当发生 git merge 冲突时,将出现类似以下的标记:
<<<<<<< HEAD:file.txt
Hello world
=======
Goodbye
>>>>>>> master:file.txt

想象一下,假设我有一个名为file.txt的文件,并且我手动编辑了它。

Hello world

为了

Goodbye

当我使用默认分页程序运行git diff时,我会得到以下输出:
diff --git a/file.txt b/file.txt
index 802992c..2b60207 100644
--- a/file.txt
+++ b/file.txt
@@ -1 +1 @@
-Hello world
+Goodbye

有没有一种方法可以将此格式转换为上面给出的格式,并为所有更改放置冲突标记?(如果它覆盖了文件也没关系。)


1
当冲突发生时,会有三个文件 - 基础文件、A文件和B文件,因此您需要使用这些标记显示三方差异。通常的差异只显示两个文件之间的差异。所以,不确定您期望什么。 - kan
有一些git合并工具可以执行双向合并,这可能是你想要的,而不是模拟3向合并的冲突标记。话虽如此,使用空文件作为基础的冲突标记的输出并不完全无用。但你可能需要解释一下你想做什么。 - zzxyz
是的,你说得对 - 我需要一个基础。我想把共同的行作为基础,将从差异中减去的行作为左提交的新行,将从差异中添加的行作为右提交的新行。这样说通了吗? - eedrah
(在这种情况下,显示基础的标记始终为空,在三方提交的情况下) - eedrah
1
你可以在这里检查我的答案 https://dev59.com/6XHYa4cB1Zd3GeqPGgNK 但它是针对diff独立命令的。我没有看到任何直接的方法将其与git diff绑定,但使用一些bash技巧是可能的。 - kan
真的很酷,@kan。我在git diff中找不到类似的选项,但我找到了一个不同的解决方案,它可以工作。 - eedrah
2个回答

2
这里有一种方法 - 下面的命令将会把一个看起来像这样的差异转换为:
diff --git a/file.txt b/file.txt
index 2b34ae8..a27a6bd 100644
--- a/file.txt
+++ b/file.txt
@@ -1,16 +1,16 @@
 Line 1
+Addition here
 Line 2
 Line 3
 Line 4
 Line 5
 Line 6
 Line 7
-Line 8
+Line 8 Change here, and deletion on line 15
 Line 9
 Line 10
 Line 11
 Line 12
 Line 13
 Line 14
-Line 15
 Line 16

将其保存为像这样的文件:

Line 1
<<<<<<< HEAD
=======
Addition here
>>>>>>> temp
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
<<<<<<< HEAD
Line 8
=======
Line 8 Change here, and deletion on line 15
>>>>>>> temp
Line 9
Line 10
Line 11
Line 12
Line 13
Line 14
<<<<<<< HEAD
Line 15
=======
>>>>>>> temp
Line 16

命令和解释如下:

命令和解释如下:

branch=$(git symbolic-ref --short HEAD)                # Get the current branch name
git checkout --orphan temp                             # Change to a branch with no parents, so to force a merge conflict
git add -A                                             # Add everything there
git commit -m 'temp'                                   # Commit
git checkout "$branch"                                 # Go back to your previous branch
(git merge --allow-unrelated-histories temp || true)   # Merge the unrelated branches, which causes a conflict with your changes. This is done in a subshell with the '|| true' so that it doesn't return an error code - I have this in a git alias, so this is necessary for me so the command isn't aborted halfway.
git add -A                                             # Add your conflict markers as additions to the file
GIT_EDITOR=true git merge --continue                   # Commit. When --continue is used it doesn't accept the flag --no-edit, so to stop git opening an editor for the commit message, use the command 'true' as the editor.
git reset HEAD^                                        # Get rid of the last commit but keep its changes (the markers). This is needed because there is no way to get out of a conflicting merge commit but keep the conflict markers.
git branch -D temp                                          # Clean up

当然,您可以将此转换为脚本或别名。请注意,它将已暂存的更改和未暂存的更改视为相同。


有没有不需要隐藏未提交的更改和取消已暂存更改的方法来完成这个操作? - dols3m
我不确定你想要什么,但这将为自上次提交以来所做的每个更改创建冲突标记,因此任何你不想要冲突标记的内容都应该在一个侧面提交(或存储)中。 - eedrah
最后一行使用了b别名,应该是branch子命令。不幸的是,我没有足够的声望来自己修复它。 - Julius Bullinger

0

这里有一种生成git合并冲突文件的方法。它不是问题的确切答案,因为它依赖于您可以访问a/file.txtb/file.txt

如果您拥有另一个文件和差异,可以使用patch来生成任何一个文件。

然后,也许这个git merge-file命令将产生您需要的输出:

touch /tmp/empty && git merge-file -L a/file.txt -L B -L b/file.txt -p a/file.txt /tmp/empty b/file.txt
<<<<<<< a/file.txt
Hello world
=======
Goodbye
>>>>>>> b/file.txt

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