Octopus merges and when to avoid them Jump to heading
Pass more than one branch to git merge and Git uses the octopus strategy: one merge commit with three, five or twenty parents. It is how some projects record “these topics went into this release together”, and it produces a strikingly compact history graph. It also has hard limits that surprise people. The octopus strategy refuses to proceed if any branch conflicts with the others — it cannot ask you to resolve conflicts across several branches at once. A commit with many parents is awkward to revert, harder to bisect, and confusing to tools that assume two parents. This page explains how octopus merges work, where they genuinely help, and when a sequence of ordinary merges is the better choice, within merge strategies and gitattributes.
When to use this approach Jump to heading
- You want to integrate several independent topic branches in one step, and they do not conflict.
- You build an integration branch and want its history to show which topics went in together.
- You are reading history containing octopus merges and need to understand them.
- If the branches conflict or will need individual reverting, ordinary sequential merges are safer — see running rerere in CI integration builds for a sequential alternative.
Step 1 — Run an octopus merge Jump to heading
Name every branch in one git merge command. Git merges them in turn into a temporary result and, if all succeed without conflicts, creates one commit with all of them as parents.
git switch integration
git merge --no-edit topic/search topic/export topic/billing-ui
git log -1 --format='%h parents: %p' # four parents: integration + three topics
git log --oneline --graph -12 Step 2 — Understand why it refuses conflicts Jump to heading
The octopus strategy does not stop for manual conflict resolution. If merging any branch conflicts, it aborts the whole operation and leaves you where you started.
Trying simple merge with topic/search
Trying simple merge with topic/export
Simple merge did not work, trying automatic merge.
Auto-merging src/export/api.py
ERROR: content conflict in src/export/api.py
fatal: merge program failed
Automated merge did not work.
Should not be doing an octopus.
Merge with strategy octopus failed. When that happens, fall back to merging the conflicting branch separately. A common pattern: octopus-merge the branches that merge cleanly, then merge the conflicting one on its own, resolving its conflicts normally.
git merge --no-edit topic/search topic/billing-ui # clean ones together
git merge topic/export # the conflicting one alone Step 3 — Weigh the history benefits against the costs Jump to heading
An octopus merge reads well in a graph, and --first-parent history shows one entry per integration rather than one per topic. The costs show up later.
Reverting one topic from an octopus merge needs git revert -m 1 plus a careful selection of which topic’s changes to undo — the revert undoes the whole merge relative to the first parent, which is every topic at once. To remove just one, you revert the octopus and re-merge the others, or revert that topic’s individual commits.
# Undoing only topic/export from an octopus merge O: revert its own commits instead
git revert --no-edit $(git rev-list --reverse "$(git merge-base O^1 O^3)..O^3") Step 4 — Know how bisect treats an octopus merge Jump to heading
Bisect handles merges by testing commits on every parent’s side, but a large octopus merge creates a big jump: the commit before it has none of the topics, the merge has all of them. If the merge itself is bad because of an interaction between topics, bisect can only point at the merge.
git bisect start bad-sha good-sha
# if it lands on the octopus merge, test each topic combination by hand
for t in 2 3 4; do git merge-tree --write-tree O^1 O^$t >/dev/null && echo "parent $t merges cleanly alone"; done The interaction case — topics that each work alone but break together — is covered in catching semantic conflicts in CI.
Step 5 — Decide on a policy Jump to heading
Most teams are better served by never creating octopus merges on branches that ship. Where they are useful — throwaway integration branches, read-only historical records of a release’s contents — allow them explicitly.
# A pre-receive or CI check rejecting octopus merges on main
for c in $(git rev-list --merges "$OLD..$NEW"); do
n=$(git rev-list --parents -n1 "$c" | wc -w)
[ "$n" -le 3 ] || { echo "$c is an octopus merge ($((n-1)) parents) — merge topics one at a time"; exit 1; }
done Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Is there a limit on the number of branches? Jump to heading
There is no practical limit; octopus merges with dozens of parents exist in large projects. Readability and tooling suffer long before Git does.
Can a forge create an octopus merge? Jump to heading
Hosted forges’ merge buttons create two-parent merges only. Octopus merges come from local git merge commands or scripts.
Do octopus merges cause problems with git log --first-parent? Jump to heading
No. First-parent history follows parent one, so an octopus merge appears as a single entry, which is part of its appeal.
Related Jump to heading
- Merge Strategies & gitattributes — the parent topic.
- Superseding a Branch with the ours Strategy — another non-default strategy.
- Bisecting Across Merges with --first-parent — how merges affect bisect.
- Undoing a Bad Merge on a Shared Branch — reverting two-parent merges.