How to identify reachability of a certain commit?

Viewed 36

I am trying to clean a repo:

local FIRST_COMMIT="bf450342272a94117d78eae34a140a2a39359dad"
git branch -d bad-master
git remote remove bad-remote
git rev-parse ${FIRST_COMMIT} > .git/shallow
git fsck --unreachable
git gc --prune=now

The idea is the following:

  • keep a single branch (the develop) branch
  • remove all unwanted references
  • cut the history in the develop branch, with .git/shallow / gc --prune

After doing this, I have verified the following:

  • there are no remotes defined
  • there are no tags defined
  • there is a single branch: develop
  • the history in the develop branch is indeed reduced up to the specified commit

But there is still a problem:

git rev-list --all

Lists commits which are not reachable through the develop branch!

I do not understand why git fsck --unreachable does not list that, and why git gc --prune=now does not remove those commits. The only explanation is that those commits are reachable, through other references. Which ones?

How can I identify how a given commit is reachable?

What I expect is:

  • identify a reference which I was missing up to now (branch / remote / tag / ???)
  • remove that reference
  • after that, prune will remove the unwanted commits.
1 Answers

Use git for-each-ref to iterate through all references (the default is to display them and their hash IDs and object types).

Note that git for-each-ref only looks at refs, not at their corresponding reflogs. Use git reflog on each ref to examine (or expire) their reflogs. Deleting a ref deletes its reflog, so if there are no other refs, the problem is most likely the reflog for develop; however, git rev-list --all looks at all refs but not reflogs, so I expect there is some other ref finding these commits.

Related