568

I've been using Git on Windows (msysgit) to track changes for some design work I've been doing.

Today I've been working on a different PC (with remote repo brian) and I'm now trying to merge the edits done today back into my regular local version on my laptop.

On my laptop, I've used git pull brian master to pull the changes into my local version. Everything was fine apart from the main InDesign document - this shows as a conflict.

The version on the PC (brian) is the latest one that I want to keep but I don't know what commands tells the repo to use this one.

I tried directly copying the file across onto my laptop but this seems to break the whole merge process.

Can anyone point me in the right direction?

Kevin Wilson
  • 7,753
  • 8
  • 35
  • 39

12 Answers12

1035

git checkout accepts an --ours or --theirs option for cases like this. So if you have a merge conflict, and you know you just want the file from the branch you are merging in, you can do:

$ git checkout --theirs -- path/to/conflicted-file.txt

to use that version of the file. Likewise, if you know you want your version (not the one being merged in) you can use

$ git checkout --ours -- path/to/conflicted-file.txt
mipadi
  • 398,885
  • 90
  • 523
  • 479
  • 66
    I had to run 'git reset HEAD path/to/conflicted-file.txt' on the file before using --ours, otherwise it seemed to have no effect. – Zitrax Oct 13 '11 at 13:48
  • 7
    @Zitrax Did you diff the file after running `git checkout --ours`? The man page suggests (IMHO) that checkout --ours/--theirs will remove the change from the "both modified, need merge" list and add it to the index, and I think that's not correct. I believe you will need to run `git add` after the checkout. – Tim Keating May 13 '13 at 21:06
  • 18
    Note: you still want to do "git add *conflicted-file.txt*" and "git commit". Handily, when I tried it, the commit message was pre-populated with a note about the conflict. – Edward Falk Jul 25 '14 at 22:34
  • 5
    phrasing of "the branch you are merging in" is dangerously close to "the branch you are merging into", i think that just dropping the preposition would be better : "the branch you are merging", which would reflect the git command as well (i.e. `git merge branch_name`). – andrybak Jun 07 '16 at 12:12
  • 19
    A couple of important points that's always missing in explanations of this topic. When doing rebase instead of merge, the meaning of `--their` and `--ours` are swapped, i.e. --their == currently checked-out branch and --ours is the branch, usually a remote branch, or path spec you're trying to merge into the current branch. The `[space]--[space]` option disambiguates to path spec between branch name and path spec that both happen to exist with the same name (e.g. an existing branch name is "abc" and a directory exists called "abc"). – BoiseBaked Dec 09 '16 at 16:54
  • 1
    If you know already that you want the _entire_ branch— _not specific files_ —then note that you can just specify e.g. `git checkout --ours .` …and if you want _all_ those changes `git add .` before you continue with what you were doing. (rebasing, merging, cherry-picking etc.) – PDK Apr 11 '17 at 11:42
  • I wanted to use this so badly, since I've heard of this method, but it didn't work for me? I was trying to solve a conflict in two `.png` files. The diff showed a binary difference. Anyone know why this didn't work in that case? – ArielSD Jan 16 '18 at 16:18
  • Even after `git checkout --theirs`, I receive a `warning: Cannot merge binary files:` when trying to `git pull`. – René Nyffenegger Apr 09 '18 at 17:40
  • This does not work when the file has been deleted in one repo. – Soerendip Dec 11 '18 at 20:30
  • If the file is binary, but you want to mix the two versions somehow, it's useful to use this answer's technic to get each version and open it side by side in whatever editor works for the particular file. Then "merge" the changes manually and save it. Atter that you can just add the save file and carry on with the merging or rebasing. – Alexandre Neto Feb 10 '22 at 11:24
  • I want to merge two binary files in Git and I was shown merge conflict with Binary files. The answers here solve conflict by keeping one version which is either --ours or --theirs ? But I want to solve merge conflict by keeping both branches versions of binary file and not just discarding other branch version . I want to keep a mix of both versions. How can I do that ? – acharyabibash Sep 18 '22 at 19:30
156

