If the conflict happen on a binary or any non-text files that can't be resolved by using text editor, I should use git checkout --theirs
or git checkout --ours
instead, then add them into the staging area.
But, if I just do nothing, add those unmerged binaries into staging area directly, without resolving the conflict, without choosing a proper version, which version will be added into staging area ? Ours or theirs ?
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
both modified: test.bin
both modified: test.a
If the conflict happen on a binary or any non-text files that can't be resolved by using text editor, I should use
git checkout --theirs
orgit checkout --ours
instead ...
This is not necessarily true. Just as with plain text files, where sometimes the correct resolution is in fact a combined change, the correct resolution of some binary files may be a combined change. It's just that Git cannot do this for you. The only way to do it correctly may be to find a source file or files, and some sort of source-to-binary translator. You may need to combine the source changes, compile / translate the result to a new, third binary, and use that.
Nonetheless, this question has an answer. It just may be pointless to study and memorize it.
But, if I just do nothing, add those unmerged binaries into staging area directly ...
What git add
does is to copy whatever is in the work-tree into the index / staging-area at slot zero, removing any higher-stage entries. What you have during the conflict is three different binaries, in the index / staging area, but using slots 1 (merge base), 2 (ours), and 3 (theirs).
Hence, this just means Copy the work-tree file into slot zero and remove the entries in slots 1, 2, and 3. So the question is the same as:
The answer to that is in both the git merge
documentation and the gitattributes documentation. This makes it hard to read.
The first one says, regarding the recursive
and resolve
strategies, that there are additional arguments that affect the result. These additional arguments are the -X ours
and -X theirs
arguments, which mean:
ours
This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. Changes from the other tree that do not conflict with our side are reflected to the merge result. For a binary file, the entire contents are taken from our side.
...
theirs
This is the opposite of ours; note that, unlike ours, there is no theirs merge strategy to confuse this merge option with.
The gitattributes documentation adds this:
Performing a three-way merge
...
The attributemerge
affects how three versions of a file are merged when a file-level merge is necessary ...
and then goes on to say that most of them "[k]eep the version from your branch in the work tree". So in general the work-tree matches index-slot-2, which you can test by doing git checkout-index --temp --stage=2 test.bin
and comparing the resulting file to test.bin
.
It's not clear whether such attributes override -X theirs
; you will have to test this, if you set your own merge
attributes and use -X theirs
, by comparing what's in the work-tree against what's in index slots 2 and 3.
In general, though, most approaches mostly leave the "ours" version in the work-tree. If that's appropriate, you can use git add
to copy the work-tree version back to slot zero and erase slots 1-3, marking the file as resolved. Just be sure that if you have used -X theirs
and/or some sort of interesting merge
setting, that you know what you are doing and have double checked everything.
(Your best bet, of course, is to avoid merging binary files this way.)