Skip to main content

Command Palette

Search for a command to run...

Inside Git: How It Works and the Role of the .git Folder

A deep dive into Git's content-addressable storage, hashing, and what actually happens inside the .git directory.

Published
8 min readView as Markdown
Inside Git: How It Works and the Role of the .git Folder

How Git Works Internally

Let’s start with a simple question : what actually happens when you save your code in Git ?

Most people think Git stores the changes you make to files - like "I added 5 lines to index.js" or "I deleted a function from app.js". But here's the interesting part: Git doesn't think in terms of changes. It thinks in terms of snapshots.

Imagine you are taking photographs of your project. Every time you make a commit, Git takes a complete picture of what all your files look like at that exact moment. It's like pressing pause and capturing the entire state of your project. That's your snapshot.

Now, you might be thinking - "Wait, if Git saves the entire project every time, won't that take up tons of space?" Smart question! Git is clever about this. If a file hasn't changed between commits, Git doesn't store it again. Instead, it just creates a reference pointing back to the previous version. Think of it like saying "Hey, index.js is still the same as last time, so just look at the old copy."

Here's another cool thing: Git is basically a content-addressable storage system. Okay, that sounds fancy, but it just means Git stores everything based on its content. When you save a file, Git looks at what's inside it, creates a unique fingerprint (called a hash), and stores it using that fingerprint as the name. If you save the exact same content later, Git recognizes the fingerprint and says "I already have this!" - so it doesn't waste space storing duplicates.

This snapshot approach is what makes Git so powerful. It's why you can jump back to any point in your project's history instantly. That’s why branching is so fast and easy. And that’s why Git is nearly impossible to corrupt - every single piece of data is checksummed and verified.

So when you run commands like git add or git commit, you're not just saving files. You're creating a timestamped snapshot of your entire project, storing it efficiently and building a timeline you can travel through whenever you need.

Pretty cool, right? Now let's dive deeper into where all of this actually happens - inside that mysterious .git folder.


Understanding the .git Folder

Alright, Let’s talk about the .git folder - the place where all the Git magic actually happens.

When you run git init in your project, Git creates a hidden folder called .git. You might not see it in your file explorer unless you've enabled "show hidden files" - but trust me, it's there, quietly doing all the heavy lifting.

Think of the .git folder as Git's personal workspace. While you are busy writing code in your Project files, Git is working behind the scenes in this folder, keeping track of everything. All your commits, all your branches, all your history - it all lives here. If you delete the .git folder, Your entire Git history disappears. Your files stay, but Git forgets everything about them.

Let's take a tour of what's inside this folder. Don't worry, you don't need to memorize this - just understand what each part does:

The Key Components

🗃️Objects/ - The Storage Room

This is where Git stores all your actual data. Remember those snapshots we talked about, They all live here. Every file you have ever committed, every version of every file, every commit you have ever made - it's all compressed and stored in this folder.

Git does not store them with normal filenames like "index.js" or "style.css". Instead, it uses those unique hash fingerprints we mentioned earlier. So you will see weird folder names like 3a/ and b2/, containing files with names like f5c9e8a1b3d4.... This looks cryptic, but it's just Git's way of organizing things efficiently.

🫙Refs/ - The Bookmarks

This folder contains pointers to commits - basically bookmarks in your project's history. Inside refs/, you'll find:

  • heads/ - This is where your local branches live. Each file in here represents a branch (like main, feature/login, etc.). The file just contains the hash of the commit that branch is pointing to.

  • remotes/ - References to branches on remote repositories (like GitHub)

  • tags/ - If you have created any tags (version makers like v1.0, v2.0)

📌HEAD/ - The Marker

The HEAD file is super important. It's a simple file that tells Git "this is where you currently are." Usually, it points to a branch (like ref: refs/heads/main), which means you're on the main branch. When you switch branches, Git just updates this file. That's it!

🗒️Other Files

  • description - Used by some Git hosting services

  • info/ - Additional repository information

  • logs/ - Keeps a log of where your branches have been

Here’s the Beautiful Part

All of this complexity is hidden from you. You never have to manually edit these files or dig through the objects/ folder. Git handles everything automatically when you use simple commands like git add, git commit and git push.

