CoreMesh

How to Fix Refusing to Merge Unrelated Histories Safely

Why git pull stops with fatal: refusing to merge unrelated histories, the one-time --allow-unrelated-histories fix, when it's safe, and how to verify the merge.

How to Fix Refusing to Merge Unrelated Histories Safely

git pull stops with this message when the branch you're pulling and the branch you're on don't share a single commit. Git's merge works by finding a common ancestor and reconciling both sides against it. When no such commit exists, it refuses rather than guess.

text
fatal: refusing to merge unrelated histories

The fix is to tell git, once, that you really do want to join two independent histories. Replace main with the branch you're pulling:

bash
git pull origin main --allow-unrelated-histories

That creates a merge commit with two parents, one from each history. From then on the two sides share that commit, so ordinary git pull works again and you never need the flag for this repository. The rest of this page covers why it happens, when the flag is the right call, what to do about conflicts, and how to check the result before you push.

Why git says refusing to merge unrelated histories#

The git merge documentation describes a merge as incorporating changes "since the time their histories diverged from the current branch". That phrase assumes the histories did diverge from something. A three-way merge needs a base commit, your tip, and their tip. If two histories have no common commit, there is no base, and by default git refuses.

The same page explains the override: --allow-unrelated-histories exists "for merging histories of two projects that started their lives independently", calls that "a very rare occasion", and states that no configuration variable to enable it by default exists or will be added. That design choice tells you how to think about the error. It's a safety check, not a bug, and the maintainers want you to make the decision explicitly every time.

git pull is fetch followed by merge, which is why you usually meet this error during a pull rather than a plain merge. The common triggers are:

  • A new GitHub repo plus a local git init. You created the repository on GitHub with a README, license, or .gitignore, so it has one commit. Locally you ran git init, committed your code, added the remote, and pulled. Two root commits, nothing shared.
  • Combining two real projects. You're importing a standalone repo into another one and want to keep both histories.
  • A re-initialized repository. Someone deleted the .git directory, ran git init again, and committed. The remote still has the old history.
  • A rewritten upstream. The remote branch was replaced with history that shares no commit with your clone.

The first case is by far the most common, and it's also the case where the flag is almost always safe. The last two cases deserve a pause, covered below.

Here's a small model of the check git performs. Each commit lists its parents, and the question is whether two tips have any ancestor in common:

python
# Minimal model of how git decides whether two histories are related.
# Each commit maps to the list of its parent commits.
history = {
    "L1": [],        # your first local commit (git init + commit)
    "L2": ["L1"],
    "R1": [],        # "Initial commit" created on GitHub with a README
}

def ancestors(commit):
    seen, stack = set(), [commit]
    while stack:
        c = stack.pop()
        if c in seen:
            continue
        seen.add(c)
        stack.extend(history[c])
    return seen

def common(a, b):
    return ancestors(a) & ancestors(b)

print("Before the merge:")
print("  common ancestors of L2 and R1:", sorted(common("L2", "R1")) or "none")
print("  git merge refuses:", not common("L2", "R1"))

# A merge commit with both tips as parents ties the histories together.
history["M"] = ["L2", "R1"]
history["R2"] = ["R1"]   # a teammate pushes another commit later

print("After merge commit M:")
print("  common ancestors of M and R2:", sorted(common("M", "R2")))
print("  flag needed again:", not common("M", "R2"))

The merge commit is what fixes things permanently. Once it exists, every future pull has a shared ancestor to work from.

The fix for git pull, step by step#

Start from a clean working tree. The merge docs warn that running a merge with non-trivial uncommitted changes "may leave you in a state that is hard to back out of", and git pull will stop anyway if local changes overlap files it needs to update. Commit or stash first.

bash
git status
git stash          # only if you have changes you want to keep
git pull origin main --allow-unrelated-histories

Git opens your editor with a default merge message. Save and close it to finish. If you'd rather supply the message inline:

bash
git pull origin main --allow-unrelated-histories -m "Merge GitHub initial commit into local history"

If your git is configured to rebase on pull, the flag does nothing. The git pull documentation lists --allow-unrelated-histories as "only useful when merging". Force a merge for this one pull with --no-rebase:

bash
git pull --no-rebase --allow-unrelated-histories origin main

The same thing as a separate fetch and merge, which is easier to reason about if something goes wrong:

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

To inspect the result before anything is committed, add --no-commit. Git performs the merge, updates the index and working tree, and stops just short of creating the commit:

bash
git fetch origin
git merge --no-commit --allow-unrelated-histories origin/main
git status
# happy? finish it:
git commit
# not happy? back out:
git merge --abort

