Search code examples
gitbranchcommit

Does git remote store deleted branches?


I was doing some experimentation to test my understanding of how git stores branches.

My understanding was that Git stores ALL commit hashes, so even if you delete a branch, the snapshot for that branch still exists under a commit hash, you can restore a deleted branch provided you know the hash.

To test this I tried the following (across two computers where I was pushing the repo to Github) :

Create a repo on GitHub

Computer 1 :

  • clone repo
  • create branch experiment
  • add a file to experiment and push it to GitHub
  • Make note of hash for the last commit to experiment
  • delete experiment branch via :
  • git push -d origin experiment
  • git branch -d experiment

Computer 2 :

  • clone repo
  • Fetch/Pull
  • try to restore the deleted branch experiment, checkout the hash I made a note of

Results

  • On computer 2 I get error: pathspec 'd168' did not match any file(s) known to git
  • On computer 1 it works.

So I guess my understanding is wrong. you can only restore a deleted branch if you still have the info locally. i.e. the info relating to the deleted experiment branch only exists on Computer 1? not on the remote GitHub repo?

so cannot be used from Computer 2?


Solution

  • The documentation for git-clone states: "Clones a repository into a newly created directory, creates remote-tracking branches for each branch in the cloned repository (visible using git branch --remotes), and creates and checks out an initial branch that is forked from the cloned repository’s currently active branch."

    What this means is that when you clone the repository, it only copies the commits that are needed to make copies of all of the branches on the remote. In your case, the commit d168 is on the remote (unless github has a very aggressive garbage collection policy and has already deleted it), but it is not needed for any of the branches that currently exist (because you deleted the branch), so it is not copied during the fresh clone.

    Try git fetch origin d168.... to retrieve the commit from the remote. If a commit is needed for a ref (loosely, it is the ancestor of some current branch tip or tag), then it will persist in the repository indefinitely. If it is not needed for a ref, then at some point it may be deleted. Typically, the default is to keep all commits for at least 30 days, so unless the garbage collection has been tuned to be more aggressive the commit should still be on the remote.