š§ Listen to this article: English
š Read this in your language: ą¤¹ą¤æą¤ą¤¦ą„ Ā· தமிஓ௠· ą°¤ą±ą°²ą±ą°ą± Ā· ą²ą²Øą³ą²Øą²” Ā· ą“®ą“²ą“Æą“¾ą“³ą“ Ā· ą¬ą¬”଼ିଠ· ę„ę¬čŖ Ā· äøę
Merge conflicts are annoying enough in code. When they happen in an image file, most people freeze ā there is no "diff view" for a picture, and the usual fix-it-in-the-browser button on GitHub simply is not there. This post walks through a real case of exactly that: what did not work, and what did.
As of today, August 29, 2026, this is worth understanding because more small teams run content-heavy websites through Git, with non-technical people pushing text and image changes through a desktop app. That mix ā plain-language content editors, binary files, and a real deploy pipeline ā is exactly where this problem shows up.
The setup: two branches, one shared image
The project uses a simple two-branch workflow. staging is where day-to-day work happens ā a content editor pushes changes there freely, and it deploys to a preview site automatically. main is the real live site, updated only when a reviewed Pull Request from staging is merged in.
The team had also recently converted the site's images to WebP, a modern format much smaller than PNG or JPG at the same visual quality. Every image now existed as a pair: the original .png, and a matching .webp, wired together with an HTML <picture> element so WebP-capable browsers get the small file automatically, with everything else falling back to the original.
Then two things happened on two different branches at almost the same time: someone made a small, direct edit to one product screenshot on main, bypassing the normal review flow, while the content editor separately uploaded a genuinely new version of that same screenshot through staging. Both edits touched the same file path. Neither side knew about the other.
Why GitHub's website could not fix this
When the content editor opened a Pull Request to bring the staging update into main, GitHub flagged it immediately: "This branch has conflicts that must be resolved." Normally, clicking through gives you a web-based editor showing both versions of a text file side by side, so you can pick which lines to keep.
That editor does not exist for images. GitHub's browser-based conflict resolution only understands line-based text ā code, markdown, config files. A PNG or WebP file has no "lines" to compare. There was no button, no view, no path through the website that could resolve this, no matter how carefully anyone clicked around. Worth saying plainly: the content editor was not doing anything wrong. The tool genuinely had no way to solve this particular problem.
The hidden second problem
Fixing this required pulling both versions of the file locally and comparing them directly ā which is where a sneakier problem turned up. The new screenshot on staging was a real update, bigger and higher-resolution than before. But its paired WebP file had not been touched in a long time ā the dimensions did not even match. The new PNG was 1024 by 1024 pixels; the WebP sitting next to it was still 750 by 750, left over from an earlier version of the image entirely.
That meant simply "picking a side" in the conflict ā keeping either version wholesale ā would have shipped a mismatched pair. The PNG would show the new screenshot, but any visitor whose browser prefers WebP (most modern browsers) would silently see an old, wrong image. The conflict message would disappear; the actual bug would ship unnoticed.
Step 1: Compare both versions properly
The first step was not resolving anything ā it was comparing file sizes and dimensions on both branches against their common starting point, to understand what had actually changed and where.
git fetch origin
git diff --stat origin/main origin/staging -- path/to/image.png path/to/image.webp
This showed both branches had modified the file independently since it was last shared ā a genuine three-way divergence, not simply "one side is newer."
Step 2: Identify which version was actually correct
Opening both PNGs side by side confirmed the staging version was the real, intended update, not a mistake or a corrupted file.
Step 3: Regenerate the WebP from the correct source
Instead of trying to merge two different binary files ā which is not possible ā the fix was to treat the WebP as something derived from the PNG, not a separate file to reconcile:
cwebp -q 82 image.png -o image.webp
This produced a fresh WebP at the correct 1024 by 1024 dimensions, properly matching the new PNG. -q 82 is just a quality setting ā a good balance between file size and sharpness.
Step 4: Complete the merge and verify
git checkout staging
git merge origin/main
git checkout --ours path/to/image.png # keep the staging PNG
cp image-regenerated.webp path/to/image.webp # use the freshly regenerated WebP
git add path/to/image.png path/to/image.webp
git commit
git push origin staging
After this, the Pull Request showed as clean and mergeable, and the live site correctly served the new screenshot to every visitor, WebP-capable or not.
Methods that were considered, and rejected
A few faster-looking shortcuts came up along the way, each worth knowing about, and worth knowing why it was not used.
Picking a version in a desktop Git client. Most Git desktop apps let you resolve a binary conflict by choosing "use my version" or "use theirs" ā no comparison, just a wholesale pick. A non-technical team member could do this themselves. The catch: it would have kept the stale, mismatched WebP file, shipping the same silent bug described above. Fast, but wrong.
Forcing the merge with a strategy flag. From the command line, git merge origin/main -X ours (or -X theirs) tells Git to automatically resolve any conflict by picking one whole side, for every file, without stopping to ask:
git merge origin/main -X ours
This has the exact same flaw as picking a version in a desktop app ā Git treats a conflicting binary file as one indivisible block, so it cannot reach in and fix just the mismatched half.
Deleting the file from the base branch first. The theory: if the live branch no longer has the file, there is nothing to conflict with, so the merge should go through cleanly. This was tested directly in an isolated branch rather than just assumed:
git rm image.png image.webp
git commit -m "test: delete file"
git merge origin/staging
The result was not a clean merge. Git remembers the file existed at the point the branches split, so deleting it on one side while it changes on the other still produces a conflict ā a "modify/delete" conflict, with its own warning message. It relabels the problem rather than skipping it.
Force-pushing over the conflict. A more drastic option is overwriting the live branch entirely with the other branch's history via a force push. This is not really conflict resolution ā it is discarding one side's changes outright, risking a silent loss of someone else's real work. On a branch that deploys to a live site, that is a genuinely risky move, not a shortcut worth taking.
Conclusion
Binary file conflicts ā images, PDFs, compiled files, anything that is not plain text ā cannot be resolved the way code conflicts can. There is no line-by-line diff to reason about. The only real options are picking one version wholesale, or, when the two versions are actually a matched pair like an image and its optimized copy, regenerating the derived file from the correct source. Understanding which situation you are in is most of the battle.
Merits
- Regenerating the derived file (the WebP, in this case) guarantees consistency instead of guessing which side to trust.
- Testing a risky-looking shortcut in an isolated branch first, before trusting it, catches wrong assumptions cheaply.
- Keeping the original file format around as a fallback (via a
<picture>element, in this case) means even a temporarily broken optimized copy never fully breaks the page for a visitor.
Demerits
- None of the fast options (pick-a-version, forced merge strategy, deleting and re-merging) actually solve a mismatched-pair problem ā they only make the conflict message disappear.
- Fixing this properly required direct server or command-line access and an image-conversion tool, which is outside what a browser-only or desktop-app-only workflow can do.
- The underlying cause ā a direct edit to the live branch, bypassing the normal review flow ā is a process gap that a one-time technical fix does not prevent from happening again.
Caution
This article is educational and describes a real situation in general terms; specific file names, paths, and identifiers have been generalized. Commands shown here can modify or discard real files and branch history ā always test in an isolated branch or a throwaway copy first, make sure you understand which direction "ours" and "theirs" point to in your specific situation, and confirm you have a backup or a way to recover before running anything that resolves a conflict by force. Verify any command against your own repository's actual state before relying on it.
Frequently asked questions
- Why can't GitHub's website resolve conflicts in image files? ā Its browser-based conflict editor only understands line-based text; there is no way to compare or merge binary data like a PNG or WebP through that interface.
- What is a "modify/delete" conflict? ā It happens when one branch deletes a file and another branch changes it since they last shared history; Git flags this rather than guessing which change should win.
- Does deleting a file from one branch avoid a merge conflict? ā No. If the file existed when the branches diverged, deleting it on one side while it is modified on the other still produces a conflict, just a different type.
- Is "use my version" or "use theirs" in a desktop Git client safe for an image conflict? ā It resolves the conflict, but only by keeping one file as-is; a derived counterpart like a WebP copy will not be fixed automatically.
- What does
git merge -X oursactually do? ā It tells Git to automatically resolve every conflicting file by keeping the current branch's version, for the whole merge, without stopping to ask. - Why regenerate the WebP file instead of just merging it? ā It is a compressed derivative of the original image; there is no meaningful way to "merge" two different compressed versions, so recreating it from the correct source is the only correct fix.
- How do teams avoid this kind of conflict in the first place? ā By keeping one consistent flow where all changes go through a working branch before reaching the live branch, instead of allowing direct edits to the live branch from multiple places.
Tags
#git #github #webp #imageoptimization #webdev #devops #versioncontrol #mergeconflict #cicd #webperformance
Linux Server Hardening Checklist
30 practical steps to take a fresh Linux box from default to defensible. Enter your email ā you'll get the PDF instantly, plus new posts on Linux, security & AI.
Free. No spam ā unsubscribe in one click.


Responses
Sign in to leave a response.