But understanding what's happening in here helps you build a mental model. When you run git commit, you're not just saving files - you're creating objects in the objects/ folder, updating the HEAD file, moving branch pointers in refs/, and clearing the index.

One Important Warning: Never manually delete or modify files inside .git/ unless you really know what you're doing. This folder is Git's source of truth. Mess with it, and you could corrupt your entire repository history.

Think of the .git folder like the engine of a car. You don't need to understand every piston and valve to drive, but knowing the basics helps you appreciate what's happening when you press the gas pedal - or in our case, when you press git commit.

Now that we know where Git stores everything, let's understand what exactly it's storing. Time to meet Git's three main types of objects: blobs, trees, and commits.


Git Objects: Blob, Tree, Commit

Git stores everything using three types of objects. Think of them as building blocks. Lets’ understand each one:

Blobs - Your File Content

A blob is just the content of your file. That’s all.

When you create index.js with some code in it, Git takes that code, compresses it, and stores it as a blob. The blob doesn't know the filename or where it lives - it's just pure content.

Here's something cool: if two files have the exact same content, Git stores only one blob for both. Same content = same blob. This is how Git saves space.

Trees - Your Folder Structure

A tree is like a folder. It organizes your files.

A tree keeps tracks of :

  • File names

  • Which blob contains each file’s content

  • Subfolders (which is also trees)

So if your project looks like this :

masterji
|
|---- index.ts
|---- navbar.ts
|---- public
      |---- logo.png

Git creates :

  • One blob for each file’s content

  • One tree for the images/ folder

  • One root tree for my-project/ that points to everything

🧠 Note : Trees know the structure. Blobs know the content.

Commits - The Complete Snapshot

A commit ties everything together. It’s like taking a photo of your entire project.

Every commit contains:

  • A pointer to the root tree (your project at that time)

  • Your name and email

  • The date and time

  • Your commit message

  • A pointer to the previous commit (parent)

When you run git commit -m "Add masterji homepage", Git creates a commit object that captures the entire state of your project at that moment.

The parent pointer is important - it creates a chain. Each commit points back to the one before it, forming your project's timeline.


How Git Tracks Changes

Let’s uncover what really happens when you run git add and git commit.

The Power of Hashing

Git's secret weapon is hashing. Every piece of content gets run through a formula (SHA-1) that creates a unique 40-character fingerprint.

For example, if your file contains console.log("hello"), Git creates a hash like:

a3f5c2b9e8d1f6a7c4b2e9f1d3a8c5b7e2f9a4c1

The magic:

  • Same content = same hash

  • Change one character = completely different hash

  • Impossible to fake or duplicate

This is how Git ensures your data stays safe and detects when file change.

What Happens During git add

You created index.ts and run git add index.ts. Here what Git does:

  1. Reads your file content

  2. Calculates the SHA-1 hash

  3. Compresses the content

  4. Stores it as blob in .git/objects/

  5. Updates the staging area to say “index.ts is ready, content in blob a3f5c…”

Your file is now staged, waiting to be commited. The content is already safely stored in Git’s database.

What Happens During git commit

Now you run git commit -m “add index.ts file”. Git takes these steps:

  1. Looks at what's in the staging area

  2. Creates tree objects representing your folder structure

  3. Creates a commit object containing:

    1. Pointer to the root tree

    2. Your name, email and timestamp

    3. Your commit message

    4. Pointer to the parent commit

  4. Calculates a hash for this commit

  5. Updates your branch to point to this new commit

  6. Moves HEAD to this commit

  7. Clear the staging area

Done ! You have now captured a snapshot of your project.

How Git Detects Changes

When you run git status , Git :

  • Calculates the hash of each current file

  • Compares to hashes in the staging area and last commit

  • Different hash = file changed

No tracking every edit. Just comparing fingerprints. Fast and efficient.

Why This Matters

Understanding this shows you:

  • Git only stores new content when files actually change

  • Every piece of data is checksummed for safety

  • Hashing makes comparisons lightning fast

  • Nothing is ever lost

When you git add, you create blobs. When you git commit, you create trees and commits. These objects link together through hashes, forming your complete project history.

Git isn't magic - it's just snapshots, hashes, and smart pointers working together!