How to Stop git from relating related history on fetch

How to Stop Git from Relating Histories on fetch

When working with Git templates, shallow clones, or forked repositories, you might run into a subtle behavior: Git fetch “relates” histories, even when you think the repositories should be separate. This results in unintentional history merging, or unshallowing, which defeats the purpose of keeping repositories clean and distinct.

In this post, we’ll explore:

  • What this behavior is
  • Why it happens
  • And how to prevent Git from relating commit histories when fetching from another repo

Problem Overview

Let’s say you:

  1. Have a template repo
  2. Create a shallow clone of it (using --depth 1)
  3. Remove the remote, and start treating it as a separate project
  4. Later want to compare or fetch from the original template (e.g., to check for changes)

At this point, you run:

git fetch ../template --shallow-since="2025-06-01 16:00:00"

You expect Git to fetch just the limited range of commits, but instead:

  • Git “relates” your repo’s history to the template’s.
  • Git unshallows your local repo.
  • You now have the full commit history — which you were trying to avoid.

Why Does This Happen?

This behavior is due to Git’s object model.

Git tracks commits by SHA-1 (or SHA-256) hashes. If your shallow clone has commits that originated from the template repo, those commit hashes are identical.

So when you fetch from the original repo again, Git sees the shared commit hash and thinks:

“Oh, these are the same commits! Let’s connect them.”

It then completes the missing ancestry — unshallowing your local history — even if you removed the remote.


How to Stop Git from Relating Histories

To break the link, you need to change the commit hashes in your current repo so they no longer match the source/template repo.

Solution: Rewrite Your Repo History

There are two main ways:


Option 1: git commit --amend (for single-commit history)

If your new repo only has one commit (e.g., from a --depth 1 clone), just amend the commit:

git commit --amend --no-edit

This creates a new commit with a different hash, even though the content is the same. Now, Git won’t relate it to the original repo anymore.


Option 2: git rebase --root (for multiple commits)

If you’ve made multiple commits and want to rewrite all of them:

git rebase --root

This lets you recreate all commits from the beginning, giving them new hashes. You can hit --exec "git commit --amend --no-edit" if you want to automate it for scripting.


Bonus: Use --allow-unrelated-histories Safely

When you fetch or merge unrelated histories (after breaking them), Git will now prompt you that they’re unrelated. You can proceed explicitly like this:

git merge FETCH_HEAD --allow-unrelated-histories

But only use this if you know what you’re doing.


Example Workflow

# Clone the template shallowly
git clone file:///path/to/template --depth 1 new-project
cd new-project

# Remove the remote (no longer needed)
git remote remove origin

# Rewrite history to break link
git commit --amend --no-edit  # Or: git rebase --root

# Later, fetch from the original template again
git fetch /path/to/template --shallow-since="2025-06-01 00:00:00"

# Now Git won’t auto-connect the histories

Summary

Action Effect
Shallow clone + remove remote Still shares commit hashes
Fetch from original again Git relates history and unshallows
Amend or rebase Breaks the link by changing commit hashes
Future fetches Treated as unrelated — no unshallowing

TL;DR

To stop Git from merging histories when fetching from a shared origin:

  • Rewrite your commits to change their hashes (--amend or rebase --root)
  • Then fetch — and Git will treat them as separate histories

This is especially useful when:

  • Using template repositories
  • Trying to isolate derived projects
  • Managing clean shallow clones