← Back to Blog

Fix Git "fatal: refusing to merge unrelated histories" Error

Quick Fix

If you created a local repo and are pulling from a remote that has existing commits:

# For git pull
git pull origin main --allow-unrelated-histories

# For git merge
git merge origin/main --allow-unrelated-histories

# Then resolve any conflicts and commit

You ran git pull origin main or git merge and Git responded with fatal: refusing to merge unrelated histories. This error means the two branches share no common ancestor commit. Git added this safety check in version 2.9 (June 2016) to prevent accidentally merging two completely separate repositories. Before 2.9, this merge would happen silently. Understanding why the histories are unrelated determines whether --allow-unrelated-histories is the right fix or a mistake.

Why Histories Become Unrelated

Two branches are "unrelated" when git merge-base finds no common ancestor. There are five common scenarios that cause this.

Scenario 1: git init Locally + Remote Already Has Commits

This is the most common cause. You created a local repo with git init, made some commits, then added a remote that already has its own commits (like a GitHub repo initialized with a README):

# Local
mkdir my-project && cd my-project
git init
echo "hello" > app.js
git add . && git commit -m "initial commit"

# Remote (GitHub) was created with "Initialize with README"
git remote add origin git@github.com:user/my-project.git
git pull origin main
# fatal: refusing to merge unrelated histories

The local initial commit and the remote initial commit (README) have no parent relationship. They are two independent root commits.

Scenario 2: Orphan Branches

An orphan branch has no parent commit. It starts a fresh history within the same repository:

git checkout --orphan gh-pages
git rm -rf .
echo "docs" > index.html
git add . && git commit -m "docs initial"

# Trying to merge this back into main fails
git checkout main
git merge gh-pages
# fatal: refusing to merge unrelated histories

This is intentional for branches like gh-pages that serve a different purpose. You typically do not merge orphan branches back into main.

Scenario 3: Repository Was Squashed or Rewritten

If someone squashed the entire history into a single commit (common when open-sourcing an internal project or resetting history for compliance), the new root commit has no relationship to any branches that existed before the squash:

# Someone did this to "clean" the repo
git checkout --orphan fresh
git add -A
git commit -m "fresh start"
git branch -D main
git branch -m main
git push --force origin main

Anyone who had the old main checked out will now get unrelated histories when they pull.

Scenario 4: Subtree or Submodule Merge

When merging a completely separate repository as a subdirectory (subtree merge), the histories are inherently unrelated:

git remote add library git@github.com:org/library.git
git fetch library
git merge library/main
# fatal: refusing to merge unrelated histories

Scenario 5: Shallow Clone Depth Issue

A shallow clone (git clone --depth 1) may not have enough history for Git to find the common ancestor. This is less common but happens in CI pipelines that use shallow clones for speed:

# Deepen the clone if this is the issue
git fetch --unshallow

The Fix: --allow-unrelated-histories

When you have confirmed that merging is intentional, use the flag:

With git pull

git pull origin main --allow-unrelated-histories

With git merge

git fetch origin
git merge origin/main --allow-unrelated-histories

What Happens Next

Git will attempt a three-way merge using an empty tree as the common ancestor. This means every file from both sides is considered "added," so:

  • Files that exist only on one side merge cleanly
  • Files that exist on both sides with different content will conflict
  • The merge commit will have two parents from unrelated lineages
# After running the merge, you may see:
Auto-merging README.md
CONFLICT (add/add): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

# Resolve conflicts
vim README.md    # Edit to resolve
git add README.md
git commit       # Creates the merge commit

Compare File Changes Visually

Use SecureBin's Diff Checker to compare conflicting file versions side-by-side before resolving merge conflicts.

Open Diff Checker

When NOT to Use --allow-unrelated-histories

The flag bypasses a safety check. Do not use it when:

  • You are merging two different projects by mistake. If you accidentally added the wrong remote, fix the remote URL instead of forcing the merge.
  • History was rewritten by force-push and you have local work. The correct fix is git fetch origin && git reset --hard origin/main (if you have no local changes to keep) or a careful rebase.
  • You do not understand why the histories are unrelated. Investigate first. Run git log --oneline --all --graph to visualize the branch topology and understand the root cause before bypassing the check.

