如何让 git 通过放置 "ours first, then theirs" 来解决合并冲突
How do I get git to resolve merge conflicts by putting "ours first, then theirs"
我希望能够通过先放置 "ours" 块,然后放置 "theirs" 块来自动解决 "two branches added blocks at the same line" 冲突。
所以不要像这样的冲突:
16:09:44 tims@firebat ~/git/merge_conflict_example (master|MERGING) $ cat test.txt
good morning
good evening
<<<<<<< HEAD
g'day
=======
aloha
>>>>>>> branch1
hello
hi
我会得到:
16:09:44 tims@firebat ~/git/merge_conflict_example (master) $ cat test.txt
good morning
good evening
g'day
aloha
hello
hi
没有冲突。
我想可能会有类似 git merge branch1 -X oursthentheirs
我在此处使用的示例可在 git@bitbucket.org:abznak/merge_conflict_example.git
获得
你可以使用 "ours" merge 将旧分支合并到当前分支
策略如下
$ git merge -s ours old
没有什么内置的,但是如果你把merge.conflictstyle
设置为diff3
,写一个程序就相对容易了(也许用perl或者python,或者我会用 awk 编写一个俗气的版本)检查 "original" 部分是否为空——这将检测 "both added" 情况——如果是,只需删除冲突标记:
good morning
good evening
<<<<<<< HEAD
g'day
|||||||
=======
aloha
>>>>>>> branch1
hello
hi
这是我的 awk 脚本(我不认为它很好,但它适用于样本输入)。请注意,它不会很好地处理 "nested conflicts"(即,如果两个原始冲突文件包含看起来像冲突标记的内容,则会出错)。
BEGIN { in_conflict = retained_left = retained_mid = retained_right = 0 }
function handle_retained(is_eof) {
# If the section between ||||||| and ======= is empty,
# retained_mid+1 == retained_right. Otherwise print
# all the retained conflict lines.
if (retained_mid + 1 == retained_right) {
s1 = retained_left + 1 # after <<<<<<<
e1 = retained_mid - 1 # before |||||||
s2 = retained_right + 1 # after =======
e2 = NR - 1 # before >>>>>>>
} else {
s1 = retained_left; e1 = NR
s2 = 1; e2 = 0
}
for (i = s1; i <= e1; i++)
print retained[i]
for (i = s2; i <= e2; i++)
print retained[i]
delete retained
if (is_eof) {
# this should never happen!
print "WARNING: ended input while still in conflict marker"
exit(1)
}
}
/^<<<<<<</ { in_conflict = 1; retained_left = NR }
{
if (!in_conflict)
print
else
retained[NR] = [=11=]
}
/^\|\|\|\|\|\|\|/ { if (in_conflict) retained_mid = NR }
/^=======/ { if (in_conflict) retained_right = NR }
/^>>>>>>>/ { if (in_conflict) handle_retained(0); in_conflict = 0 }
END { if (in_conflict) handle_retained(1) }
很简单。只需将 merge
gitattribute 设置为 union
。
来自 https://git-scm.com/docs/gitattributes:
union
Run 3-way file level merge for text files, but take lines from both
versions, instead of leaving conflict markers. This tends to leave the
added lines in the resulting file in random order and the user should
verify the result. Do not use this if you do not understand the
implications.
例如,我刚刚添加了一个包含文本 *.txt merge=union
:
的 .gitattributes 文件
10:58:21 tims@thor ~/git/merge_conflict_example (master) $ cat .gitattributes
*.txt merge=union
与运行合并:
10:58:26 tims@thor ~/git/merge_conflict_example (master) $ git merge origin/branch1
Auto-merging test.txt
[...]
Merge made by the 'recursive' strategy.
test.txt | 1 +
1 file changed, 1 insertion(+)
达到预期效果:
10:58:42 tims@thor ~/git/merge_conflict_example (master) $ cat test.txt
good morning
good evening
g'day
aloha
hello
hi
我希望能够通过先放置 "ours" 块,然后放置 "theirs" 块来自动解决 "two branches added blocks at the same line" 冲突。
所以不要像这样的冲突:
16:09:44 tims@firebat ~/git/merge_conflict_example (master|MERGING) $ cat test.txt
good morning
good evening
<<<<<<< HEAD
g'day
=======
aloha
>>>>>>> branch1
hello
hi
我会得到:
16:09:44 tims@firebat ~/git/merge_conflict_example (master) $ cat test.txt
good morning
good evening
g'day
aloha
hello
hi
没有冲突。
我想可能会有类似 git merge branch1 -X oursthentheirs
我在此处使用的示例可在 git@bitbucket.org:abznak/merge_conflict_example.git
获得你可以使用 "ours" merge 将旧分支合并到当前分支 策略如下
$ git merge -s ours old
没有什么内置的,但是如果你把merge.conflictstyle
设置为diff3
,写一个程序就相对容易了(也许用perl或者python,或者我会用 awk 编写一个俗气的版本)检查 "original" 部分是否为空——这将检测 "both added" 情况——如果是,只需删除冲突标记:
good morning
good evening
<<<<<<< HEAD
g'day
|||||||
=======
aloha
>>>>>>> branch1
hello
hi
这是我的 awk 脚本(我不认为它很好,但它适用于样本输入)。请注意,它不会很好地处理 "nested conflicts"(即,如果两个原始冲突文件包含看起来像冲突标记的内容,则会出错)。
BEGIN { in_conflict = retained_left = retained_mid = retained_right = 0 }
function handle_retained(is_eof) {
# If the section between ||||||| and ======= is empty,
# retained_mid+1 == retained_right. Otherwise print
# all the retained conflict lines.
if (retained_mid + 1 == retained_right) {
s1 = retained_left + 1 # after <<<<<<<
e1 = retained_mid - 1 # before |||||||
s2 = retained_right + 1 # after =======
e2 = NR - 1 # before >>>>>>>
} else {
s1 = retained_left; e1 = NR
s2 = 1; e2 = 0
}
for (i = s1; i <= e1; i++)
print retained[i]
for (i = s2; i <= e2; i++)
print retained[i]
delete retained
if (is_eof) {
# this should never happen!
print "WARNING: ended input while still in conflict marker"
exit(1)
}
}
/^<<<<<<</ { in_conflict = 1; retained_left = NR }
{
if (!in_conflict)
print
else
retained[NR] = [=11=]
}
/^\|\|\|\|\|\|\|/ { if (in_conflict) retained_mid = NR }
/^=======/ { if (in_conflict) retained_right = NR }
/^>>>>>>>/ { if (in_conflict) handle_retained(0); in_conflict = 0 }
END { if (in_conflict) handle_retained(1) }
很简单。只需将 merge
gitattribute 设置为 union
。
来自 https://git-scm.com/docs/gitattributes:
union
Run 3-way file level merge for text files, but take lines from both versions, instead of leaving conflict markers. This tends to leave the added lines in the resulting file in random order and the user should verify the result. Do not use this if you do not understand the implications.
例如,我刚刚添加了一个包含文本 *.txt merge=union
:
10:58:21 tims@thor ~/git/merge_conflict_example (master) $ cat .gitattributes
*.txt merge=union
与运行合并:
10:58:26 tims@thor ~/git/merge_conflict_example (master) $ git merge origin/branch1
Auto-merging test.txt
[...]
Merge made by the 'recursive' strategy.
test.txt | 1 +
1 file changed, 1 insertion(+)
达到预期效果:
10:58:42 tims@thor ~/git/merge_conflict_example (master) $ cat test.txt
good morning
good evening
g'day
aloha
hello
hi