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-repositoryShould 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 -vBaseline 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 upstreamThis 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 --tagsThe 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 mainWithout 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 tracksSee also
- Repoint and Push a Remote — changing a remote URL and pushing a branch to it.