There are numerous questions on Stack Overflow on how to resolve merge conflicts in favour of one or the other branch. But the most common answer I'm finding is using git checkout --ours
or git checkout --theirs
.
The problem is git checkout
will take the entire file from either branch. There could've been parts of the file that merged just fine, and we don't want them removed.
Given a file in a conflicted state, is there a way to remove the conflict markers in favour of "ours" or "theirs" without applying this strategy to the entire merge or taking the entire file from "ours" or "theirs"?
This is definitely possible with a simple script, but I want to know if there's an existing solution I'm not finding.
If you want to resolve all remaining conflicts in a file to ours or theirs it's a straightforward sed
per side you want and your conflict style.
For most code files, where the conflict markers are so foreign that you don't have to be careful about identifying them, it's so easy you can just type it:
sed -si '/^<<</,/^>>>/ {/^<<</,/^===/d;/^>>>/d}' thefile # keep theirs
sed -si '/^<<</,/^>>>/ {/^<<</d;/^===/,/^>>>/d}' thefile # keep ours
And to do that for everything,
sed -si $yourpattern $(git ls-files -m | uniq)
is easiest.
To be more careful with your conflict markers, it's better to make the simple script you referred to, and the diff3 conflict-reporting style needs some changes as well. The usual conflict symbol count is 7, and for best safety make your sed range /^<<<<<<< ours$/,/^>>>>>>> theirs$/
, and with diff3 reporting the "keep ours" deletion range starts with ^||||||| base$
, not ^=======$
.
sed
on the Mac has been butchered to refuse to do inline edits without creating a backup file. You have to do e.g. -si.bak
and then delete the backup.
I think you shouldn't work this way. Instead, you should install a suitable merge editor (KDiff3, for example), run git mergetool
(which iterates over the files in conflict and runs the installed merge editor) and review the changes manually.
The merge tool will open the three versions of the file in conflict, will automatically take all solvable changes just as you wished, and will highlight remaining conflicts. If you really don't want to review them one-by-one, select menu item Merge → Choose xxx for each unresolved conflict, and tadah.
If you are really sure you don't want to use a visual merge tool, you have the following options beneath the one mentioned by torek.
If you want to apply this strategy to each conflicted file during one merge, use the "ours" or "theirs" suboption to the standard merge strategy:
git merge -Xours ...
Don't confuse it with selecting the whole merge strategy with -s ours
, which simply takes everything from ours without trying to do a merge.
If you want to apply this strategy to some particular files during every merge, you can define a custom merge driver (in .gitconfig) and apply it to that files (in .gitattributes). This sounds much more complicated than it is. Defining a merge driver simply means to define a command line which takes three input files and creates one output file, you can for example use git merge-file as torek explained it. Once defined, you can assign such a merge driver to any file or pattern by creating a .gitattributes file in the repository root and committing it. Just read about it on gitattributes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With