1

I have an automated process that creates a temporary commit and stash, does some stuff, and then pops the stash and reverts the commit.

After doing this a few times, the automated git gc complains that there is too much stuff for it to clean up, so I'd like this process to tidy up after itself.

I don't however want to completely wipe out any other orphaned commits or stashes that might be in the repository, so git prune and git gc --prune=now will be more destructive than I want.

Is there a way to specifically delete one commit or stash that is no longer accessible?

Ed Bennett
  • 63
  • 8
  • 3
    What does it mean “that there is too much stuff for it to clean up”? – Davis Herring Jul 30 '23 at 13:42
  • Also, why would wiping out other orphaned commits be a bad thing? If they are useful, they should be on a branch, or in stash, or tagged. – Amadan Jul 30 '23 at 13:44
  • 1
    @Amadan I disagree. You've never made an experimental detached commit? You've never used the reflog to undo a rebase? You'd lose that work if all orphaned commits vanished prematurely. – matt Jul 30 '23 at 13:49
  • The specific message in gc.log is `warning: There are too many unreachable loose objects; run 'git prune' to remove them.` – Ed Bennett Jul 30 '23 at 13:50
  • Git is specifically designed to do even destructive operations non-destructively so you can recover later. I've on occasion needed to go and dig around detached commits and stashes where I've accidentally wiped out some work. Given that the process I'm writing will be run by others, I don't want to write something that will wipe out their ability to do that. – Ed Bennett Jul 30 '23 at 13:52
  • This process you're writing doesn't sound good. What's it supposed to do? – matt Jul 30 '23 at 13:54
  • It's a pre-commit hook; I need to get a clean working directory to run `black` and `eslint` on so I only test the staged content, and temporarily committing the planned commit and stashing everything else is the easiest solution I've hit on (and worked perfectly until `git gc` started complaining at me). (I'm aware that `.pre-commit-config` and its tooling exists in this space, but the repo owner I'm working with has vetoed that solution.) – Ed Bennett Jul 30 '23 at 20:59
  • A collaborator has now pointed out that this is a really bad workflow, as it will destroy any open pipes to untracked files, among other issues. I'm now instead looking into making a temporary working copy to clean and run the tests in, which will remove the need I originally had. (Still, one would think it should be possible to expunge specific information without flushing everything…) – Ed Bennett Aug 02 '23 at 10:04

1 Answers1

1

Try first to git config --global gc."refs/stash".reflogExpireUnreachable now in order to configure the removal of reflog entries, limited to stash, older than this time and are not reachable from the current tip.

Then a git reflog expire would not be too destructive (as opposed to a git gc --prune=now)


For the rest, you can rely on git maintenance, (introduced with Git 2.29, Q4 2020).
Since Git 2.31, Q1 2021, it knows how to schedule packing refs cleanup.

See this article by Brooke Kuhlmann for illustration.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • If I'm reading this right, it would delete only unreachable stashes, rather than all unreachable objects? While the stashes are likely to be the bigger objects that `git gc` complains about, if possible I'd also like to clean out the orphaned commits, as they may become numerous. – Ed Bennett Jul 30 '23 at 13:55
  • @EdBennett "I don't however want to completely wipe out any other orphaned commits or stashes that might be in the repository": that does exactly that – VonC Jul 30 '23 at 13:55
  • You mean this does exactly wipe out other orphaned commits and stashes? I don't see a way to specify a commit ID or other ref, so I don't see how this answers my question, but perhaps my question was poorly posed. – Ed Bennett Jul 30 '23 at 21:03
  • @EdBennett Interesting. I do not know of a way to specify a commit ID. May be [`git stash drop `](https://git-scm.com/docs/git-stash#Documentation/git-stash.txt-drop-q--quietltstashgt) – VonC Jul 30 '23 at 21:15
  • `git stash drop` removes the reference to the stash from the `.git/refs/stash` file, but leaves the underlying stash commit intact in the repository. (See https://stackoverflow.com/questions/89332/how-do-i-recover-a-dropped-stash-in-git) – Ed Bennett Jul 31 '23 at 08:26
  • @EdBennett Hopefully, `git maintenance`, when executed regularly on a schedule, with `gc` activated, should avoid the "`warning: There are too many unreachable loose objects; run 'git prune' to remove them`". – VonC Jul 31 '23 at 08:29