TL;DR: what you really want is the fetch.prune
setting. Still, I'm going to answer the question you asked, rather than the one you should have. :-)
To turn your existing clone into what looks like a fresh clone, you need at least four steps.
Run git fetch -p
. Or, configure fetch.prune
to true
in either your local repository or your per-user settings and run git fetch
. This will delete any origin/*
remote-tracking names in your repository corresponding to branch names that used to, but no longer, exist in the repository at origin
.
Manually delete any branches that you don't want—all but one. To do this you'll have to check out the one you are willing to retain. Automate this removal if you like, but be aware that if you have commits you never sent upstream, you may lose those commits at this point. See below.
git reset --hard
your remaining branch(es) to their remote-tracking counterparts. You may lose some commits at this point. See below.
Run git clean -dfx
. See below.
You now have what resembles a fresh clone, except for these items:
The reflog for your HEAD
still has all your recent activity, which may retain some commits. You can clean that out too, using git reflog expire --expire=all --expire-unreachable=all
.
Any stashes you have still exist. You can drop them all with git stash clear
.
Any unusual references you have made still exist (e.g., refs/notes/
, refs/replace/
from git replace
). You must delete those manually if desired.
Any shallow clone status persists. You can use git fetch --unshallow
to clear that out.
Some assume-unchanged or skip-worktree bits may still be set in the index. You can use git update-index --no-assume-unchanged
and git update-index --no-skip-worktree
to fix these. You only need to do this if you set those bits earlier; Git never sets them on its own.
(I think that's everything but I might be missing an item or two.)
Notes
If you were to do a fresh git clone
, you would:
- create a new empty repository:
mkdir name; cd name; git init
- add to it a remote named
origin
using the appropriate URL: git remote add origin url
- run
git fetch
to acquire all its existing branches as your origin/*
remote-tracking names
- pick one of those branches (based on your
-b
argument to git clone
) to create locally
- run
git checkout name
, which creates name from origin/name
.
This new repository has the same remote-tracking names that remain after step 1 (the pruning fetch), so step 1 fixes your remote-tracking names. It has no branch names—no refs/heads/*
references—other than the one created in the last step, so step 2 removes these. You are of course on that one remaining branch, so step 2 includes the git checkout name
and step 3, git reset --hard
, makes your branch name point to the correct commit while updating all of your index and most of your work-tree.
Of course, untracked files and directories may remain, so step 4, git clean -dfx
, has Git remove them, including files ignored by .gitignore
directives.
To automate removing branches that are not the current branch, you'll need a small script. There are some in the linked questions (the possible duplicates). But these delete your branches, which are not anyone else's branches. You should not just randomly delete them: you should already delete them yourself when you're done with them, so there should be nothing to delete. This is why steps 2 and 3 are listed, but shouldn't be done—at least, not automatically.
The last operation, git clean -dfx
, removes build artifacts (e.g., compiled *.o
files or *.pyc
byte-coded Python files). Usually you want to do this manually under your own control, not just because something has changed upstream.