Safer Alternatives

Alternative 1: Clone Instead of Init

The cleanest way to avoid this entirely is to clone the remote repo first, then add your files:

# Instead of git init + git remote add
git clone git@github.com:user/my-project.git
cd my-project
# Now add your files - histories are already connected

Alternative 2: Rebase Instead of Merge

Rebasing replays your local commits on top of the remote branch, creating a linear history without a merge commit:

# Fetch the remote branch
git fetch origin

# Rebase your local commits onto origin/main
git rebase origin/main

# If that fails with the same error, use:
git rebase --onto origin/main --root

This is often cleaner than a merge when one side has only a few commits (like the initial README on GitHub). Your local commits get new hashes but the history reads linearly.

Alternative 3: Start Fresh from the Remote

If your local work is small, the simplest approach is to clone the remote and copy your files in:

# Save your local work
cp -r my-project my-project-backup

# Clone the remote
git clone git@github.com:user/my-project.git my-project-clean
cd my-project-clean

# Copy your files (excluding .git)
cp -r ../my-project-backup/src ./src
cp ../my-project-backup/package.json .

# Commit
git add .
git commit -m "Add project source files"
git push origin main

Alternative 4: Replace History (Nuclear Option)

If you want the remote to match your local history exactly, discarding the remote's history:

# WARNING: This destroys the remote's existing history
git push --force origin main

Only do this if you are the sole contributor and the remote's commits (like the auto-generated README) are not needed. On shared repositories, force-pushing to main is destructive and should never be done without team coordination.

Real-World Scenarios

GitHub Repo Created with README + Local Project

The most searched scenario. You have a local project you want to push to a new GitHub repo, but you checked "Initialize this repository with a README" on GitHub.

Best approach:

# Option A: Pull with allow-unrelated-histories
git remote add origin git@github.com:user/repo.git
git fetch origin
git pull origin main --allow-unrelated-histories
# Resolve any conflicts (likely just README.md)
git push origin main

# Option B (cleaner): Delete the GitHub repo's initial commit
# Go to GitHub Settings > Delete repository
# Recreate without "Initialize with README"
# Then push normally:
git remote add origin git@github.com:user/repo.git
git push -u origin main

Monorepo Subtree Import

You are importing an external repository as a subdirectory of your monorepo:

# Using git subtree (recommended for this use case)
git subtree add --prefix=packages/library \
  git@github.com:org/library.git main --squash

# Or with read-tree for more control
git remote add library git@github.com:org/library.git
git fetch library
git read-tree --prefix=packages/library -u library/main
git commit -m "Import library as packages/library"

The git subtree add command handles unrelated histories internally without needing the flag.

CI Pipeline Shallow Clone

Your CI pipeline uses --depth 1 for speed, and a merge operation fails:

# In your CI config, fetch enough history
git fetch --deepen=100

# Or fetch full history for this branch
git fetch --unshallow

# GitHub Actions example:
- uses: actions/checkout@v4
  with:
    fetch-depth: 0    # Full history instead of depth 1

Verifying the Fix

After resolving the unrelated histories merge, verify the result:

# Check that both histories are now connected
git log --oneline --graph --all | head -20

# Verify the merge commit has two parents
git cat-file -p HEAD
# Should show two "parent" lines

# Confirm remote tracking is set
git branch -vv

The Bottom Line

The "refusing to merge unrelated histories" error is Git protecting you from accidentally merging two disconnected commit trees. In most cases, it happens because you initialized a local repo separately from the remote. The fix is --allow-unrelated-histories on the pull or merge command. But before you use it, confirm that merging is actually what you want. If the histories are unrelated because you are pulling from the wrong remote, or because someone rewrote history, the flag will create a messy merge that masks the real problem. Understand the cause first, then pick the right solution.

Related Articles

Continue reading: Fix Docker OOM Killed, Fix Kubernetes CrashLoopBackOff, Detect Secrets in GitHub Repositories, How to Secure API Keys in Code, Fix Let's Encrypt Renewal Failed.

UK
Written by Usman Khan
DevOps Engineer | MSc Cybersecurity | CEH | AWS Solutions Architect

Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.