How to confirm it worked: git status reports a clean tree, git log shows a new merge commit at the top with two parents, and running git pull again prints Already up to date.

When allowing unrelated histories is safe and when it isn't#

The flag is safe when all three are true:

  1. You know why the histories are unrelated. For the GitHub-README case, the answer is obvious.
  2. You want the content of both sides in the result.
  3. You're prepared to resolve conflicts in files that exist on both sides, typically README.md, .gitignore, or LICENSE.

It's the wrong tool when you expected the histories to be related. If this is a repository you've been pulling from for months and the error appeared out of nowhere, the unrelated history is a symptom. Likely causes are a remote URL pointing at a different repository, pulling the wrong branch, a re-initialized .git directory, or an upstream history that was replaced. Merging in that situation stitches two copies of the same project together, doubles the history, and produces a wall of conflicts. Look at what you're about to merge first:

bash
git fetch origin
git log origin/main

If the remote history looks like the project you already have, stop and find out what changed. If your local commits are throwaway and the remote is the source of truth, the cleaner fix is a fresh git clone and copying your working files in, with no merge at all.

Two variations are useful when you've decided to merge but want control over the content:

  • Keep your tree, record their history. The ours merge strategy keeps "the resulting tree of the merge" identical to your current branch while still creating a merge commit that ties the histories together. Everything on their side is ignored, so only do this when their content is disposable.
bash
git merge -s ours --allow-unrelated-histories origin/main
  • Auto-resolve conflicts one way. The -X ours and -X theirs options to the default ort strategy only decide conflicting hunks. Non-conflicting changes from both sides are kept. Don't confuse -X ours with -s ours; the git pull docs call this out explicitly.
bash
git merge -X theirs --allow-unrelated-histories origin/main

Handling conflicts after the merge starts#

Two independent projects often both have a README.md, and git can't merge files with no shared base version cleanly. You'll see conflict markers in the file and git status will list it as both modified. The merge isn't done yet: HEAD stays where it was and MERGE_HEAD points at the other side.

bash
git ls-files -u          # which paths are still conflicted
# edit each file, remove the <<<<<<< ======= >>>>>>> markers
git add README.md
git merge --continue     # or: git commit

If the conflicts are worse than expected, abort and think again:

bash
git merge --abort

That works for a pull as well as a plain merge, because the merge docs describe --abort as equivalent to git reset --merge whenever MERGE_HEAD is present. It restores the pre-merge state, with the caveat already mentioned: uncommitted changes present when the merge started may not come back cleanly.

How to verify the merged history#

Don't push until you've checked three things.

The merge commit has two parents. Run git log. The top entry should be a merge commit listing both parent commits, the previous tip of your branch and the tip you pulled in. Further down you'll see two separate root commits, one per original project. That's expected, and it's exactly what makes the result "related" from now on.

The content is what you intended. Before the merge, git sets ORIG_HEAD to your previous tip, so you can diff the whole operation in one command:

bash
git diff ORIG_HEAD

Read through it. Files that only existed on the remote side show up as additions. Files you resolved by hand should contain exactly what you chose, with no leftover markers.

A second pull is a no-op. The merge docs say that when all named commits are already ancestors of HEAD, git exits early with Already up to date. If you see the unrelated-histories error again instead, the merge commit wasn't created, usually because of --squash (see the gotchas below).

If the result is wrong and you haven't pushed, undo it. This resets your branch, index, and working tree back to the pre-merge tip, so make sure nothing uncommitted matters to you:

bash
git reset --merge ORIG_HEAD

After verification, git push should be a plain fast-forward on the remote, because your merge commit descends from the remote tip you just pulled. If the push is rejected, someone pushed in between, and the steps in fixing a rejected non-fast-forward push apply as usual. If you ended up on a detached HEAD while poking around commits, recovering from a detached HEAD covers getting your work back onto a branch.

Fixing it in IntelliJ, SourceTree, Visual Studio and other GUIs#

Every Git GUI runs the same git merge underneath, so the error text is identical whether it appears in an IDE log panel or a terminal. The official git docs don't describe any particular client's dialogs, so the dependable path is the command line:

  1. Open a terminal in the repository root. Most IDEs have a built-in terminal that already sits there.
  2. Run the one-time command: git pull origin main --allow-unrelated-histories.
  3. Resolve conflicts in the IDE's merge tool if you prefer, then stage and commit.
  4. Refresh the GUI. It'll pick up the new merge commit from the repository on disk.

