Git: how to repack all loose commits

2020-07-09 09:12发布

问题:

After using git gc and git repack (with various options) I still have 4825 loose commits in the folder .git/objects. I would like to have all of them in the pack file with the rest or in another pack file.

I'm doing lots commit rewriting (amend + rebase) hence it's perfectly normal to have many unreachable commits. My .gitconfig contains these parameters to keep reflogs and unreachable commits for a long time.

[gc]
    reflogExpire = 300 days
    reflogExpireUnreachable = 200 days
    pruneExpire = 90 days

You may wonder if it make sense but I already needed and have recovered a few commits made several months ago. It happens we develop for many months on a new set of higher priority branches and afterwards continue on the older lower priority branches.

The main reason for this question is that git gui keeps on complaining to compress my database despites I have done this many times. If we are not able to pack those loose commits then this "complaining" might be a bug in git gui.

回答1:

Considering that git bundle is used to work with packaging objects only (calling fetch-pack), did you try to bundle, and then clone your repo?

git bundle create aBundle --all # hopefully package everything, 
                                # the result being *one* file.
git clone aBundle newRepo       # recreate a full repo
# check if the cloned repo contains only packaged object

If this works, you might go on, using the new cloned repo as your main repo.



回答2:

The warning from git-gui is just a hint that you might want to do some maintenance. For most people having a high number of objects is just slowing them down. In your case, you should disable the warning. The function in question is hint_gc and it is called from near the end of the git-gui script file. Just comment it out as below.

if {[is_enabled multicommit]} {
        #after 1000 hint_gc
}

The multicommit business is a flag that determines if we are running as committool or a general purpose app.

If you want to use git-gui normally elsewhere, then you could add a respository specific flag instead. Something like:

if {[is_enabled multicommit] && ![is_config_true gui.skip_gc_warning]} {
        after 1000 hint_gc
}

should let you use git config --bool gui.skip_gc_warning true to disable that on a per-repository basis.