Reputation: 1240
Lets say I've created a new repo (in Github or Gitlab doesnt matter), then:
git clone <uri>
touch test
git add .
git commit -m "Initial"
git push
Which commands do I need to execute such that the remote repo is reseted/reverted to an empty repository without any history, aka, in a state just like when I first created the repo?
Every google search has a git add and git commit
in the list of commands to execute, which won't work, since I want a completely clean repo.
Upvotes: 3
Views: 2457
Reputation: 487725
A totally-empty repository, as freshly created by git init
, has no commits and no branches (and no tags, and so on). Oddly enough, though, you're on your initial branch—whatever it will be—at this point, even though it does not exist.
Locally, you can get back to this state—well, almost; see footnote 1—simply by deleting every branch. This requires one special trick, because you are never allowed to delete the current branch, whatever it is. So you must use git checkout --orphan
or git switch --orphan
to set things up so that the current branch is a branch that does not exist. This puts your Git back in that odd state of being on a branch that does not exist. That makes it possible to delete all the other branches.1 You can now change the name of the branch you are on, that does not exist, to some other name—the name you want to come into existence in the future, when you make the initial commit—using git checkout -b
or git switch -c
.
Hence, the recipe for doing this, assuming you have no tags, no stashes, and so on, is:
git checkout --orphan fakebranch
for name in <insert your list of branch names>; do git branch -D $name; done
git checkout -b main # or whatever name you want here
Note that the for name in ...; do <commands>; done
loop is a shell (sh/bash) construct, not a Git command; in other command line interpreters you may need other commands, or you can just run one git branch -D
per branch.
There's one big problem here: you did not ask how to do this locally but rather how to do it on GitHub, GitLab, Bitbucket, and so on. Since those sites do not give you command-line Git, there's no obvious way to make them run git checkout --orphan
or something equivalent. In fact, there's no way at all to do that on GitHub, as far as I know. Whether there is on any other hosting site, I don't know. This means that, as Asif Kamran Malick said, you literally can't do it.
1The commits that were find-able through those other branches are not necessarily gone yet. With no way to find them, though, Git will eventually delete those commits. Until that happens, the apparently-empty Git repository will consume extra disk space to hold those not-yet-garbage-collected commits. You can use git gc
, or some of its underlying commands, to garbage collect those commits sooner, but there's rarely any reason to bother: just let Git do it on its own, when Git gets around to it.
You can get very close, as noted in Git: How to reset a remote Git repository to remove all commits?, by creating one new root commit, pushing that to the main branch with --force
, and deleting all the other branches. Note also that when creating a new repository on GitHub, you can choose to create a new repository with one initial commit. If you make your new root commit here match the GitHub-created root commit, this gets you something that looks like you had GitHub create it, even though you didn't. And, since you suggest creating an initial commit and sending it, your own initial commit will suffice for this purpose.
Since your own recipe listed these commands:
git clone <uri> touch test git add . git commit -m "Initial" git push
we can make our new root commit consist of a commit with log message Initial
and just one empty file named test
. To do that, we have the following two recipes, one for Git versions predating 2.23 and one for 2.23 or later:
# git < 2.23
git branch -m main out-of-the-way # replace main with master if necessary
git checkout --orphan main # likewise
git rm -rf .
cp /dev/null test # adjust per OS
git add test
git commit -m Initial
git push -f origin
git push --delete origin <list of other names> # if needed
for name in <list of names>; do git branch -D $name; done # if needed
or:
# git 2.23 or later
git branch -m main out-of-the-way # replace main with master if necessary
git switch --orphan main # likewise
cp /dev/null test # adjust per OS
git add test
git commit -m Initial
git push -f origin
git push --delete origin <list of other names> # if needed
for name in <list of names>; do git branch -D $name; done # if needed
Note that the only difference here is that we need not empty out the index (the git rm -rf .
step, which also cleans up the working tree).2 This does have to be run from the top level of the working tree in either case (so that the file "test" can be created in the right place).
2This is because git switch --orphan
does this for us. The old git checkout --orphan
continues not to do it.
Upvotes: 2