views:

252

answers:

4

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?

A: 

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.

VonC
Indeed you can. Merely doing a git add <file> will remove the marker and you are then free to commit.http://pastebin.com/KKLtCZ35
Christian Jonassen
@Christian: interesting (I have amended the answer to reflect it), but will the `git mergetool` detect it and re-trigger a merge?
VonC
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.
Charles Bailey
@Christian: completed my answer after Charles's comment.
VonC
A: 

@VonC: I did not create an account at first (I have now), so I could not post a comment. Invoking git mergetool does not detect it, it seems:

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
>>>>>> 881d60f5f738bc5716f5c9a9384e262b535717fd:README
lynx:~/test_clone$ git mergetool
merge tool candidates:  opendiff emerge vimdiff
No files need merging
lynx:~/test_clone$

git mergetool can accept a file name, but that does not work either:

Auto-merged README
CONFLICT (content): Merge conflict in README
Automatic merge failed; fix conflicts and then commit the result.
caracal:~/test_clone2$ git mergetool
merge tool candidates:  opendiff emerge vimdiff
Merging the files: README

Normal merge conflict for 'README':
  {local}: modified
  {remote}: modified
Hit return to start merge resolution tool (emerge): 
caracal:~/test_clone2$ ls
#*merge*#145962bz#  README  README~  README.orig
caracal:~/test_clone2$ git mergetool
merge tool candidates:  opendiff emerge vimdiff
No files need merging
caracal:~/test_clone2$ git mergetool README
merge tool candidates:  opendiff emerge vimdiff

README: file does not need merging
caracal:~/test_clone2$ ls
#*merge*#145962bz#  README  README~  README.orig
caracal:~/test_clone2$ 

Note here also that I did not commit after exiting git mergetool.

Christian Jonassen
Just completed my answer after Charles's comment.
VonC
+2  A: 

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.

Jakub Narębski
Heh, I was just writing this response. ;-)
ebneter
what is hacky and unreliable about it?
Christian Jonassen
`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.
Jakub Narębski
A: 

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

Christian Jonassen