You have to resolve the conflict manually (copying the file over) and then commit the file (no matter if you copied it over or used the local version) like this

git commit -a -m "Fix merge conflict in test.foo"

Git normally autocommits after merging, but when it detects conflicts it cannot solve by itself, it applies all patches it figured out and leaves the rest for you to resolve and commit manually. The Git Merge Man Page, the Git-SVN Crash Course or this blog entry might shed some light on how it's supposed to work.

Edit: See the post below, you don't actually have to copy the files yourself, but can use

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

to select the version of the file you want. Copying / editing the file will only be necessary if you want a mix of both versions.

Please mark mipadis answer as the correct one.

VolkA
  • 34,983
  • 7
  • 37
  • 37
  • 1
    Thanks for that. I wasn't sure if there was some sort of build-in way to mark a file as the 'correct' one. Explains why I couldn't find the non-existent command though! – Kevin Wilson Nov 10 '08 at 18:35
  • Yep, thats a bit unintuitive - something like git resolve would be nice, but would also be an extra step ... – VolkA Nov 10 '08 at 20:22
129

You can also overcome this problem with

git mergetool

which causes git to create local copies of the conflicted binary and spawn your default editor on them:

  • {conflicted}.HEAD
  • {conflicted}
  • {conflicted}.REMOTE

Obviously you can't usefully edit binaries files in a text editor. Instead you copy the new {conflicted}.REMOTE file over {conflicted} without closing the editor. Then when you do close the editor git will see that the undecorated working-copy has been changed and your merge conflict is resolved in the usual way.

jpsecher
  • 4,461
  • 2
  • 33
  • 42
RobM
  • 8,373
  • 3
  • 45
  • 37
  • 12
    If the files are large or you don't want to risk opening binary in a text editor at all, you can hit ctrl+c at the mergetool prompt ("`Hit return to start merge resolution tool`") and git will leave the extra files in place. Then you can modify them or merge them in an external tool (useful for binary document formats like LibreOffice/OpenOffice/MSWord) and save the result back to the original filename. To inform git that the conflict is resolved, `git add` the original filename, and you can then finish the merge commit. – Felix Aug 24 '15 at 21:54
  • This worked flawlessly for me. Thanks! – Stephan Kristyn Jul 31 '23 at 16:41
23

To resolve by keeping the version in your current branch (ignore the version from the branch you are merging in), just add and commit the file:

git commit -a

To resolve by overwriting the version in your current branch with the version from the branch you are merging in, you need to retrieve that version into your working directory first, and then add/commit it:

git checkout otherbranch theconflictedfile
git commit -a

Explained in more detail

Joshua Flanagan
  • 8,527
  • 2
  • 31
  • 40
  • 1
    I prefer this variant over the accepted answer, because it is more intuitive, especially considering that the meaning of those "--ours" and "--theirs" is swapped in case of rebasing. – Antony Hatchkins May 22 '20 at 15:47
16

mipadi's answer didn't quite work for me, I needed to do this :

git checkout --ours path/to/file.bin

or, to keep the version being merged in:

git checkout --theirs path/to/file.bin

then

git add path/to/file.bin

And then I was able to do "git mergetool" again and continue onto the next conflict.

kris
  • 11,868
  • 9
  • 88
  • 110
6

From the git checkout docs

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
When checking out paths from the index, check out stage #2 (ours) or #3 (theirs) for unmerged paths.

The index may contain unmerged entries because of a previous failed merge. By default, if you try to check out such an entry from the index, the checkout operation will fail and nothing will be checked out. Using -f will ignore these unmerged entries. The contents from a specific side of the merge can be checked out of the index by using --ours or --theirs. With -m, changes made to the working tree file can be discarded to re-create the original conflicted merge result.

5

I came across a similar problem (wanting to pull a commit that included some binary files which caused conflicts when merged), but came across a different solution that can be done entirely using git (i.e. not having to manually copy files over). I figured I'd include it here so at the very least I can remember it the next time I need it. :) The steps look like this:

% git fetch

This fetches the latest commit(s) from the remote repository (you may need to specify a remote branch name, depending on your setup), but doesn't try to merge them. It records the the commit in FETCH_HEAD

