$ git init Initialized empty Git repository in /home/dave/tmp/foo/.git/ $ du -sb .git 64828 .git
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
(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
$ git add . $ git commit -m 'initial commit'
Let’s see how big .git is now:
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.
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.
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
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.