How to shrink your .git folder in your git repo
First try this
If you have a lot of duplicate data, try running git gc
. It has the potential to save a lot of space when you have tons of duplicate copies of the same or similar files. See here: Does git de-duplicate between files?, and my answer and anecdotal experience on it here, where git gc
automatically compressed a whopping 107 GB down to 11 GB.
Summary
Do, in this order, from least-dangerous and/or most-effective and/or fastest to more-dangerous and/or less-effective and/or slowest.
Note that the git lfs
lines only apply if you have git lfs
installed. Google for it and you'll see it's a 3rd party stand-alone application. If you don't have git lfs
installed, just ignore those lines. See my comments below this answer, starting here. Also, if you don't use git lfs
, don't. It has the potential to cause many problems. I talk about it in my question here, for instance.
These test results are for a repo where du -hs --exclude=.git .
shows that the total repo size, NOT including the .git
dir, is about 80 GB, and du -hs .git
showed that the .git
folder alone started out at about 162 GB:
Update: definitely do run time git gc
! It can have a huge space savings in cases where text files are largely duplicated. See my answers here and here.
# Memory Saved
# Time it took in .git dir
# ------------ ------------
time git lfs prune # 1~60 min 62 GB
time git gc # 3 min < 1 GB
time git prune # 1 min < 1 GB
time git repack -a -d --depth=250 --window=250 # 2 min < 1 GB
# (Note: `--prune` does nothing extra here; `man git gc` says
# `--prune is on by default`)
time git gc --aggressive --prune # 1.25 hrs < 1 GB
As you can see, the last command takes a very long time for very little benefit, so don't even run it!
Also, an alternative to running git lfs prune
is to just delete the whole .git/lfs
directory manually instead, then re-fetch the lfs (git Large File System) contents from scratch after.
CAUTION: do NOT accidentally delete the whole .git
directory instead! YOU'LL LOSE ALL GIT HISTORY, BRANCHES, AND COMMITS FOR THIS REPO! Delete only the .git/lfs
directory. Something like this might work:
# 1. Delete the whole git lfs directory
rm -rf .git/lfs
# 2. Re-fetch the git lfs contents again from scratch.
# See my answer here: https://mcmap.net/q/12212/-what-is-the-difference-between-git-lfs-fetch-git-lfs-fetch-all-and-git-lfs-pull
# Option 1 (recommended): fetch (to the ".git/lfs" dir) AND check out just the
# git lfs files for just the one branch or commit you currently have
# checked-out.
# - this might download ~20 GB of data on a large corporate mono-repo
git lfs pull
# OR do this (these two commands do the exact same thing as `git lfs pull`)
git lfs fetch
git lfs checkout
# Option 2: fetch (to the ".git/lfs" dir) ALL git lfs files for ALL branches on
# the remote
# - this might download ~1000 GB of data on the same large corporate mono-repo
# as above
git lfs fetch --all
# Also check out, or "activate" the git lfs files for your currently-checked-out
# branch or commit, by updating all file placeholders or pointers in your
# active filesystem for the current branch with the actual files these git lfs
# placeholders point to.
git lfs checkout
For details on the git lfs
commands shown just above, see my other answer here: How to use git lfs
as a basic user: What is the difference between git lfs fetch
, git lfs fetch --all
, git lfs pull
, and git lfs checkout
?
Details
First off, you need to know what in the .git folder is taking up so much space. One technique is to run the ncurses-based (GUI-like) ncdu
(NCurses Disk Usage) command inside your repo. Another way is to run this:
du -h --max-depth=1 .git
Side note: To see how big your repo is, NOT including your .git
folder, run this instead:
du -h --max-depth=1 --exclude=.git .
Sample output of the 1st command above:
$ du -h --max-depth=1 .git
158G .git/lfs
6.2M .git/refs
4.0K .git/branches
2.5M .git/info
3.7G .git/objects
6.2M .git/logs
68K .git/hooks
162G .git
As you can see, my total .git
folder size is 162 GB, but 158 GB of that is my .git/lfs
folder since I am using the 3rd-party "Git Large File Storage" (git lfs
) tool to store large binary files. So, run this to reduce that significantly. Note: the time
part of all commands below is optional:
time git lfs prune
(If git lfs prune
fails with "panic: runtime error: invalid memory address or nil pointer dereference", see my notes below.)
Source: How to shrink a git LFS repo
Official documentation: git-lfs-prune(1)
-- Delete old LFS files from local storage
That took 60 seconds to run!
Now I've just freed up 62 GB! My .git/lfs
folder is now only 96 GB, as shown here:
$ du -h --max-depth=1 .git
96G .git/lfs
6.2M .git/refs
4.0K .git/branches
2.5M .git/info
3.0G .git/objects
6.2M .git/logs
68K .git/hooks
99G .git
Next, run this to shrink the .git/objects
folder by a few hundred MB to ~1 GB or so:
time git gc
time git prune
git gc
takes about 3 minutes to run, and git prune
takes about 1 minute.
Check your disk usage again with du -h --max-depth=1 .git
. If you'd like to save even more space, run this:
time git repack -a -d --depth=250 --window=250
That takes about 2 minutes and saves a few hundred more MB.
Now, you can stop here, OR you can run this final command:
time git gc --aggressive --prune
That final command will save a few hundred more MB but will take about 1.25 hours.
If git lfs prune
fails with "panic: runtime error: invalid memory address or nil pointer dereference"
If git lfs prune
fails with:
panic: runtime error: invalid memory address or nil pointer dereference
then you may have an old version of git-lfs
installed and need to update it. Here is how:
First, check to see what version you have installed. Run man git-lfs
and scroll to the bottom to see the date. Maybe it says it is from 2017, for instance. Now, update your version with these commands. The first command comes from here: https://packagecloud.io/github/git-lfs/install.
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
sudo apt update
sudo apt install git-lfs
Run man git-lfs
again and scroll to the bottom. I now see my date as "March 2021", when previously it was some date in 2017.
Also, if I run sudo apt install git-lfs
again, it tells me:
git-lfs is already the newest version (2.13.3).
So, the update for git-lfs
worked, and now the error is gone and git lfs prune
works again!
I first documented this in a comment on GitHub here: https://github.com/git-lfs/git-lfs/issues/3395#issuecomment-889393444.
References:
- @knittl: How to shrink the .git folder
- @David Dehghan: How to shrink the .git folder
git lfs prune
: How to shrink a git LFS repo
- Linus Torvalds on
git repack -a -d --depth=250 --window=250
: https://gcc.gnu.org/legacy-ml/gcc/2007-12/msg00165.html
- https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-prune.1.ronn
See also:
- Does git de-duplicate between files?
- My Q&A: How does git LFS track and store binary data more efficiently than git?
- My answer: Unix & Linux: All about finding, filtering, and sorting with
find
, based on file size - see the example near the end, titled "(Figure out which file extensions to add to git lfs
next)".
- Other really useful
git lfs
info:
- Great article!: my developer planet: Git LFS: Why and how to use
- https://git-lfs.github.com/
- My repo and notes: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles#how-to-clone-this-repo-and-all-git-submodules
- ***** [my Q&A] How to use
git lfs
as a basic user: What is the difference between git lfs fetch
, git lfs fetch --all
, git lfs pull
, and git lfs checkout
?
- [my Q&A] How to resume `git lfs post-checkout` hook after failed `git checkout`
- Note: for pure synchronization, try FreeFileSync or
rsync
, as I explain in my answer here. That being said, occasionally I use git
for synchronization too, as I explain for my sync_git_repo_from_pc1_to_pc2.sh
tool here, and in my other answer here: Work on a remote project with Eclipse via SSH.
- ***** My answer: What are the file limits in Git (number and size)?
- ***** My answer: Does git de-duplicate between files?
git count-objects -v
? – Sourdoughgit lfs
was taking up tons of space in the.git/lfs
dir. By runninggit lfs prune
I reduced my.git
folder size by >60 GB! I added this information and more in my answer here. – Razor-f
argument? – Razor