6

I want to check my understanding of Git garbage collection here.

Say you have two branches: master, and newidea. At a certain point you merge newidea into master, and delete the branch newidea.

The commits you made while working on newidea would never be garbage-collected, since they are now part of master's tree due to the merge, right?

By contrast had you never merged, those same commits would eventually be garbage-collected since they are no longer reachable from a living branch.

Do I have that right?

Stephen
  • 8,508
  • 12
  • 56
  • 96

1 Answers1

5

Yes, you are correct1. Orphaned commits... commits that are not referenced by a branch or tag, are garbage collected after a certain (configurable) length of time.

Commits that are referenced either directly by a branch or tag or indirectly through the commit history of another referenced commit are preserved and will not be garbage collected.

It's not only commits that are garbage collected. Various plumbing commands can create files and trees that, for various reasons, might not be referenced by a commit. Those objects will also be garbage collected.

For more information, see documentation for git-gc, specifically:

git gc tries very hard not to delete objects that are referenced anywhere in your repository. In particular, it will keep not only objects referenced by your current set of branches and tags, but also objects referenced by the index, remote-tracking branches, refs saved by git filter-branch in refs/original/, or reflogs (which may reference commits in branches that were later amended or rewound). If you are expecting some objects to be deleted and they aren’t, check all of those locations and decide whether it makes sense in your case to remove those references.


1 One caveat: while a standard git merge will retain a reference to both source commits (thus preserving the commits in both branches, even if the source branch is eventually deleted), there are other ways to "merge" a commit/branch that will not preserve a reference to the original commits, such as a git cherry-pick, git rebase or a git merge --squash. If you use one of these commands, you will preserve the substance of the original commits (contents, author, dates, etc), but not the commits themselves, after the issue branch is deleted.

Also note that even if you use a merge and squash, etc, some git servers (like GitHub) actually create a shadow branch for PRs, so while the original commits might be gc-ed on your local machine, they might continue to exist on the server.

JDB
  • 25,172
  • 5
  • 72
  • 123
  • 1
    Also worth mentioning (and the `git gc` documentation should probably get updated), Git will look in any additional index and detached `HEAD` references added with `git worktree add`. – torek Oct 11 '17 at 17:19