No history yet

Git Internal Architecture

Inside the .git Directory

You know the basic commands: add, commit, push. But what happens when you run them? All the magic is orchestrated within a hidden directory in your project: .git.

This isn't just a folder; it's the complete database for your repository. It contains every version of every file, all the commit history, and the pointers that tie everything together. If you copy this directory, you have a full backup of the entire project history. Let's explore its key components.

# A typical .git directory structure
.git/
├── HEAD
├── config
├── description
├── hooks/
├── index
├── objects/
├── refs/
│   ├── heads/
│   └── tags/

While files like config and hooks/ are important for configuration and automation, the core of Git's versioning power lies in objects/, refs/, index, and HEAD.

Git as a Key-Value Store

At its heart, Git is a content-addressable filesystem. Think of it as a giant key-value database. The "value" is a piece of data, and the "key" is a unique hash of that data. This key is a 40-character checksum generated by the SHA-1 algorithm.

Every piece of content you add to Git—a file, a directory structure, a commit—is stored as an "object" in the .git/objects directory. The object's filename is its SHA-1 hash. This has a powerful side effect: if the content doesn't change, its hash doesn't change. Git only stores new data, making it incredibly efficient.

Git stores three main types of objects: blobs, trees, and commits. Each one serves a distinct purpose in building a snapshot of your project.

Blobs: The Content A blob, or "binary large object," is the simplest object type. It stores the raw contents of a file. That's it. A blob has no name, no timestamp, no metadata at all—just the data. If you change a single character in a file, Git creates an entirely new blob with a new SHA-1 hash.

Trees: The Directory Structure A tree object represents a directory. It's essentially a list of pointers. Each entry in a tree contains the file mode, the object type (blob or another tree), the object's SHA-1 hash, and the filename. This is how Git reconstructs the directory structure for any given snapshot. A tree can point to blobs (files) and other trees (subdirectories).

Commits: The Snapshots A commit object ties everything together. It contains a pointer to a single top-level tree object, which represents the project's root directory at that point in time. It also includes metadata: the author's name and email, the committer's name and email, a timestamp, and the commit message.

Crucially, a commit also contains one or more pointers to its parent commits. This chain of parent pointers forms the project's history. A standard commit has one parent, while a merge commit has two or more.

The Index as a Staging Area

When you run git add, you're not just telling Git you want to track a file. You are adding the file's current content to a special area called the staging area, or more accurately, the index . This index isn't a vague concept; it's a physical file located at .git/index.

The index is a binary file that acts as a middle ground between your working directory and your repository history. When you run git add, Git takes the content of the specified file, creates a blob object from it, and updates the index with that blob's information. The index effectively holds the tree that Git will use to create the next commit.

This is why you have to git add changes you want to commit. It's the mechanism for building up the precise snapshot (the tree object) that your next commit will point to. When you finally run git commit, Git takes the tree represented by the index, creates a commit object pointing to it, and adds that commit to your history.

References and HEAD

Remembering 40-character SHA-1 hashes is impractical. That's where references, or "refs," come in. Refs are simple files in the .git/refs directory that act as human-readable pointers to commit hashes. The most common refs are branches and tags.

A branch, like main, is just a file at .git/refs/heads/main that contains the SHA-1 hash of the latest commit on that branch. When you make a new commit, Git automatically updates this file to point to the new commit's hash.

So what is HEAD? It's the ultimate pointer. HEAD is a symbolic reference that points to the branch you currently have checked out. It's a file, located at .git/HEAD, that usually contains text like ref: refs/heads/main. This tells Git that HEAD is currently pointing to the main branch. When you switch branches with git checkout, Git simply changes the content of the HEAD file to point to the new branch.

This system of objects, the index, and references is the foundation of Git's power and flexibility. By understanding these core components, you can move beyond simply using commands and begin to truly understand what's happening under the hood.

Quiz Questions 1/6

What is the primary function of the .git/objects directory?

Quiz Questions 2/6

You've made a change to a single file and run git add myfile.txt. What does Git do at this stage?