> ## Content Index
> Fetch the complete content index at: https://debugly.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# fatal: refusing to merge unrelated histories
- URL: https://debugly.dev/git-refusing-to-merge-unrelated-histories/
- Published: 2025-09-16T14:00:00.000Z
- Updated: 2026-10-17T05:59:14.000Z
- Description: Git is protecting you from combining two repositories that share no common ancestor. Sometimes that is exactly what you want.
- Author: Rohit Bhadani
- Tags: Tooling, Error Autopsy, Debugging

## The short answer

```
fatal: refusing to merge unrelated histories

```

The two branches have no common ancestor commit. Git will not merge them by default because the result is almost always a mistake.

If you genuinely want to combine two separate histories:

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

```

Before you do that, work out why they are unrelated, because in most cases the answer is that you are on the wrong repository or you re-initialised one by accident.

Tested on git 2.47.

## What "unrelated" means

Git history is a directed graph. A merge works by finding the most recent commit reachable from both branches, the merge base, and computing what changed on each side since then.

With no common ancestor there is no merge base. Git cannot tell what changed, so every file on both sides looks like a new file, and every file present in both looks like a conflict.

The flag exists because there are legitimate cases. The default is a refusal because the common case is a mistake.

## Why it happened

### You initialised a local repository and then added a remote that already had commits

The most frequent cause.

```bash
mkdir project && cd project
git init
# write code, commit
git remote add origin git@github.com:me/project.git
git pull origin main        # remote has a README from the web UI

```

Your local history starts at your first commit. The remote's starts at the README commit GitHub created. Two roots, no relationship.

If your local work is the real content and the remote only has a README or a licence:

```bash
git pull origin main --allow-unrelated-histories
# resolve conflicts, usually keeping both

```

Or if you do not care about the remote's initial commit:

```bash
git push --force-with-lease origin main

```

`--force-with-lease` rather than `--force`. It refuses if someone else pushed since you last fetched, which is the difference between overwriting your own history and overwriting a colleague's.

### You re-ran git init

Deleting `.git` and running `git init` again creates a completely new history. The files are identical, the commits are not.

Usually done to escape a confusing state. Check for the old repository before assuming it is gone:

```bash
ls -la .git
git reflog                  # if .git still exists, your commits are probably there

```

Nine times out of ten the original history is recoverable and re-initialising was the wrong move. [The reflog holds a lot more than people expect](https://debugly.dev/recover-work-after-git-reset-hard/).

### You are on the wrong remote

```bash
git remote -v

```

Fetching from a fork you did not intend, or a repository with a similar name. The histories genuinely are unrelated because they are different projects.

### A squashed or rewritten history on the remote

Someone ran a history rewrite, `git filter-repo`, or force pushed a rebased branch. Every commit sha changed, so your local commits no longer share ancestry with the new remote state.

Confirm:

```bash
git log --oneline origin/main | tail -5
git log --oneline main | tail -5

```

Different root commits means the history was rewritten. Coordinate with whoever did it rather than merging, because merging produces a duplicated history that is genuinely unpleasant to untangle.

## The legitimate cases

### Merging one repository into another as a subdirectory

You have two projects and want to combine them, preserving both histories.

```bash
git remote add other ../other-project
git fetch other
git merge --allow-unrelated-histories other/main

```

That merges the other project's files into your root, which is usually not what you want. To put it in a subdirectory with its history intact, use a subtree merge:

```bash
git remote add other ../other-project
git fetch other
git merge -s ours --no-commit --allow-unrelated-histories other/main
git read-tree --prefix=packages/other/ -u other/main
git commit -m "merge other-project into packages/other"

```

`-s ours` takes your tree and records the other branch as a parent, then `read-tree` places its files under a prefix. History from both sides is reachable, and `git log --follow` works on the moved files.

For a monorepo migration, `git subtree add` does the same thing with a friendlier interface:

```bash
git subtree add --prefix=packages/other ../other-project main

```

### Adopting an orphan branch

Documentation sites frequently live on an orphan branch:

```bash
git checkout --orphan gh-pages
git rm -rf .
# add site files
git commit -m "initial site"

```

An orphan branch has no parent by design. If you later want to merge it into main, you need the flag.

### Combining a template with an existing project

You started from a template repository and now want to pull in upstream template changes. The histories diverged at the point the template was copied rather than forked.

## What the merge looks like

Prepare for a lot of conflicts. Every file present in both trees conflicts, because git has no base to compare against.

```bash
git merge --allow-unrelated-histories other/main
# CONFLICT (add/add): Merge conflict in README.md
# CONFLICT (add/add): Merge conflict in .gitignore
# CONFLICT (add/add): Merge conflict in package.json

```

`add/add` is the signature. Both sides added the file, git has no idea which is correct.

To resolve wholesale in one direction:

```bash
git checkout --ours README.md      # keep your version
git checkout --theirs LICENSE      # keep theirs
git add README.md LICENSE

```

Note that `--ours` and `--theirs` mean the opposite of what you might expect during a rebase, where the sides are swapped. During a merge, `ours` is the branch you are on.

For `package.json` and lockfiles, resolve the manifest by hand and then regenerate the lockfile rather than merging it:

```bash
rm package-lock.json
npm install

```

Merging lockfiles by hand produces dependency trees that satisfy neither side, and it is a reliable way to create [a build that works locally and fails in CI](https://debugly.dev/docker-build-works-locally-fails-ci/).

## Backing out

If the merge goes badly:

```bash
git merge --abort

```

If you already committed:

```bash
git reset --hard ORIG_HEAD

```

`ORIG_HEAD` points at where you were before the last merge or rebase, which makes this the fastest recovery available.

## Preventing it

**Clone rather than init when the remote exists.**

```bash
git clone git@github.com:me/project.git

```

Obvious, and the mistake happens because people create the repository on GitHub with a README while also having local work.

**When creating a repository on GitHub for existing local work, create it empty.** No README, no licence, no gitignore. Then `git remote add` and push cleanly.

**Check before you pull into a fresh repository:**

```bash
git log --oneline origin/main -1
git log --oneline main -1

```

Two different root commits is your warning.

**Do not delete `.git` to fix a problem.** Almost every git state is recoverable, and re-initialising throws away the recovery path along with the problem.

---

Published on [debugly.dev](https://debugly.dev/) by [Rohit Bhadani](https://debugly.dev/about/) | Founder of [Krova Cloud](https://krova.cloud/?ref=debugly.dev)