0

Problem description

When merging two branches in git with conflicting files, git adds markers to the conflicting areas. For example, a file with conflict would look like this

Some code

<<<<<<< HEAD
Changes in branch A
||||||| cbf9a68
Original code
=======
changes in branch B
>>>>>>> branch-B

some more code

where branch-A/HEAD is the branch to merge into, branch-B is the branch to merge, and <<<, ===, and >>> are referred to as conflict markers. There are various tools that help in resolving these conflicts. These include meld, vimdiff, diffview, and many more. However, these tools can only be used in git repos that are in conflict-resolution status (i.e., when the two branches are not yet merged).

There are situations where these tools can no longer be used (as far as I'm aware), and these include:

  1. if the conflicting files are comitted with the conflict markers (i.e., the conflicting files are comitted with <<<, ===, and >>> markers);
  2. if the conflicting file with the conflict markers are moved outside a git repo (e.g., to keep track of conflicts).

In such situations, the git merge tools can no longer be used to resolve these conflicts.

It seems that these conflict tools are only possible to use in a git repo, which makes sense. So, my question is as follow: is it possible to use the git merge tools on files that contain conflict markers (i.e., <<<, ===, and >>>) outside a git repo (or after comitting the file with conflict markers)?

That is, I would like the process to look like this:

git checkout branch-A
git merge branch-B

# Part 1: committing file with conflict markers
git add foo.txt                           # Add conflicting file, with conflict markers (i.e., withOUT resolving conflicts)
git commit -m "Add conflicting file"      # Commit file with conflict markers

# Part 2: resolve conflict on committed files (i.e., this is what I'm asking for)
# TODO: Use conflict resolution tools such as meld, diffview, etc. to find conflict markers and resolve them
git add foo.txt                           # Stage and commit files after resolving conflicts
git commit -m "Conflicts resolved"

When is this problem encountered?

I understand this is an unusual way to use the git merge tools, but here's a situation where it can be used. Some organizations ask developers to commit the conflicting files with the conflict markers, and then resolve the conflicts in another commit. The reasoning is that when creating a PR, the reviewers can see how the developer resolved the conflicts.

I understand this may be considered a bad practice (e.g., committing the files with conflict markers means there's a commit at which the code doesn't work or compile). However, my question is not about this practice since I have no option but to follow this convention.

Sub-optimal solution

A possible sub-optimal solution to the problem above is the following

git checkout branch-A
git merge branch-B

# Part 1: committing file with conflict markers
git add foo.txt                           # Add conflicting file, with conflict markers (i.e., withOUT resolving conflicts)
git commit -m "Add conflicting file"      # Commit file with conflict markers

# Part 2: committing file to another branch after conflict resolution
git checkout HEAD~1                       # Checkout previous commit (i.e., before merging)
git checkout -b branch-A-resolved         # Create a branch at which the conflicts are to be resolved
git merge branch-B                        # Merge branch-B
# Resolve conflicts
git add foo.txt                           # Add file *after* resolving conflicts
git commit -m "Resolve conflicts"         # Commit file withOUT conflict markers

# Part 3: cherry-pick conflict-resolved files into branch-A
git checkout branch-A
git cherry-pick branch-A-resolved -m 1 -X theirs  # `theirs` is used since `branch-A-resolved` contains the resolved file
git branch -D branch-A-resolved

The above solution works, but as you can see, it's quite tedious.

Amro
  • 130
  • 7

2 Answers2

1

The short answer is "no". matt has already covered some of the longer answer, but there's one more item to know here: when you run git mergetool, Git grabs the three copies of the file that exist in Git's index aka staging area. Git does not directly use the working tree copy, with its conflict markers, to invoke your chosen merge tool.

If all you have is a single marked-up-with-conflicts file, the only way to make git mergetool work with it would be to read it, construct the three inputs, insert them into the index using git update-index, and then run git mergetool. Many conflicted (marked-up) files don't have enough information to construct the original three inputs, but you could construct something that might (or might not) be good enough for your purposes, whatever those purposes are. Whether that's the case depends on your needs.

Note: You're probably better off constructing the three input files and invoking your chosen merge tool directly, rather than using git update-index and running git mergetool. This cuts out a lot of the complexities and means you don't need a Git repository in the first place.

torek
  • 448,244
  • 59
  • 642
  • 775
  • This is good to know, thank you for explaining how the merge-tool works. Are there tools that automatically construct the three files from the marked-up files? – Amro Nov 23 '22 at 15:22
  • 1
    I don't know of any. If you have the diff3 style markup, the base version can be constructed; without it, the true base can't be constructed and must be guessed-at. In all cases there are potential issues if there are merge conflict markers in the original three input files (and nested conflicts are possible when using recursive merge, so that the actual merge base might have merge conflicts in it!). These last problems will be rare though: if you decide to write such a tool, you can probably just leave them as a problem for the user... – torek Nov 24 '22 at 09:33
0

Unclear what you mean by the Git merge tools; the tools you mention don't belong to Git. The tools I use are a really good text editor and my brain. That's all you need to resolve a conflicted file containing the markers. The tools you mention don't tell you anything that you can't see with your own eyes just by looking at the marked up file (especially when the file is marked up in diff3 style, as yours is).

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thanks for your feedback @matt. You're right, these tools do not belong to git. True, it's possible to to manually fix up the conflicts by manually looking through the code, but then I wouldn't be able to use the full power of these tools. As I understand it, these tools parse the files looking for the conflict markers and then gives the programmer options to handle the conflicts. However, if I trigger these tools on an arbitrary file containing the conflict markers, the tools do not see the conflict markers as "conflicts", but rather as part of the file. – Amro Nov 22 '22 at 21:45
  • I don't get what you mean. I resolve merge conflicts every day using nothing but the marked-up text file. What can't you do the same? You look for the conflict markers (a good text editor has a Find command) and then you handle them (by deleting whatever doesn't belong, rearranging if needed, etc.). In fact you're likely to get a _better_ outcome under certain circumstances by looking and thinking and editing than any three-way comparison GUI can give you. – matt Nov 22 '22 at 21:53
  • Doing it manually requires manually deleting many lines, which is slower/less-efficient than using the tools and more prone to error. Furthermore, the merge-tools splits the conflicts visually into multiple columns making it easier to see the difference (check [this example](https://user-images.githubusercontent.com/2786478/188286293-13bbf0ab-3595-425d-ba4a-12f514c17eb6.png)). – Amro Nov 22 '22 at 22:05
  • 1
    Well that seems quite a silly objection, but I suppose you _could_ just cook up a custom merge tool as explained in [this answer](https://stackoverflow.com/a/56121685/341994). – matt Nov 23 '22 at 02:40
  • I don't think it's silly to look for more efficient, less error-prone ways to do things. That's why these tools are available and are quite popular. Thank you for the link to the custom mergetool approach, I think that could be of help. Thanks for your input. – Amro Nov 23 '22 at 15:26