1

I have been trying to code up an experiment that involves putting the following code in the post-receive git hook:

unset GIT_DIR
cd (path to some temp directory outside the repository)
git clone --local (path to repository just pushed to) .
git checkout dev
git reset --hard HEAD^
git reflog expire --expire=now --all
git gc --aggressive --prune=now

Basically what I'm doing is cloning the repository that was just pushed to, doing a hard reset to remove the last commit, and then doing garbage collection to remove traces of the last commit from history. To check that the garbage collection is really doing its job, I commit a huge 4-MB file in the last commit, and then check the size of .git to see if it's been removed.

So when I run this code inside the git "post-receive" hook, the reset seems to work fine; the cloned repository is back in the state without the huge file. However, the garbage collection doesn't seem to have worked. The size of .git is still huge.

On the other hand, if I manually run "git reflog" and "git gc" from the command line at this point, it correctly removes the traces of the huge file, and the size of .git is restored to a manageable size.

Any ideas why garbage collection might behave differently when run within "post-receive", rather than at a command prompt?

Daryl McCullough
  • 303
  • 5
  • 20

2 Answers2

1

Git aggressive garbage collection might not be doing what you're expecting. Linus posted about this here. But it has also been covered in other posts:

Community
  • 1
  • 1
andygavin
  • 2,784
  • 22
  • 32
  • Thank you, I will try repack. But my major point was about the difference in results between running the above code in post-receive, as opposed to manually entering it in a command prompt afterward. I can't understand why that would make a difference. – Daryl McCullough Sep 09 '15 at 14:57
0

Okay, I think I managed to get to the bottom of this. It doesn't actually have anything to do with being in post-receive, or not.

Just a bit more about the problem that prompted this question. I have a repository, call it "repo". The last commit to this repository was a huge file, call it "BigFatFile.bin" This is 4 MB in size. This file should not be in the repository. So my attempt to fix the problem is this:

  1. Clone the repository.
  2. Do git reset --hard to remove the last commit.

These steps manage to remove "BigFatFile.bin" from the cloned repository. However, the effects of this push are still visible, in the sense that the .git directory is still huge: The 4MB of "BigFatFile.bin" is still reflected in the directory .git/objects/pack

At this point, I can try various cleanup commands to try to get rid of the effects of "BigFatFile.bin":

git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git repack -a -d -f --depth=250 --window=250
git gc --aggressive --prune=now --force

These steps have no significant effect on the size of .git. However, what I discovered is that if I do git push -f origin master immediately after git reset --hard, and then do the cleanup steps, the size of .git is back to what it was before "BigFatFile.bin" was pushed. This doesn't solve my problem (because although the cloned repository is back as it was, the original repository is still bloated in size). However, it does answer my question about why garbage collection (and other cleanup measures) were having no effect: Until I "push" my changes, .git must be maintaining not only the local contents of files, but also their original contents.

So my original question (why didn't cleanup work locally) is answered, although I still don't know the answer to the real question, which is how to reset the remote repository so that it doesn't show the effects of the commit of "BigFatFile.txt"

Daryl McCullough
  • 303
  • 5
  • 20
  • I'm not sure this is an answer, more an elaboration of your question with new knowledge on what gc does. That is if you're looking for an answer this might form part of the question. – andygavin Sep 11 '15 at 13:17