Is there a way to make Git mark a file as conflicted?

12,179

Solution 1

You can get contents of file with conflict markers using git checkout --conflict=merge -- file, but if you have cleaned up index by using git add file (or if GUI did that for you) it wouldn't work.

There is git update-index --unresolve, but it is hacky, and does not work very reliably. I think the state it restores would be not enough for git-mergetool.

You would probably have to redo merge, or use git update-index --cacheinfo to manually set stages version... git-stash can help you preserve correctly resolved conflicts.

Solution 2

If the index is already in a conflict state, simply check out the file with the --conflict=merge flag:

git checkout --conflict=merge file

If the index is clean because the unresolved file has been [erroneously] added, just reset it before checking it out:

git reset file
git checkout --conflict=merge file

This will allow you to resume conflict resolution normally (e.g., git mergetool).

NOTE: Promoting a comment to @jakub-narębski's answer into its own answer by request from @fourpastmidnight. :)

Solution 3

The most elegant solution would be to prevent this problem from the very beginning:
git config --global mergetool.[tool].cmd [command-line call]
git config --global mergetool.[tool].trustExitCode false

Solution 4

As far as I know, you won't be able to commit while a file still contain conflict markers in it.... which is not exactly true:
The OP mentions that you can (I copy here his pastbin), but that won't be enough for the mergetool to be trigger again:

Auto-merged README
CONFLICT (content): Merge conflict in README
Automatic merge failed; fix conflicts and then commit the result.
lynx:~/test_clone$ ls
README
lynx:~/test_clone$ git add README
lynx:~/test_clone$ git commit -a
Created commit 46ee062: It works!
lynx:~/test_clone$ ls
README
lynx:~/test_clone$ cat README
<<<<<<< HEAD:README
testingtesting
=======
hmm
>>>>>>> 881d60f5f738bc5716f5c9a9384e262b535717fd:README
lynx:~/test_clone$

As Charles Bailey comments, and illustrates in this SO answer, the mergetool is queried because there are 3 instances of the same file in the index:

For an unmerged file in a conflict git makes available the common base, local and remote versions of the file in the index. (This is where they are read from for use in a 3-way diff tool by git mergetool.) You can use git show to view them:

# common base:
git show :1:afile.txt

# 'ours'
git show :2:afile.txt

# 'theirs'
git show :3:afile.txt

git add (with whatever content, including conflict markers) will automatically removes 2 of them, ensuring the mergetool won't be called again.

Share:
12,179
Christian Neverdal
Author by

Christian Neverdal

I enjoy Scala.

Updated on July 27, 2022

Comments

  • Christian Neverdal
    Christian Neverdal almost 2 years

    It's possible to commit files that contains conflict data. Is there a way to mark these files as conflicted again, so that running git mergetool will generate the necessary files and run the merge tool?

  • Christian Neverdal
    Christian Neverdal about 14 years
    Indeed you can. Merely doing a git add <file> will remove the marker and you are then free to commit. pastebin.com/KKLtCZ35
  • VonC
    VonC about 14 years
    @Christian: interesting (I have amended the answer to reflect it), but will the git mergetool detect it and re-trigger a merge?
  • CB Bailey
    CB Bailey about 14 years
    git determines that a file is conflicted if it has multiple entries in the index, rather than just the usual one. git places conflict markers in the working tree version to help the user resolve the conflict but these are not how git counts the file as unmerged. Calling git add tells git to add the working tree version of the file to the index removing all the other entries. After git add, as there is now just a single index entry the file is no longer 'unresolved' so you can commit it.
  • ebneter
    ebneter about 14 years
    Heh, I was just writing this response. ;-)
  • VonC
    VonC about 14 years
    @Christian: completed my answer after Charles's comment.
  • VonC
    VonC about 14 years
    Just completed my answer after Charles's comment.
  • Christian Neverdal
    Christian Neverdal about 14 years
    what is hacky and unreliable about it?
  • Anonigan
    Anonigan about 14 years
    git update-index --unresolve was created in "ancient" times to allow to restore git diff --ours etc. after (accidental) git add confirming conflict resolution. It stuffs HEAD version (not version with automatically resolvable conflicts resolved) in stage #2, stuffs MERGE_HEAD version in stage #3, and doesn't put anything in stage #1, the ancestor version.
  • Adam
    Adam over 11 years
    So .. the answer is: "No, it's not possible, Git can easily corrupt the repository". Nice. (I'm in a situation where a file was committed from a remote machine that no-one currently has access to. "re-doing the merge" is physically impossible.
  • Anonigan
    Anonigan over 11 years
    @Adam: That shouldn't matter. Before doing merge git always downloads (fetches) commits into current repository, so instead of doing git pull <repo> you can do git merge <repo> which is shortcut for git merge <repo>/<branch>, and <repo>/<branch> is remote-tracking branch.
  • Adam
    Adam over 11 years
    @JakubNarębski The repository has files commmited with conflicts INSIDE them (I believe: someone did "git pull", and there were so many changes that they didnt see the "CONFLICT" message scroll off top of screen. Then they committed some other change, and BANG! repository is now corrupt). It is now impossible to get git to treat those as "conflicted" files any more. In the end, I used a text editor (and spent a LOT of time) re-writing the affected files :(.
  • Mikko Rantalainen
    Mikko Rantalainen about 11 years
    If somebody commits a mixture of conflicting merge and actual work, I fail to see how that's a case where "Git can easily corrypt the repository". Git has saved verbatim copy of the state this committer has asked, no matter how insane that state is. In the end, I'd probably redo the merge and then do git diff with the redone merge and this messed up merge commit. That diff hopefully contains roughly the changeset that was originally intended to be committed so you do not need to manually re-create all that work.
  • Mikko Rantalainen
    Mikko Rantalainen about 11 years
    @CharlesBailey Is it possible to add extra entry for a file in index to intentionally cause git to interpret a file as conflicting? I think that in some situations it would be nice to have fabricated conflicting versions in index after running custom merge driver...
  • Christian Neverdal
    Christian Neverdal almost 11 years
    Yes. This will cause Git to ask every time if the file was merged successfully instead of relying on the merge tool itself to report success or failure truthfully.
  • Superole
    Superole over 10 years
    so does that mean it will not 'git add' the files unless you answer yes? I also have 'mergetool.prompt = false' will that affect this?
  • Christian Neverdal
    Christian Neverdal over 10 years
    That is correct. I would think that mergetool.prompt would have to be true.
  • Gingi
    Gingi over 10 years
    If the index is clean because the unresolved file has been erroneously added, you can just reset it: git reset file; git checkout --conflict=merge file.
  • fourpastmidnight
    fourpastmidnight about 8 years
    @Gingi Awesome!! Just what I was looking for. I've been wanting to know how to do this for quite a while. You should make this an answer--I'd up-vote it!
  • user1133275
    user1133275 about 7 years
    s/lynx:.*\$/\n#/g