Git inner workings 101: .git folder structure

Since the current API Call limit for my main side project is reached, let’s take a deep dive into that mysterious .git folder that gets created whenever you initialize a new git repository. In there we’ll find everything we need, to get a deeper understanding of how git works behind the curtain.

In this post, I will demonstrate some of git’s inner working by scuba diving into the .git folder of one of my personal projects. If you want to follow along, feel free to do so with one of your own projects. Make sure it has at least a few commits, or else there won’t be as much to do and see in there. With that out of the way, hold your breath and cd %projectname%.

If you don’t have ‘show hidden files’ enabled, you might not even know that the .git folder existed in the first place because the operating system hides all files beginning with a . by default. But don’t worry, you can always see them with the help of your terminal.

Inside a git repository, simply type ls -la

ls lists all the files in the current directory, -a tells it to not skip hidden files and -l uses the long listing format, which is optional, but makes everything easier to digest.

Into the Git Folder

Now you should be able to see .git listed there. And since it is there, we can cd into it…

Now we can run ls -la again and are greeted by something similar to this:

Let’s take a closer look at the top level files.


cat ing config gives us an output similar to this:

[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [branch "dev"] remote = origin merge = refs/heads/dev

As you can see, this is where some of the top level information/configuration is stored, such as the names of remotes and their related URLs, as well as info regarding the remote branches.


The head file stores a single line, a ref indicating where the HEAD (the currently checked out branch & commit) is currently pointing to. You probably noticed that all those “refs” don’t look like a sha key or anything else we could check out. That’s because those refs are actually aliases, defined in a file called info/refs which associates each of these refs with a corresponding commit sha.

There might be some others, such as ORIG_HEAD, which is the equivalent of the HEAD file, just pointing to the origins head. But these are the most important ones for the start.

A final word of warning: this is for educational use only, I can’t recommend messing with these files unless you really know what you are doing.

In the next post, we’ll see how Git actually goes about storing files/branches/tags etc.

Originally published at on November 5, 2016.