问题
I would like to be able to automatically resolve "two branches added blocks at the same line" conflicts by putting the "ours" block first, then the "theirs" block.
So instead of a conflict like:
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
I'd just get:
16:09:44 tims@firebat ~/git/merge_conflict_example (master) $ cat test.txt
good morning
good evening
g'day
aloha
hello
hi
with no conflict.
I figure there might be something like git merge branch1 -X oursthentheirs
The sample I used here is available at git@bitbucket.org:abznak/merge_conflict_example.git
回答1:
There's nothing built in, but if you set merge.conflictstyle
to diff3
, it would be relatively easy to write a program (in perl or python perhaps, or I'll write a cheesy version in awk) that checks whether the "original" section is empty—this will detect the "both added" situation—and if so, simply removes the conflict markers:
good morning
good evening
<<<<<<< HEAD
g'day
|||||||
=======
aloha
>>>>>>> branch1
hello
hi
Here's my awk script (which I don't claim to be good, but it works on the sample input). Note that it won't handle "nested conflicts" very well (i.e., if the two original conflicting files contain what look like conflict markers, this will go wrong).
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] = $0
}
/^\|\|\|\|\|\|\|/ { 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) }
回答2:
It's easy. Just set the merge
gitattribute to union
.
From 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.
For the example, I just added a .gitattributes file containing the text *.txt merge=union
:
10:58:21 tims@thor ~/git/merge_conflict_example (master) $ cat .gitattributes
*.txt merge=union
And ran the merge:
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(+)
Which had the desired effect:
10:58:42 tims@thor ~/git/merge_conflict_example (master) $ cat test.txt
good morning
good evening
g'day
aloha
hello
hi
回答3:
You can merge, say branch old into the current branch, using "ours" merge strategy like below
$ git merge -s ours old
来源:https://stackoverflow.com/questions/33603595/how-do-i-get-git-to-resolve-merge-conflicts-by-putting-ours-first-then-theirs