13

Assume I create a branch in my local repository named feature1 based on master and add one or two commits. Then I switch back to master and decide that feature1 is not going to make it and delete the branch.

I assume that a branch is basically a "pointer" to a particular commit object.

Now on to the actual questions.

  1. Is the assumption above correct, perhaps in some simplified sense?
  2. For how long do the commit objects still exist on the filesystem (so that I can later do git checkout SHA1-HERE)? Is there some kind of "retention policy" that would remove commits which are not part of any existing branch history or tag (not sure if using correct terminology here...) ?
  3. Would any of the above be dependent on the git server's implementation (gitosis, github, etc...)?
  4. If the objects are kept around forever and are not auto-cleaned after some time/event, would it imply that setting git's receive.denyNonFastForwards as a measure to prevent data loss is meaningless?

Reason for this question: I am currently working on a project that has receive.denyNonFastForwards enforced on the basis that it avoids losing any committed work (I suspect receive.denyDeletes is also enforced). I want to make sure there is no better way to preserve commited but unmerged work and also be able to clean up old branches to avoid clutter.

Robert Rossmann
  • 11,931
  • 4
  • 42
  • 73

1 Answers1

13

The default s 90 days:

gc.reflogexpire
gc.<pattern>.reflogexpire

git reflog expire removes reflog entries older than this time; defaults to 90 days. With "<pattern>" (e.g. "refs/stash") in the middle the setting applies only to the refs that match the <pattern>.

So:

  1. Yes
  2. 90 days
  3. no (you actually can contact GitHub support to ask them and restore a deleted pushed branch)
  4. "preserve commited but unmerged": you can push it on a dedicated dev branch or to a dedicated upstream repo (just for you)
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 2
    Thanks, `man git-gc` and `man git-reflog` was the missing piece of puzzle. Would it not make more sense then to just prevent the server's repo to prune loose objects instead of denying branch deletions? In practice, you rarely (read, never) push a rebase so it's not like there would be thousands of loose objects hanging around... – Robert Rossmann Dec 10 '14 at 09:50
  • I think it might help to distinguish between reflog on your own machine, and how long orphaned commits hang around on someone else's machine. If OP pushed out his branch and then rebased or deleted it, I think those orphaned commits would by default stick around for 90 days in reflog on OP's machine, and just 2 weeks for everyone else that had fetched them while they were on the remote? – TTT Jan 27 '21 at 18:06
  • @TTT Why two weeks? A reflog is always local. – VonC Jan 27 '21 at 18:09
  • Right. I mean- I landed on this question wondering how long my repo would retain someone else's orphaned commits. Suppose after the first sentence OP pushed out the branch and I fetched. Then OP deletes local and remote branch, and I fetch again and the branch is pruned. How long does my repo retain those commits? Assume I never looked at OPs branch at all so it's not in *my* reflog. – TTT Jan 27 '21 at 18:33
  • @TTT Standard 90 days: for a local repo, any commit which is no longer references by a tag/branch becomes orphan, whether or not it was from "someone's else branch". It does not matter you have looked or not at OP's branch: as long as it was fetched, it was referenced by a remoye tracking branch. If said remote branch is pruned from your local repo, those commits becomes orphan (in your repo), hence 90 days. – VonC Jan 27 '21 at 18:35
  • Perhaps I'm confused by the fact that when `git gc` runs automatically it appears to use `--prune` by default, and that has a default of 2 weeks. This is why I assumed that if an orphaned commit is not in my reflog that it may not last longer than 2 weeks. Sounds like you're saying it would still be 90 days though? If yes I don't understand why it wouldn't be gc'd. – TTT Jan 27 '21 at 18:55
  • 1
    @TTT But those two weeks are for loose objects (objects not in a packfile: https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery), not for orphan objects (referenced by reflog). Plus, git gc will soon be replaced by `git maintenance`, that I mention in https://stackoverflow.com/a/64077241/6309 and https://stackoverflow.com/a/64627726/6309. It will process those same loose objects by batch (https://git-scm.com/docs/git-maintenance#Documentation/git-maintenance.txt-loose-objects) instead of a "stop the world' approach. – VonC Jan 27 '21 at 19:02
  • Perfect! I realize now I had mixed up "loose object" with "orphan commit" when reading the docs. Fantastic linked answers too. – TTT Jan 27 '21 at 19:18