Rehoming a Fork

Why this comes up

Applies whenever you’re working inside a checkout of someone else’s repo — cloned it, or it came pre-set-up as a base/template/tooling project — and partway through you realize:

  • You’ve built genuinely new, possibly sensitive work inside it (plans, findings, configs).
  • The repo’s origin points at the original project’s server. You don’t own it, don’t have push rights to it as a destination for your own work, and even if you did, pushing internal work there would leak it into someone else’s shared/public history.
  • But the repo isn’t just your new work — it also has useful base tooling (configs, scripts, docs) you want to keep, and possibly share with a team, rather than discard.

The fix isn’t “start a fresh empty repo” (loses the tooling and all its history) or “copy files by hand into a new repo” (loses git history and any branches). It’s: keep the exact same local checkout, but re-point where it syncs to. Git makes this cheap because it’s fully distributed — a repo isn’t tied to any one server, it’s just data plus a list of remembered remote addresses.

The steps

1. Confirm you have full history, not a shallow clone

git rev-parse --is-shallow-repository

Should print false. Some clones (especially CI checkouts) are “shallow” — only recent commits, not full history. If true, run git fetch --unshallow first, or the re-homed copy permanently loses history.

2. See what remotes currently exist

git remote -v

Baseline check before changing anything — confirms which remote is the “someone else’s server” one you’re moving away from.

3. Turn remote-tracking branches into real local branches

git branch <branch-name> origin/<branch-name>

Cloning downloads all branches’ data, but only checks one out as a local branch (usually main). The rest exist as references to already- downloaded data (origin/some-branch), not local branches. A later push --all only pushes local branches — anything left as remote-tracking-only silently gets left behind. Do this for each branch you want to carry over.

4. Rename the old remote out of the way (don’t delete it)

git remote rename origin upstream

This is the step that actually solves the original problem: it frees up the name origin for your new destination, while keeping the old server reachable under upstream — in case you ever want to pull future updates from the original project without re-adding it from scratch.

5. Point origin at your own destination

git remote add origin <new-repo-url>

This is where your work will actually live going forward — somewhere you control. The destination has to already exist (even empty); git doesn’t create remote repos for you, only pushes into ones that exist.

6. The actual data transfer

git push origin --all
git push origin --tags

The one step that leaves your machine — everything before this was local-only file edits under .git/. --all pushes every local branch at once; --tags does the same for tags (not included by --all). After this, the new destination has an exact, complete copy: full history, every branch.

7. Make git push/pull default to the new home

git branch --set-upstream-to=origin/main main

Without this, plain git push/git pull (no arguments) stay ambiguous or fall back to old tracking info. This makes the new origin/main the default target.

Quick verification

git remote -v                          # remotes and their URLs
git remote get-url origin              # just origin's URL
git branch -vv                         # local branches + what each tracks

See also