% git checkout FETCH_HEAD stuff/to/update

This takes the copy of the binary files I want and overwrites what's in the working tree with the version fetched from the remote branch. git doesn't try to do any merging, so you just end up with an exact copy of the binary file from the remote branch. Once that's done, you can add/commit the new copy just like normal.

Brian Webster
  • 11,915
  • 4
  • 44
  • 58
4

This procedure is to resolve binary file conflicts after you have submitted a pull request to Github:

  1. So on Github, you found your pull request has a conflict on a binary file.
  2. Now go back to the same git branch on your local computer.
  3. You (a) re-make / re-build this binary file again, and (b) commit the resulted binary file to this same git branch.
  4. Then you push this same git branch again to Github.

On Github, on your pull request, the conflict should disappear.

david m lee
  • 2,547
  • 26
  • 14
1

I've come across two strategies for managing diff/merge of binary files with Git on windows.

  1. Tortoise git lets you configure diff/merge tools for different file types based on their file extensions. See 2.35.4.3. Diff/Merge Advanced Settings http://tortoisegit.org/docs/tortoisegit/tgit-dug-settings.html. This strategy of course relys on suitable diff/merge tools being available.

  2. Using git attributes you can specify a tool/command to convert your binary file to text and then let your default diff/merge tool do it's thing. See http://git-scm.com/book/it/v2/Customizing-Git-Git-Attributes. The article even gives an example of using meta data to diff images.

I got both strategies to work with binary files of software models, but we went with tortoise git as the configuration was easy.

BoJohDoh
  • 11
  • 1
1

If the binary is something more than a dll or something that can be edited directly like an image, or a blend file (and you don't need to trash/select one file or the other) a real merge would be some like:

I suggest searching for a diff tool oriented to what are your binary file, for example, there are some free ones for image files for example

and compare them.

If there is no diff tool out there for comparing your files, then if you have the original generator of the bin file (that is, there exist an editor for it... like blender 3d, you can then manually inspect those files, also see the logs, and ask the other person what you should include) and do output of the files with https://git-scm.com/book/es/v2/Git-Tools-Advanced-Merging#_manual_remerge

$ git show :1:hello.blend > hello.common.blend
$ git show :2:hello.blend > hello.ours.blend
$ git show :3:hello.blend > hello.theirs.blend
tyoc213
  • 1,223
  • 18
  • 21
0

I use Git Workflow for Excel - https://www.xltrail.com/blog/git-workflow-for-excel application to resolve most of my binary files related merge issues. This open-source app helps me to resolve issues productively without spending too much time and lets me cherry pick the right version of the file without any confusion.

Sidd Thota
  • 2,040
  • 1
  • 20
  • 24
0

my case seems like a bug.... using git 2.21.0

I did a pull... it complained about binary files:

warning: Cannot merge binary files: <path>
Auto-merging <path>
CONFLICT (content): Merge conflict in <path>
Automatic merge failed; fix conflicts and then commit the result.

And then nothing in any of the answers here resulted in any output that made any sense.

If I look at which file I have now... it's the one I edited. If I do either:

git checkout --theirs -- <path>
git checkout --ours -- <path>

I get output:

Updated 0 paths from the index

and I still have my version of the file. If I rm and then checkout, It'll say 1 instead, but it still gives me my version of the file.

git mergetool says

No files need merging

and git status says

    All conflicts fixed but you are still merging.
    (use "git commit" to conclude merge)

One option is to undo the commit... but I was unlucky and I had many commits, and this bad one was the first. I don't want to waste time repeating that.

so to solve this madness:

I just ran

git commit

which loses the remote version, and probably wastes some space storing an extra binary file... then

git checkout <commit where the remote version exists> <path>

which gives me back the remote version

then edited the file again...and then commit and push, which again probably means wasting space with another copy of the binary file.

Peter
  • 3,067
  • 2
  • 17
  • 18
  • In my case, after trying to `git checkout --ours ` I've received `Updated 0 paths from the index `. I've fixed that with `git add ` command, which does the same. – Andriy Mar 07 '20 at 13:30