Skip to content
ohsudo, Home
CI/CD

Git "fatal: refusing to merge unrelated histories": when the flag is safe, and when it isn't

Fix Git "fatal: refusing to merge unrelated histories": why it happens, how to use --allow-unrelated-histories safely, and how to spot a wrong remote or shallow clone.

Beginner4 min readApplies to Git 2.9+ · GitHub · GitLab · Bitbucket

by OhSudo ··

Checked on real software: Git · November 2026How we check

Part of a learning path:Git for everyday work

$ git pull --no-rebase origin main
fatal: refusing to merge unrelated histories

Commits in Git form a chain back to a starting point, and a merge normally looks for the last commit the two sides share. Here it found none: the two branches started separately. Since Git 2.9, it refuses by default, because that’s usually a mistake.

The most common reason is entirely innocent: you ran git init locally, then created the repository on GitHub with a README. That made two first commits, each with its own history.

  1. Local historystarted with git init
  2. Remote historystarted with the README commit
  3. No common commitrefusing to merge unrelated histories(breaks here)
A merge looks for the last commit both sides share. git init locally plus a README created on GitHub gives two first commits, and nothing in common.

TL;DR

Check that you have the right repository, then merge them:

Terminal window
git remote -v
git pull --no-rebase origin main --allow-unrelated-histories

Solve any conflicts, then:

Terminal window
git push -u origin main

1. Check before you merge

The flag does exactly what you tell it, including merging two projects that have nothing to do with each other. So take a moment to look:

Terminal window
git remote -v
git fetch origin
git log --oneline --all --graph -n 20

You should see two separate lines. Then see what’s in the other side:

Terminal window
git fetch origin
git ls-tree --name-only origin/main
git log --oneline origin/main

Is that what you expected? Just a README.md and a LICENSE is the harmless case. If you see some other project’s files, your remote is wrong. Fix that instead of merging:

Terminal window
git remote set-url origin git@github.com:acme/the-right-repo.git

2. New repository: merge the two

Terminal window
git pull --no-rebase origin main --allow-unrelated-histories

--no-rebase makes the choice explicit. Without it, and with no default set, current versions of Git stop earlier with fatal: Need to specify how to reconcile divergent branches.

If both sides have a file with the same name, such as a README, you’ll get a conflict:

CONFLICT (add/add): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

Edit the file to keep what you want, and finish the merge:

Terminal window
git add README.md
git commit
git push -u origin main

Your history now has both starting points, joined by a merge commit. That’s perfectly fine.

3. New repository: throw away the remote’s first commit

If the remote holds nothing you need, such as an auto-generated README, you can replace it. This overwrites the remote, so check that nobody else has pushed there first:

Terminal window
git log --oneline origin/main
git push --force-with-lease origin main

--force-with-lease refuses if the remote has changed since you last fetched, which makes it safer than --force. A protected branch will refuse it anyway, and that’s the correct behavior.

The other way is to start from the remote, which keeps one clean history:

Terminal window
git clone git@github.com:acme/app.git app-clean
rsync -a --exclude .git app/ app-clean/ # your files on top, without the old history

Next time, avoid all of this: create the GitHub repository empty, with no README, license or .gitignore. Or clone first, and work in the clone. The .gitignore Generator can write that file before your first commit.

4. A shallow clone

Here’s one that looks the same with a very different cause. With a shallow clone, the shared commit isn’t on your machine, so Git thinks the histories are unrelated:

Terminal window
git rev-parse --is-shallow-repository

true means this is your case. Don’t use the flag: get the rest of the history instead.

Terminal window
git fetch --unshallow

It’s common in CI, where a checkout usually fetches one commit. For example, in GitHub Actions:

- uses: actions/checkout@v4
with:
fetch-depth: 0

5. History was rewritten

Someone rewrote the history with git filter-repo, or recreated the repository to remove a leaked secret. Your copy and the remote now have different commits all the way back. Merging would bring the old history back, including whatever was removed.

So if you have no unpushed work, reset to the new history. This discards your local commits and uncommitted changes:

Terminal window
git status
git fetch origin
git reset --hard origin/main

If you do have local work, save it as a patch before that, with git format-patch origin/main --stdout > my-work.patch, and apply it afterwards. Asking the person who rewrote it is a good idea too.

6. Combining two real projects

If you do want to merge two real repositories, keep them apart by moving one into its own folder first, in the repository you’re merging from:

Terminal window
mkdir legacy-app
git mv -k * legacy-app/
git commit -m "Move everything into legacy-app/"

Then, in the main repository:

Terminal window
git remote add legacy ../legacy-app
git fetch legacy
git merge legacy/main --allow-unrelated-histories

You then have both, with their histories, without conflicts.

Warning

Don’t make --allow-unrelated-histories a habit, or add it to scripts or CI. It turns off a check that’s there to catch a wrong remote. In an automated pull, that can merge the wrong project without anyone noticing.

Shell, we have a problem!

Similar, but different: Updates were rejected because the remote contains work that you do not have locally is the normal case where the histories are related: see git push rejected. fatal: Need to specify how to reconcile divergent branches is about choosing merge or rebase, and a plain git pull can show it for these same repositories, before it gets as far as this error. detected dubious ownership is about the folder’s owner: see that article. And if .gitignore is ignored, see why .gitignore doesn’t work. All the everyday commands are in the Git Cheat Sheet.

$ ./practice.sh

Practice this in the terminal

Open the Terminal Playground with this article’s scenario loaded. It is safe and runs in your browser.

Open the terminal →

Found this useful? Share it.

Found a mistake? Let us know at contact@ohsudo.com.

Tools

Try it yourself

Articles

Related articles