← All posts

Git Merge, Rebase & Squash — Part 5: Conflicts, ours/theirs, and Merge Strategies

Data-Sci & Digital HealthBasic InfoTech & Computing Nexus
Git Merge, Rebase & Squash — Part 5: Conflicts, ours/theirs, and Merge Strategies
On this page

Abstract

Version control systems typically automate branch integration, but concurrent modifications to identical lines demand manual conflict resolution. Understanding these underlying mechanics prevents unintended code loss. When integrating branches, a standard merge halts for resolution just once, whereas a rebase replays individual commits and may repeatedly surface the same discrepancy. Resolving these clashes involves selecting file versions via the ours or theirs commands; however, a rebase inverts their meanings, treating the base branch as ours. Furthermore, users must distinguish between merge methods, like squash or fast-forward, and underlying merge strategies. Git defaults to the ort strategy for two-head merges, while octopus combines multiple non-conflicting branches, and subtree integrates differing repository roots. Crucially, operators must not conflate the -s ours strategy, which discards incoming content entirely, with the -X ours or -X theirs options, which act as automated tie-breakers that risk silently dropping code. This article outlines these workflows to ensure developers safely arbitrate integrations.


Infographic visual summary of Git Merge, Rebase & Squash — Part 5: Conflicts, ours/theirs, and Merge Strategies
Visual summary · ภาพสรุป

Parts 1 to 4 assumed the happy path — that Git could combine your work automatically. This part is about what happens when it cannot. When two branches change the same lines, Git stops and hands the decision back to you, and the way a conflict appears (and how you resolve it) is different for merge and for rebase. We then open the machinery Git uses to combine branches: the difference between a merge method (what you click in a UI) and a merge strategy (the algorithm underneath), plus the handful of strategies and strategy options that occasionally matter — ort, octopus, -s ours, -X ours/-X theirs, and subtree.

By the end you will be able to resolve a conflict during both merge and rebase, use ours/theirs without being fooled by their reversed meaning under rebase, and tell apart two dangerous-looking siblings that behave very differently: -s ours and -X ours.

Conflicts during a merge

Suppose both branches changed the same line. You start an ordinary merge:

git switch main
git merge feature/login

Git cannot decide which version should win, so it reports a conflict:

CONFLICT (content): Merge conflict in app.js

The reason is visible in the graph — main and feature/login both edited the same line after diverging at C:

D E A B C F feature/login (edits the same title line) main (edits the title line)
Both branches edited the same line after diverging at C, so merging feature/login into main raises a conflict in app.js.

Inside the file, Git marks the clash with conflict markers:

<<<<<<< HEAD
const title = "Main version";
=======
const title = "Feature version";
>>>>>>> feature/login

Edit the file down to the single version you actually want:

const title = "Final version";

Then stage the resolved file and complete the merge:

git add app.js
git commit

On newer Git versions you can finish with:

git merge --continue

Aborting a merge

If you would rather back out and return to where you started:

git merge --abort

Conflicts during a rebase

Now start a rebase from the feature branch:

git switch feature/login
git rebase main

When a conflict stops the rebase, inspect the state:

git status

Fix the file, then continue:

git add app.js
git rebase --continue

Skipping the current commit

git rebase --skip

Use this only when you are sure the commit being replayed is no longer needed.

Aborting the whole rebase

git rebase --abort

This returns you to exactly the state you were in before the rebase began.

Why a rebase can conflict several times

This is the key mental difference. A rebase replays your commits one at a time, so the same underlying disagreement can surface at every replayed commit, whereas a merge usually asks you to resolve it just once:

merge — resolve once D E F A B C G M one conflict round, at M rebase — replay commit by commit A B C G D′ E′ F′ a conflict can appear at each replayed commit
Merge resolves the disagreement once, at the merge commit M; rebase replays D, E, F one at a time onto G, so a conflict can appear at each replayed commit.

So a long-running feature branch that conflicts with heavy changes on main may cost you several rounds of the same fix under rebase — something to weigh when choosing between the two.

ours and theirs (and why rebase flips them)

When you hit a conflict you can take one whole side of a file instead of hand-editing it. During a merge:

git checkout --ours app.js

means "use the file from the current branch", while:

git checkout --theirs app.js

means "use the file from the branch being merged in". Newer Git offers the same thing through restore:

git restore --ours app.js
git restore --theirs app.js

Then stage and continue as usual:

git add app.js
git merge --continue

The rebase inversion — a safety warning

During a rebase, ours and theirs appear reversed from the intuition you built during a merge.

Because a rebase replays your commits on top of the base branch, Git treats the base as the side it is building onto:

So always open the actual file and confirm its contents. Never pick a side by its name alone.

Merge strategy is not the same as merge method

Merge method

The choice most people make in a UI or at the top level:

Fast-forward
Merge commit
Squash merge
Rebase and merge

Merge strategy

The internal algorithm Git uses to compute the combination. You select it with:

git merge -s <strategy>

The method is what you want the history to look like; the strategy is how Git computes the merged tree. They are separate choices, and most of the time you set the method and let Git pick the strategy.

The ort strategy (the modern default)

This is the main strategy for merging two branches:

git merge -s ort feature/login

You normally never need to type it — Git selects it for you automatically. ort stands for the idea "Ostensibly Recursive's Twin". It is well suited to:

octopus: merging more than two branches

The octopus strategy merges more than two branches at once:

git merge feature-a feature-b feature-c
M feature-a feature-b feature-c
An octopus merge: a single merge commit M joins feature-a, feature-b and feature-c at once.

It is typically used to combine branches that do not conflict. If any conflict needs manual resolution, octopus refuses the merge and you must fall back to merging the branches one at a time instead.

-s ours: keep this branch, record the merge

git merge -s ours obsolete-branch

This strategy:

It must not be confused with:

git merge -X ours feature

These two are genuinely different things:

Aspect -s ours (strategy) -X ours (strategy option)
What gets merged Nothing from the other branch — its content is discarded completely Everything merges normally
Effect on conflicts Not applicable — no real content merge happens Only conflicting hunks are resolved toward the current branch
Resulting tree Identical to the current branch, but a merge commit records the other branch as merged A normally merged tree, biased to your side wherever hunks collide
Typical use Marking an obsolete branch as merged without taking any of its changes Auto-resolving conflicts toward your side during a real merge

-X ours and -X theirs: conflict tie-breakers

git merge -X ours feature/login

On each conflicting hunk, prefer the current side.

git merge -X theirs feature/login

On each conflicting hunk, prefer the incoming side. Crucially, the parts that do not conflict are still merged normally.

Do not use -X ours or -X theirs without reviewing the result — they can silently drop important code. Because Git resolves every conflicting hunk in one direction without asking, real changes on the losing side can vanish with no warning.

subtree: merging repositories with different roots

The subtree strategy is used to combine a repository or directory whose root structure differs from your own. Conceptually:

main repository:
src/
docs/

external repository:
library files at the repository root

Git can adjust the paths during a subtree merge so the incoming tree lands in the right subdirectory. In practice, many teams now use the dedicated git subtree command, or a package manager, rather than managing this strategy by hand.

Key takeaways

0
Message for International and Thai ReadersUnderstanding My Medical Context in ThailandRead more →Message for International and Thai ReadersUnderstanding My Broader Content Beyond MedicineRead more →

Comments

No comments yet. Be the first to share your thoughts.

Sign in to comment