Git

How to Resolve Merge Conflicts in Binary Files in Git

4 min read by DebuggedIt

Quick answer

Git flags a conflict on a binary file β€” an image, a compiled asset, a PDF, a SQLite database β€” and instead of showing readable conflict markers, it just tells...

Git flags a conflict on a binary file β€” an image, a compiled asset, a PDF, a SQLite database β€” and instead of showing readable conflict markers, it just tells you the files differ. Binary conflicts can't be resolved by editing text, so the workflow is different from a normal merge conflict.

The Problem

During a merge, rebase, or pull, Git reports a conflict on a non-text file:

$ git merge feature/new-assets
warning: Cannot merge binary files: assets/logo.png (HEAD vs. feature/new-assets)
Auto-merging assets/logo.png
CONFLICT (content): Merge conflict in assets/logo.png
Automatic merge failed; fix conflicts and then commit the result.

Running git status afterward shows the file as unmerged, but opening it in a text editor is useless:

$ git status
Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   assets/logo.png

Why It Happens

Git's merge algorithm works line by line on text content. Binary files have no meaningful "lines" to diff, so Git can't automatically combine two versions the way it does with source code. A conflict is flagged whenever:

  • Both branches modified the same binary file since the last common ancestor (two different versions of the same image, database file, or compiled binary).
  • The file's content changed on both sides, even if the change seems trivial (a re-exported image with the exact same visual content can still have different bytes).
  • .gitattributes doesn't declare the file type as binary, so Git tries a text-style merge first and fails messily instead of cleanly flagging it as binary from the start.

The Fix

Since there's no line-level merge possible, you have to pick one version outright. To keep your current branch's version:

git checkout --ours assets/logo.png
git add assets/logo.png

To take the incoming branch's version instead:

git checkout --theirs assets/logo.png
git add assets/logo.png

On newer Git versions, the equivalent restore syntax is:

git restore --source=HEAD --staged --worktree assets/logo.png   # ours
git restore --source=MERGE_HEAD --staged --worktree assets/logo.png   # theirs

If neither version is correct and you need a manually merged result (for example, a design file where you need pieces of both), replace the file yourself with the correct final version, then stage it:

cp ~/Downloads/logo-final.png assets/logo.png
git add assets/logo.png

Once every conflicted binary file is resolved and staged, finish the merge:

git commit

To avoid messy binary conflict output in the future, mark binary file types explicitly in .gitattributes so Git treats them correctly from the start:

*.png binary
*.pdf binary
*.sqlite binary

Still Not Working?

If you're conflicted on a large binary asset repeatedly (design files, video, datasets), consider that Git itself isn't well suited to versioning large binaries β€” every version is stored in full in the repo history, which bloats .git over time. Tools like Git LFS track binary files as lightweight pointers instead, which avoids repeated painful binary merges and keeps clone times fast:

git lfs track "*.png"
git add .gitattributes

It also helps to set a merge strategy specifically for binary paths so future conflicts resolve predictably instead of always requiring manual intervention. In .gitattributes, you can tell Git to always keep the current branch's version automatically for certain files, which is useful for generated or environment-specific binaries that should never be merged at all:

*.lockb merge=ours

Then register the ours merge driver in your Git config so the attribute actually takes effect:

git config merge.ours.driver true

With that in place, Git will silently keep the current branch's version of matching files during any future merge instead of flagging a conflict β€” appropriate for files like compiled lockfiles or IDE-generated binaries that shouldn't be manually reconciled between branches in the first place.

Finally, if you're not sure whether a given conflicted file is actually binary or just being misdetected as one, check Git's own classification directly:

git check-attr binary assets/logo.png

If Git treated a text file as binary by mistake (this happens with some encodings or unusual line endings), you can override it explicitly and get a normal line-based merge instead:

echo "assets/data.csv text" >> .gitattributes