gitvisual-studio-codemerge-conflict-resolution

Forcefully set files status as "unmerged" in a Git repository


When I merge a branch into another one, and get conflicts, Git tells me some files are unmerged. For example:

% git status
On branch test-merge
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Changes to be committed:
        modified:   .gitignore
        new file:   build.py

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   Makefile
        both modified:   duties.py
        both modified:   pyproject.toml

Now let say that, in a clean repository (not during a merge) I manually add conflict markers in some file, for example:

<<<<<<< before updating
=======
This line was added
>>>>>>> after updating

How would I go about having Git report this file as "unmerged", even if that's not really the case?


Context: Copier is a project templating tool. One of its main features is project-template updating: you can generate a projet from a Copier template, evolve the project, then evolve the template, and apply the template changes into the project, while keeping the project changes. See How the update works.

After running an update, Copier sometimes leaves conflict markers in some files. But since these markers do not come from a merge, tools like VSCode do not provide the same UX as for unmerged files, i.e. the Source Control tab takes you to the diff view instead of the normal view where you get buttons to "Accept incoming", "Accept current", "Accept both", etc.. Also, it does not group files with markers under a "Merge changes" section, and instead puts everything under a basic "Changes" section. Also also, it does not prevent me from staging a file containing conflict markers, because that file is not reported by Git as being "unmerged". I have detailed all this with screenshots in this GitHub comment.


I noticed that, during a merge, a few files appear in the .git folder, namely AUTO_MERGE, MERGE_HEAD, MERGE_MODE, and MERGE_MSG. Would there be a way to manually create these files, even if that is considered lying (for example by using an arbitrary or fake Git reference in MERGE_HEAD) to force Git to report files with conflict markers as unmerged?


I understand I'm going to quite some lengths just to improve a tiny bit the UX between Copier and VSCode, but I'm also very curious to learn if that is something possible, and how it could be done :) Maybe I'm going in the wrong direction, and should instead open a feature request for VSCode to recognize conflicted files regardless what Git is saying about them.

Happy to provide more information if needed!


Solution

  • How would I go about having Git report this file as "unmerged", even if that's not really the case?

    You update the index to its state during an unresolved merge, with base and tip contents but no merged content. You do this with git update-index --index-info, see its entry in the Git docs.

    There's four "stages" of content at a path. "Stage 0" is the normal stage, in a merge there's three more, "Stage 1" is its base state, "Stage 2" is the "ours" version, "Stage 3" is the "theirs" version. Unmerged paths have pointers to the "higher order" versions that doc's talking about and no entry for the resolved content.