GitGit

fatal: refusing to merge unrelated histories

Two branches share no common commit, so Git will not guess how to combine them. How to check you are merging what you think, and what --allow-unrelated-histories really does.

easy fix6 min read

the git error
fatal: refusing to merge unrelated histories

fatal: Not possible to fast-forward, aborting.

Do this first3 steps

Run these in order. Each one tells you what its output means before you change anything.

  1. 1

    Confirm the two histories really share nothing

    git merge-base HEAD origin/main || echo "NO COMMON ANCESTOR"

    A printed commit hash means they do share history and the error is about something else. No output confirms two independent histories, which is almost always because one side was created with a fresh git init.

  2. 2

    Look at what each side actually contains before combining them

    git log --oneline -5 HEAD && echo '---' && git log --oneline -5 origin/main

    Check you are not about to merge an unrelated project. This error is a guard against pushing into the wrong remote, and it catches that mistake surprisingly often.

  3. 3

    If both histories are genuinely yours, allow the merge

    git pull origin main --allow-unrelated-histories

    This creates a merge commit with two parents and no common ancestor. Expect conflicts in any file that exists on both sides, because Git has no base version to compare against.

All 9 sections

Git refuses to merge two branches with no common ancestor. Every normal merge works by finding the commit both sides descend from and comparing against it. With no shared commit there is no base, so Git cannot tell an addition from a deletion, and it stops rather than guessing.

This became an error in Git 2.9. Before that it merged silently, which quietly produced a lot of damaged repositories.

Confirm it

git merge-base HEAD origin/main || echo "NO COMMON ANCESTOR"

No output confirms the diagnosis. A commit hash means the histories do connect and your problem is something else, most likely Not possible to fast-forward.

Look at what each side is before combining anything:

git log --oneline -5 HEAD
echo '---'
git log --oneline -5 origin/main
a1b2c3d Add user service
e4f5a6b Initial commit
---
9z8y7x6 Initial commit from GitHub template

Two separate Initial commits. Two histories that never met.

How you got here

The common one. You created a repository on GitHub with a README, licence or .gitignore, then ran git init locally, committed, added the remote and pulled. GitHub's initial commit and your initial commit are unrelated roots.

Re-initialising. Someone deleted .git and ran git init again. Every commit that existed before is gone from the new history, even though the files look identical.

Wrong remote. You added the wrong URL and are about to merge someone else's project into yours. This is the case the error exists to catch, and it does catch it.

Orphan branches. git checkout --orphan deliberately starts a branch with no parent. A gh-pages branch built this way is unrelated to main on purpose, and merging them is a mistake.

Rule out the third before doing anything:

git remote -v

Fix 1: You only want one side

If the remote has just a README and your local work is the real repository, do not merge. Overwrite:

git push --force-with-lease origin main

--force-with-lease refuses if the remote moved since you last fetched, which --force does not. There is no reason to prefer plain --force here.

The reverse case, where the remote is right and your local work is a mistake:

git fetch origin
git reset --hard origin/main

reset --hard discards uncommitted changes with no confirmation and no undo. Run git status first.

Fix 2: Both histories matter

git pull origin main --allow-unrelated-histories

Expect conflicts in every file present on both sides. Without a common ancestor Git cannot do a three-way merge, so it falls back to showing you both versions in full:

<<<<<<< HEAD
# My Project
A service for processing payments.
=======
# my-project
>>>>>>> origin/main

There is no clever resolution available. Read both and write what you want.

The result has two root commits, which is unusual but valid. git log --graph --oneline --all shows two lines that only converge at the merge.

Fix 3: Replay your work on top instead

A merge of unrelated histories leaves a permanently odd shape. If your local work is a handful of commits, rebasing produces a linear history that looks like it was always one repository:

git fetch origin
git rebase --onto origin/main --root main

--root includes your very first commit, which a normal rebase excludes. Each commit is replayed onto the remote's history, so afterwards there is one root and one line.

Expect to resolve conflicts once per commit rather than once in total. For two or three commits that is fine; for fifty it is not worth it, and the merge is the pragmatic choice.

Rebase rewrites every commit hash. Do not do this on a branch anyone else has pulled.

Avoiding it

Create the remote repository empty, with no README and no .gitignore, then:

git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin git@github.com:acme/myapp.git
git push -u origin main

Or start from the remote and avoid the second history entirely:

git clone git@github.com:acme/myapp.git
cd myapp
# add your files here

GitHub's own "push an existing repository" instructions assume an empty repository for exactly this reason. The error is the price of ticking "Add a README file".

The error people confuse with this

fatal: Not possible to fast-forward, aborting. is a different thing. The histories do share an ancestor, but yours has diverged and your config says fast-forward only:

git config pull.ff only     # this is what causes it

Choose how to reconcile instead:

git pull --rebase
git pull --no-rebase        # merge

Set a default so the prompt stops appearing:

git config --global pull.rebase true

A checklist

  1. git merge-base HEAD origin/main. Output means the histories are related; this is a different error.
  2. git remote -v. Make sure it is the repository you think.
  3. git log --oneline -5 on both sides. Two Initial commits confirms two roots.
  4. Only local matters → git push --force-with-lease.
  5. Only remote matters → git reset --hard origin/main, after checking git status.
  6. Both matter → git pull --allow-unrelated-histories and resolve by hand.
  7. Few local commits and want a clean line → git rebase --onto origin/main --root main.
  8. Avoid it next time by creating the remote repository empty.

Frequently Asked Questions

What does "refusing to merge unrelated histories" mean?

The two branches share no common ancestor commit, so Git has no base version to compare both sides against. A normal merge is a three-way comparison between the two tips and the commit they both descend from; without that base, Git cannot distinguish a line one side added from a line the other side deleted. Rather than guess, it stops. Git 2.9 made this an error specifically because the previous silent behaviour produced a lot of quietly broken repositories.

Is --allow-unrelated-histories safe?

It is safe in the sense that it will not lose commits, and it is worth pausing before you use it. The flag exists to make you confirm this is deliberate, because the most common reason to see this error after a wrong remote URL is that you are about to merge a completely different project. Run git remote -v and read a few commits from each side first. Once you are sure both histories are yours, the merge is fine; expect to resolve a conflict in every file that exists on both sides, since Git has no base to merge against.

How do I avoid this when pushing an existing project to GitHub?

Create the remote repository empty, without a README, .gitignore or licence. Those options make an initial commit on the remote, which becomes a second root unrelated to your local one. With an empty remote you can git remote add origin and git push -u origin main with nothing to reconcile. If the repository already has that commit and contains nothing you need, git push --force-with-lease replaces it, which is the quickest way out.

Should I merge or rebase to fix unrelated histories?

Merge if you have many local commits or anyone else has pulled the branch; it is one conflict resolution and it does not rewrite history. Rebase with git rebase --onto origin/main --root if you have a handful of commits and want a repository that looks like it always had one history, accepting a conflict resolution per commit. Rebase changes every commit hash, so it is only appropriate on a branch nobody else has.

Why do I get "Not possible to fast-forward" instead?

That is a different situation: the histories are related, but your branch and the remote have both moved on, so no fast-forward is possible, and pull.ff is set to only. Git is refusing to create a merge commit because you told it not to. Decide how you want to reconcile: git pull --rebase replays your commits on top of the remote, and git pull --no-rebase creates a merge commit. Setting git config --global pull.rebase true picks a default so the prompt stops appearing.

Reference and practice

Learn the underlying concept

Other Git errors