How big is a Git commit?
back to Git.
Short answer: It depends. Git stores "objects" as zlib compressed data. So the exact size of a commit will depend on the compressibility of your files (which is basically a function of the amount of repetition in them).
The other factor is that Git eventually turns object files into even more efficient packfiles, saving additional space by getting rid of redundancy across objects.
For fun, I did some little experiments (all "loose objects" with no packfiles created). Here’s the results:
-
64,828 bytes - git init
-
47,640 bytes - committing 250 tiny files
-
17,145 bytes - committing 3 bytes of change to a file in a directory of 50 files
-
8,709 bytes - committing 3 bytes of change to a single-file repo
-
297,873 bytes - committing a 583,840 byte binary file
-
1,622,188 bytes - committing a huge 16,415,223 source file
So we see kilobytes of overhead for very tiny commits - exactly how much will depend on the size of the file/directory tree involved with the changes.
For larger commits with small numbers of files, the stored data in .git will be anywhere from 50% to 10% of the uncompressed committed files.
Below is the running log of the experiments resulting in the numbers above.
Init, 5 directories, 250 files
First, how big is a brand new empty Git directory (.git)?
$ git init Initialized empty Git repository in /home/dave/tmp/foo/.git/ $ du -sb .git 64828 .git
About 64 Kb.
(The du options are: s to summarize and b to display bytes
Now I’m going to make a bunch of tiny files in directories with a pair of nested shell loops:
$ for d in {1..5};do
mkdir $d;
for f in {1..50};do
echo foo > $d/$f;
done;
done
Now I have 250 files in 5 directories containing the string "foo":
$ ls 1 2 3 4 5 $ cat 2/45 foo
I’ll commit them:
$ git add . $ git commit -m 'initial commit'
Let’s see how big .git is now:
$du -sb .git 112468 .git
The commit has added about *47 Kb to the initial blank repo.
Aside: I calculated this in the geekiest way I could think of, using the standard Unix command dc, the arbitrary precicision reverse-polish notation desk calculator (note that 'p' is the print command so we can see the result!):
(---- $ dc -e '112468 64828 - p' 47640
Now I'll make one tiny change to one file and commit it:
$ echo bar > 1/1 $ git commit -am 'changed 1/1'
$ du -sb .git 129613 $ dc -e '129613 112468 - p' 17145
So that's *17 Kb* to store about 3 bytes of changes to my repo. Where is that weight coming from? I'm gonna do another little commit. Here's what it looks like before:
$ du -b .git 4096 .git/objects/info 4096 .git/objects/pack 4115 .git/objects/25 4155 .git/objects/7b 4225 .git/objects/af 4115 .git/objects/57 4271 .git/objects/07 4177 .git/objects/61 4255 .git/objects/bb 4299 .git/objects/a8 45900 .git/objects 4336 .git/info <4096 .git/refs/tags 4137 .git/refs/heads 12329 .git/refs 4096 .git/branches 4411 .git/logs/refs/heads 8507 .git/logs/refs 12918 .git/logs 27538 .git/hooks 129613 .git
Then I modify file 1/1 again to contain the string 'baz' and commit that. After:
4096 .git/objects/info 4096 .git/objects/pack 4115 .git/objects/25 4253 .git/objects/81 ←- new 4 Kb 4155 .git/objects/7b 4225 .git/objects/af 4115 .git/objects/57 4271 .git/objects/07 4177 .git/objects/61 4302 .git/objects/fc ←- new 4 Kb 4255 .git/objects/bb 4115 .git/objects/76 ←- new 4 Kb 4299 .git/objects/a8 4177 .git/objects/92 ←- new 4 Kb 62747 .git/objects 4336 .git/info 4096 .git/refs/tags 4137 .git/refs/heads 12329 .git/refs 4096 .git/branches 4561 .git/logs/refs/heads ←- added 0.1 Kb 8657 .git/logs/refs 13218 .git/logs 27538 .git/hooks 146759 .git
That's 4 new objects for a single-file commit. Thanks to Julia "b0rk" Evans's awesome work on the https://jvns.ca/blog/2026/01/08/a-data-model-for-git/[new Git data model documentation] (jvns.ca) , I can figure out what these new objects are. Although these files are all zlib compressed data, I figured out that `git show` will show the value of *any* object by hash identifier, not just commits! So to view these objects, I did:
$ ls .git/objects/81 b1a9d27494b40679d612b96bb6acaac83afa9c $ git show 81b1a9d27494b40679d612b96bb6acaac83afa9c
And the results are: * 81... is my actual commit * fc... is the tree file for the changed directory `1`., listing all of the files in that directory (1 through 50). * 76... is the actual contents of file 1/1 (which is now the string 'baz') * 92... is another tree for the root directory of the repo That makes sense. There's a commit, two trees, and one file. == Tiny repo How about a repo with just a single little file. How much space does a commit require then?
$ git init $ echo foo > foo $ git add foo $ git commit -m 'initial' $ du -sb .git 94208 $ echo bar > foo $ git -am 'change1' $ du -sb .git 102917 $ dc -e '102917 94208 - p' 8709
So that's *8 Kb* per commit, about _half_ the size of the repo with a larger tree of files. I suspect a lot of the size of both of these is overhead and larger commits will see substantial savings. Sure enough, when I add a big (580 Kb) binary file:
$ cp /usr/bin/librewolf . $ du -b librewolf 583840 $ git add . $ git commit -m 'added librewolf' $ du -sb .git 400790 $ dc -e '400790 102917 - p' 297873
The binary compresses quite a bit, so the commit is considerably smaller than the added file (*300 Kb* for a 580 Kb file). And even better, how about a huge source file:
$ cp /usr/src/linux…mask.h . $ du -b nbio_7_2_0_sh_mask.h 16415223 $ git add . $ git commit -m 'huge source' $ du -sb .git 2022978 $ dc -e '2022978 400790 - p' 1622188
So that's *1.6 Mb* to commit a 16.4 Mb source file!