0

I looked quite thoroughly yo find an answer to this and was not able too. Is there a simple way to prevent git from appending conflict markers to conflicted files when merging. I'd like to prevent git from adding "<<<< ==== -----" when there is a conflict in a file.

I tried using the gitattributes "binary" as I thought it was not gonna change the content of the file but without success. Any ideas?

Cheers!

phd
  • 57,284
  • 10
  • 68
  • 103
RBL92
  • 21
  • 3
  • 4
    Welcome to SO, what is the issue these are causing that makes you want to get rid of them? – LightBender Dec 13 '18 at 16:24
  • I don't know of a way to do this, nor can I imagine why you would want to do this, since it might leave you unable to resolve the merge conflicts. One option to avoid them would be to merge using the `--ours` or `--theirs` flags. Then, Git would unequivocally accept one version of each file, and there would be no conflicts. – Tim Biegeleisen Dec 13 '18 at 16:26
  • 5
    Sounds like you're fighting the symptoms. Do you understand why Git is producing the conflict markers? Why do you want to prevent Git from doing so? What should Git do instead? – alfunx Dec 13 '18 at 16:34
  • My question would be: what would you want git to do then when there's a conflict? If there are no conflict markers, how will you know what the conflict is about? – eftshift0 Dec 13 '18 at 16:37
  • Hi, thank you for your answers. The reason I want to prevent git from adding markers is because I use beyond compare to manually resolve my conflicts and those git markers tend to mess with how beyond compare sees the differences between files. – RBL92 Dec 13 '18 at 16:42
  • @RBL92 - I think the question remains: what DO you want the file to look like? If the "base' version of the file was a single line that says "base", and then you changed that line to "ours', and then you merge in a branch where that same line was changed to "theirs" - a situation that normally generates a conflict marker - then; (1) do you want the file to remain in a conflicted state, and (2) what do you wan the file in your work tree to look like? – Mark Adelsberger Dec 13 '18 at 16:54
  • Possible duplicate of [Resolve Git merge conflicts in favor of their changes during a pull](https://stackoverflow.com/questions/10697463/resolve-git-merge-conflicts-in-favor-of-their-changes-during-a-pull) – mx0 Dec 13 '18 at 17:19
  • @MarkAdelsberger Ideally I would want the file in my work tree to not change at all and say "ours". I would also like to know that there is a conflict in the file. Using beyond compare afterwards between my working tree and the branch that has "theirs" would clearly show the conflicting line and I could resolve it myself. However, if the markers are present, beyond compare can't match the lines and figure out which ones have changed. – RBL92 Dec 13 '18 at 17:28

2 Answers2

1

Considering your comments, you should set up Beyond Compare as mergetool instead of manually opening the files with conflicts. Make sure you can run bc3 in the terminal first. You can then set it up like this (on Linux):

git config --global merge.tool bc3
git config --global mergetool.bc3.trustExitCode true

Now, when you run into a conflict, simply run

git mergetool

to open the conflicted file(s) in Beyond Compare.

Find more details and instructions for other operating systems on their support site: scootersoftware.com/support.php.

alfunx
  • 2,910
  • 1
  • 10
  • 21
0

The goal is, if a file is conflicted, to

1) have git mark the file as "in conflict", and

2) be able to use Beyond Compare between the unmerged versions of the file ("our" version and "their" version).

I will caution that while this will work well in simple cases, it does somewhat defeat the 3-way merge approach that would typically be used (i.e. you're not looking at the changes in the context of a merge base), so in some more complex cases this will not be so easy. (For that reason I would recommend becoming familiar with a more "standard" approach to conflict resolution, so that you can at least fall back on it when necessary.)

But certainly there are a few ways to do it. The simplest thing is to start the merge normally

git checkout our_branch
git merge their_branch

and then, when it conflicts, revert the work tree to "our" version

git checkout --ours path/to/conflicted/file

If you have Beyond Compare configured to work as your diff tool, then you may be able to skip the checkout and just

git diff our_branch their_branch -- path/to/conflicted/file

but the disadvantage here is that BC won't have your working version of the file open, so you might not have the support you want for directly editing it.

So another option, more complex to set up but more automatic to use, is to set up a custom merge driver. A custom merge driver kicks in whenever both "our" version and "their" version of a given file are changed (relative to the "base" version). It is a script that receives, as parameters, the names of temporary files representing the various versions of the file. It creates a (tentative) merge result at the path for "our" version, and returns a status that indicates whether conflicts occurred.

Merge drivers are described in the documentation of the merge attribute (at https://git-scm.com/docs/gitattributes). This also shows that, given a configured merge driver, you would associate it with file(s) at given path(s) with a .gitattributes file. (You could associate it with all paths in your repo with an entry for *, but if your repo may contain binary files you may want to either avoid doing that, or take care that your driver script behaves reasonably for binary files as well.)

The script itself would attempt a normal merge

git merge-file -p <ours> <base> <theirs> > <temp-path>

(where <ours>, <base>, and <theirs> are from the scripts' parameters, and <temp-path> is a new temporary file). If this command returns 0 (no conflicts), the script would move the output (<temp-path>) over "our" version and return 0. Otherwise it would delete the temp file, leave "ours" unchanged, and return a non-zero value.

Now, that would make your merges work pretty much like the first approach, except you can skip the git checkout --ours. That may not be worth it. But the advantage of this solution is, you can build on it to do a bit more.

The problem with all of the above solutions is, if a file contains any conflicts, then none of the changes (including non-conflicting changes) for that file are auto-merged. You have to process the entire file manually (with Beyond Compare, or whatever).

You could refine the merge driver script so that, in case of conflict, it reruns the merge with the --ours strategy option

git merge-file --ours <ours> <base> <theirs>

(You would still want to run without the --ours option first, so that you know if any conflicts occurred. If there are conflicts, then you delete the temp file, rerun with the --ours option - but without the -p or the output redirection - and, again, return a non-zero value so git knows there was a conflict.)

Finally, note that this should not be confused with what happens if you just run merge with either -s ours (which ignores the other branch content entirely) or -X ours (which resolves conflicts in favor of "our" version and reports no conflicts).

Mark Adelsberger
  • 32,904
  • 2
  • 24
  • 41