One thing to check inside the IDE: if its pull action is set to rebase, the flag won't apply, because it's only meaningful for a merge. Either switch the pull mode to merge for that one operation or use --no-rebase in the terminal as shown earlier.

Common mistakes and gotchas#

  • Looking for a way to force it. There's no --force for merge. The override is --allow-unrelated-histories, and if what you want is "take mine, ignore theirs", that's the -s ours strategy, not a force flag.
  • Looking for a config setting. There isn't one, on purpose. The docs say no configuration variable "exists or will be added". You pass the flag exactly once per combined history.
  • Using it to paper over a wrong remote. If the error surprised you in a repo that used to pull fine, the flag will succeed and leave you with a doubled history. Inspect the remote branch with git log origin/main before merging.
  • Combining it with --squash. --squash builds the merged tree but, in the words of the docs, does not record the merge information and doesn't set MERGE_HEAD. Your next pull sees two unrelated histories all over again.
  • Expecting it to work with rebase. With pull.rebase set or --rebase on the command line, the flag is ignored. Use --no-rebase for this pull.
  • Merging over uncommitted work. If conflicts appear, git merge --abort may not be able to restore your uncommitted changes. Commit or stash first.
  • Forgetting to clean up the README duplicate. After the merge you'll often have your own README.md content and GitHub's placeholder stitched together. Resolve it properly rather than committing both halves.

Quick reference#

Situation Command
New GitHub repo plus local git init git pull origin main --allow-unrelated-histories
Pull is configured to rebase git pull --no-rebase --allow-unrelated-histories origin main
Inspect before committing git merge --no-commit --allow-unrelated-histories origin/main
Keep my files, record their history git merge -s ours --allow-unrelated-histories origin/main
Prefer their side on conflicting hunks git merge -X theirs --allow-unrelated-histories origin/main
List conflicted paths git ls-files -u
Finish after resolving git merge --continue
Back out of an in-progress merge git merge --abort
Review what the merge changed git diff ORIG_HEAD
Undo a finished, unpushed merge git reset --merge ORIG_HEAD

Checklist before you push:

  1. You know why the two histories are unrelated and you want both.
  2. Working tree was clean before the merge.
  3. git log shows a merge commit with two parents at the top.
  4. git diff ORIG_HEAD shows only the content you expect.
  5. git pull now reports Already up to date.

For the full option list, the git merge reference and the git reset reference are the pages to keep open.

Quick answers

What does fatal: refusing to merge unrelated histories mean?

The branch you're on and the branch you're merging or pulling have no commit in common, so git can't find a base for a three-way merge. By default it refuses instead of guessing, and the error appears most often after creating a GitHub repo with a README and then running git init locally.

How do I fix refusing to merge unrelated histories in git pull?

Commit or stash local changes, then run git pull origin main --allow-unrelated-histories, replacing main with your branch. Git creates a merge commit with both histories as parents, and future pulls work without the flag.

Is there a force option for refusing to merge unrelated histories?

No. The override is --allow-unrelated-histories, and there is no config setting to enable it permanently by design. If you want to keep only your files while still joining the histories, use the ours merge strategy with -s ours.

How do I fix it in IntelliJ, SourceTree or Visual Studio?

These tools run the same git merge underneath. Open a terminal in the repository root, run the pull with --allow-unrelated-histories, resolve any conflicts, then refresh the GUI. If the IDE pulls with rebase, add --no-rebase, since the flag only applies to merges.

Does the flag work with git pull --rebase?

No. The git pull documentation lists --allow-unrelated-histories as only useful when merging, so with pull.rebase set or --rebase given it has no effect. Use --no-rebase for the one pull that joins the histories.

Did this solve it?

One tap. No account.

Saved you an hour? Send a tip.

USDC or ETH on Base, Ethereum, Arbitrum and more. Keeps the notes free and the examples running.

Base

Network

0xc783bc5c3fa14cEC3f09A22284bC91C5AF0d59e1
Open in wallet · 5 USDC

On a computer? Scan the code with your phone wallet, or copy the address.

Pick the network your wallet or exchange uses. USDC works on all six; ETH on Base, Ethereum, Arbitrum and Optimism. Don't send on Tron or Solana: this address doesn't exist there. Tips are optional and unlock nothing; every guide stays free.

Discussion

Start the discussion

Indra Wijaya

Builds and runs AI agents, bots and content pipelines, and writes down what works and what broke.

About · Email · RSS

Keep reading

New notes, no spam.

One post at a time, only when there's something worth reading. Follow in any feed reader.

Subscribe via RSS