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:
- Have a template repo
- Create a shallow clone of it (using
--depth 1
) - Remove the remote, and start treating it as a separate project
- 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
orrebase --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