Real-world examples of examples of merge conflict in Git
Let’s start with the most common of all real examples of merge conflict in Git: two people edit the same line in the same file on different branches.
You’re on feature/login-ui, your teammate is on feature/login-copy. Both branches start from main at the same commit.
main originally has:
// login.js
const BUTTON_TEXT = "Log in";
On feature/login-ui, you change the label:
const BUTTON_TEXT = "Sign in";
On feature/login-copy, your teammate changes it differently:
const BUTTON_TEXT = "Log in to your account";
When you try to merge feature/login-copy into feature/login-ui (or both into main), Git can’t decide which new line to keep. You see this classic conflict marker:
const BUTTON_TEXT = "<<<<<<< HEAD
Sign in
=======
Log in to your account
>>>>>>> feature/login-copy";
This is one of the best examples of Git’s behavior: Git is very good at merging when changes touch different lines. The moment two branches rewrite the same line, Git asks you to be the adult in the room and choose.
The fix here is simple: pick one version, or create a new line that combines both intents, then remove the conflict markers and commit.
Examples of examples of merge conflict in Git from formatting tools
In modern 2024–2025 workflows, auto-formatters and linters are a surprisingly rich source of merge conflict examples. Tools like Prettier, Black, ESLint, or go fmt rewrite code structure, which can collide with human edits.
Imagine this timeline:
- You run a formatter on
main, which rewritesuser.jsinto multiple lines. - A teammate, on a branch that did not run the formatter yet, edits the old, unformatted version.
- Later, you merge their branch into
main.
Git sees two very different versions of the same file: one heavily reformatted, the other lightly edited but still in the old layout. Even if the logic change is tiny, the formatter’s edits touch many of the same lines, creating textbook examples of merge conflict in Git.
It might look like this:
<<<<<<< HEAD
function getUserName(user) {
return user && user.profile && user.profile.name;
}
=======
function getUserName(user) { return user.profile.name; }
>>>>>>> feature/quick-fix
The underlying intent is compatible, but the layout is not. The best examples of avoiding this kind of conflict usually involve:
- Running the formatter on a dedicated branch and merging it quickly.
- Enforcing format-on-save or pre-commit hooks so everyone’s code looks the same.
- Avoiding big, pure-formatting PRs mixed with feature work.
These are boring habits, but they dramatically cut down on noisy conflicts.
Merge conflict examples from parallel feature development
Real projects don’t have one feature at a time; they have many. That’s where richer examples of merge conflict in Git show up: two features reshaping the same area of the codebase.
Say you have a checkout.js file. Team A builds discount support, Team B builds tax calculation changes. Both touch the calculateTotal function.
Team A branch:
function calculateTotal(cart) {
const subtotal = sum(cart.items);
const discount = getDiscount(cart.user, subtotal);
return subtotal - discount;
}
Team B branch:
function calculateTotal(cart) {
const subtotal = sum(cart.items);
const tax = calculateTax(subtotal, cart.region);
return subtotal + tax;
}
Merge them without coordination and Git shrugs:
<<<<<<< HEAD
function calculateTotal(cart) {
const subtotal = sum(cart.items);
const discount = getDiscount(cart.user, subtotal);
return subtotal - discount;
}
=======
function calculateTotal(cart) {
const subtotal = sum(cart.items);
const tax = calculateTax(subtotal, cart.region);
return subtotal + tax;
}
>>>>>>> feature/tax-update
This is a more interesting example of merge conflict in Git because there is a correct combined version, but Git can’t infer business logic. A human has to decide something like:
function calculateTotal(cart) {
const subtotal = sum(cart.items);
const discount = getDiscount(cart.user, subtotal);
const taxable = subtotal - discount;
const tax = calculateTax(taxable, cart.region);
return taxable + tax;
}
As teams grow, these real examples become more common. They’re less about syntax and more about product decisions. Git is just surfacing the disagreement.
Rename and delete: subtle examples include path-level conflicts
Not all conflicts are about lines of code. Some of the most confusing examples of merge conflict in Git involve file moves and deletions.
Picture this:
- Branch A renames
config.jsontoconfig.default.jsonand updates references. - Branch B deletes
config.jsonbecause it’s moving to environment variables.
When you merge B into A, Git says: “On one side this file was renamed; on the other it vanished. Now what?” You’ll see a conflict like:
CONFLICT (modify/delete): config.json deleted in feature/env-config and
modified in HEAD. Version HEAD of config.json left in tree.
Or with a rename detection:
CONFLICT (rename/delete): config.json renamed to config.default.json in HEAD
and deleted in feature/env-config. Version HEAD of config.default.json left in tree.
These are great real examples because they highlight that Git tracks content and paths, not just text. The resolution depends on product direction:
- If the team truly moved to env vars, you keep the deletion and remove references.
- If you still need defaults, you keep the renamed file and maybe add a migration path.
The key pattern: when one branch deletes and another edits or renames the same file, expect a conflict and a decision.
Rebase vs. merge: examples of conflicts during history rewriting
So far, we’ve been talking about git merge. In modern workflows, git rebase is just as common, especially with GitHub’s “rebase and merge” or linear-history policies. The examples of merge conflict in Git during a rebase feel similar, but the mental model is different.
Imagine you branched off main a week ago, made three commits, and now main has moved on. You run:
git fetch origin
git rebase origin/main
Git replays your commits on top of the new origin/main. Any commit that touches lines changed on main can trigger a conflict.
For example, if main updated an API endpoint:
// main
fetch("/api/v2/users")
And one of your commits (written against the old API) still calls:
fetch("/api/v1/users")
During the rebase, Git stops and shows a conflict in the file containing that call. You fix it to use /api/v2/users, run git add, then git rebase --continue.
The difference between these examples and merge-based conflicts is mostly about context:
- With merge, you’re combining two branches and keeping both histories.
- With rebase, you’re rewriting your branch as if it were created from the latest
main.
In both cases, the conflict markers look the same, but with rebase you resolve them commit-by-commit instead of all at once.
Binary files: painful examples of merge conflict in Git
Let’s talk about the examples of merge conflict in Git that nobody enjoys: binary files. Think design assets, PDFs, or large data snapshots.
Git can’t meaningfully merge binary files line-by-line. If two branches both change design/homepage.fig or logo.png, you’ll usually see something like:
CONFLICT (content): Merge conflict in design/homepage.fig
There won’t be conflict markers inside the file because Git can’t show you a human-readable diff. Your options are limited:
- Pick one side (
git checkout --oursor--theirsfor that path). - Save both versions under different names and let a designer or stakeholder decide.
In 2024–2025, with more teams storing design system artifacts, ML models, or large assets in Git (or Git LFS), these become more frequent real examples. They’re a good reminder that Git is text-first; anything else needs extra process.
CI bots and auto-generated files: modern conflict examples
Another modern example of merge conflict in Git comes from automation. CI bots that update lockfiles (package-lock.json, yarn.lock, poetry.lock), generated code, or documentation can create conflicts with human edits.
Imagine:
- A dependency update bot opens a PR that bumps a library and rewrites
package-lock.json. - At the same time, a developer updates dependencies manually on a feature branch.
When both land, Git sees two completely different package-lock.json states. Lockfiles are noisy by design, so conflicts there can be intimidating. Yet they’re still just text conflicts.
Typical resolution pattern:
- Decide which branch represents the intended dependency graph.
- Re-run the package manager (
npm install,yarn install, etc.) on that branch. - Commit the regenerated lockfile as the single source of truth.
These are some of the best examples for learning to trust tools: often the fix is “re-run the generator,” not “hand-edit the mess.”
Real examples of merge conflict in Git from cherry-picking and hotfixes
Cherry-picking is another fertile ground for examples of merge conflict in Git, especially with production hotfixes.
Scenario:
- You fix a production bug on
hotfix/production-crashand merge it intomain. - Later, you try to cherry-pick that same commit into
release/1.2.
If release/1.2 diverged from main—for example, the function you patched was refactored there—you’ll hit conflicts.
Say the hotfix commit changed:
function getUser(id) {
return db.users.findById(id);
}
But in release/1.2, that function was already rewritten:
async function getUser(id) {
return await userRepo.getById(id);
}
Cherry-picking tries to apply the original patch and collides with the new function body. You now have to manually transplant the intent of the hotfix into the refactored version.
These real examples highlight a theme: Git can’t understand business logic or runtime behavior. It only knows text. When history diverges, you become the translator.
Trends in 2024–2025: why merge conflicts feel different now
Merge conflicts haven’t changed much since Git’s early days, but the context around them has.
Some recent trends that shape modern examples of merge conflict in Git:
- More automation: Dependabot-style tools, code formatters, and documentation generators introduce conflicts that are machine vs. human, not just human vs. human.
- Microservices and monorepos: Large monorepos mean many teams touching the same modules, increasing the odds of parallel edits.
- AI-assisted coding: Tools that suggest entire blocks of code can cause larger, overlapping changes that collide more often.
Good engineering hygiene still matters. Concepts like frequent integration, small pull requests, and clear ownership are echoed in long-standing software engineering guidance from organizations like NIST and academic software engineering programs (for example, at MIT). They don’t eliminate conflicts, but they make the examples you run into smaller and easier to reason about.
Practical habits to reduce painful conflicts
Looking across all these examples of examples of merge conflict in Git, a few patterns stand out.
- Integrate early and often. Long-lived branches drift. The longer you wait to merge or rebase, the more likely your examples include large, ugly conflicts.
- Keep formatting changes separate. Run formatters in their own short-lived branches, or enforce format-on-save so your team doesn’t fight over whitespace.
- Avoid editing generated files by hand. Let tools regenerate them instead of patching them manually.
- Communicate about hotspots. If you know a core file is being heavily refactored, announce it. Coordinate large changes.
None of this is glamorous, but it turns nasty conflict stories into minor speed bumps.
FAQ: common questions about merge conflict examples
What are some simple examples of merge conflict in Git for beginners?
Simple examples include two developers editing the same line in a file, one developer renaming a file while another edits it, or a formatter reflowing code while someone else changes a nearby line. All of these examples of conflict are small enough to understand by reading the diff and the conflict markers.
Can you give an example of a merge conflict that Git can resolve automatically?
Yes. If one branch edits line 10 and another edits line 50 of the same file, Git usually merges them automatically with no conflict. That’s an example of Git’s three-way merge working as intended: the changes don’t overlap, so Git combines them safely.
Are binary file conflicts handled differently than text conflicts?
Yes. With text, Git inserts conflict markers so you can edit and resolve them. With most binary files, Git can’t show a readable diff, so you typically choose one version or save both under different names and have a human decide later.
How can I practice with real examples of merge conflict in Git safely?
Create a test repository, make a main branch, then create two feature branches from it. Edit the same line differently on each branch, or rename a file on one branch and delete it on another. Then try merging them. These controlled examples of conflict let you practice without risking production code.
Do tools exist to help visualize and resolve complex conflicts?
Yes. Git ships with git mergetool integration, and popular GUI tools like VS Code, GitKraken, and others provide side-by-side views. Many teams also use external diff tools taught in university software engineering courses, such as those referenced in Carnegie Mellon’s SEI resources, to reason about larger, real examples of merge conflict in Git.
Related Topics
Real‑world examples of branch conflict examples in Git
Real-world examples of merge conflict handling examples in GitHub
Git examples of rebasing with conflicts: 3 practical examples for real teams
Real-world examples of examples of merge conflict in Git
When Your Git History Turns Into a Battlefield
Explore More Version Control Conflicts
Discover more examples and insights in this category.
View All Version Control Conflicts