Skip to main content

Command Palette

Search for a command to run...

How Git Works Internally

So you've been using git add, git commit, git push like a good developer. But have you ever wondered what actually happens when you run these commands

Published
โ€ข6 min read
How Git Works Internally
A

i was a nobody until the covid-19 and like most of the devs from this covid-19 wave, i too started learning something to transition from that nobody to somebody/someone because i had some spare time during ๐Ÿ˜‰ & after all those online classes.

so fast-forward โฉ to 2025 i am currently a frontend developer who

  • is still learning basics of javascript
  • primarily uses CSS for styling
  • ships a couple of apps every now and then
  • uses react.js as the primary framework

impact:

  • Sep,2022 developed the first website aka current one for MuLearn Foundation
  • 2023 developed the web app for MuLearn Foundation, used by over 30,000+ students
  • 2024 - present co-founded the event management and ticketing platform makemypass.com along with few sub-products such as hoogo, premote, quizit, jusvote, leadx
  • 2025 - present working at ente.io

Where does the code GO? How does Git remember everything? What sorcery is this? Today we're going DEEP. We're opening that mysterious .git folder and understanding what the hell is inside.

The .git Folder โ€” Where All the Magic Lives

When you run git init, Git creates a hidden folder called .git in your project directory. This folder? It IS Git. Delete this folder and boom โ€” your entire Git history is gone. No more commits, no more branches, nothing. Just regular files. So what's inside this magical folder?

.git/
โ”œโ”€โ”€ HEAD
โ”œโ”€โ”€ config
โ”œโ”€โ”€ description
โ”œโ”€โ”€ hooks/
โ”œโ”€โ”€ index
โ”œโ”€โ”€ info/
โ”œโ”€โ”€ logs/
โ”œโ”€โ”€ objects/
โ”œโ”€โ”€ refs/
โ”‚   โ”œโ”€โ”€ heads/
โ”‚   โ””โ”€โ”€ tags/
โ”œโ”€โ”€ COMMIT_EDITMSG
โ”œโ”€โ”€ FETCH_HEAD
โ””โ”€โ”€ ORIG_HEAD

Looks intimidating right? Let me break it down:

  • HEAD โ€” tells Git "where am I right now?", points to current branch

  • config โ€” repo configuration, author name, email, remote URLs

  • index โ€” your staging area, when you do git add file info goes here

  • objects/ โ€” THE MOST IMPORTANT FOLDER, stores everything โ€” files, commits, trees

  • refs/ โ€” pointers to commits, branches live in refs/heads/, tags in refs/tags/

  • logs/ โ€” tracks when refs were updated, useful for git reflog

  • hooks/ โ€” scripts that run automatically on Git events

Git Objects โ€” The Building Blocks

Git is basically a content-addressable filesystem. Fancy words, simple meaning โ€” Git stores everything as objects, and each object has a unique ID (a hash). There are THREE main types of objects:

1. Blob (Binary Large Object) A blob is basically the content of a file. Just the content, not the filename, not the location โ€” just what's inside. When you add a file to Git, it creates a blob with the file's content and generates a SHA-1 hash for it. Same content = Same hash. Always.

2. Tree A tree is like a directory listing. It contains:

  • references to blobs (files)

  • references to other trees (subdirectories)

  • filenames and permissions

Think of it as Git's way of saying "in this folder, there's file A (blob xyz) and subfolder B (tree abc)."

3. Commit A commit object contains:

  • pointer to a tree (snapshot of your project)

  • author and committer information

  • commit message

  • pointer to parent commit(s)

This is the unreadable shit you see when you look at raw Git data โ€” but it's actually beautifully organized.

The Objects Folder โ€” Let's Get Our Hands Dirty

Remember the objects/ folder? Let's see what's actually inside.

.git/objects/
โ”œโ”€โ”€ 1b/
โ”œโ”€โ”€ 05/
โ”œโ”€โ”€ 5a/
โ”œโ”€โ”€ 1c/
โ”œโ”€โ”€ 8a/
โ”œโ”€โ”€ pack/
โ””โ”€โ”€ info/

See those two-letter folders? 1b, 05, 5a? Here's the trick: Git takes the first 2 characters of the hash and makes it a folder name. The rest becomes the filename. So if your commit hash is 2b9b0a8hdec89a1667..., Git stores it as objects/2b/9b0a8hdec89a1667... Why? Performance. Instead of having millions of files in one folder, Git distributes them. You can actually READ these objects:

bash

git cat-file -p 2b9b0a8hdec

And you'll see the raw content โ€” the changes, the author, the commit message, the parent commit hash. Everything.

How Git Tracks Changes โ€” The Flow

Let me walk you through what ACTUALLY happens when you use Git.

When You Do git add:

  • Git reads your file's content

  • creates a blob object with that content

  • generates a SHA-1 hash for it

  • stores the blob in .git/objects/

  • updates the index (staging area)

Your file is now "staged" โ€” but not committed yet.

When You Do git commit:

  • Git takes everything in the staging area

  • creates a tree object representing current directory structure

  • creates a commit object pointing to this tree

  • stores author, message, timestamp, parent commit hash

  • updates branch pointer in refs/heads/

And THAT'S IT. Your commit now exists as objects in the .git/objects/ folder.

How Git Uses Hashes โ€” Integrity on Steroids

Every single thing in Git is identified by a SHA-1 hash โ€” a 40-character hexadecimal string like 2b9b0a8hdec89a1667a4c5d8e9f0a1b2c3d4e5f6. Why is this genius?

  • Content-based addressing โ€” hash is generated FROM the content, same content = same hash, always

  • Integrity verification โ€” if even ONE bit changes, hash completely changes, Git detects corruption instantly

  • Deduplication โ€” same file in 10 commits? Git stores ONE blob

  • Distributed trust โ€” clone a repo and verify your copy is EXACTLY the same by comparing hashes

Branching โ€” It's Just Pointers

Here's a mind-blowing fact: branches in Git are just text files containing a commit hash. That's it. When you create a branch:

bash

git branch feature-xyz

Git just creates a file at .git/refs/heads/feature-xyz containing the current commit hash. When you switch branches with git checkout feature-xyz, Git updates the HEAD file to point to refs/heads/feature-xyz. That's why branching in Git is INSTANT. No copying files, no duplicating data. Just updating a pointer. How does Git know which branch you're on?

bash

cat .git/HEAD

Output: ref: refs/heads/main HEAD points to a branch, and that branch points to a commit. Simple.

The Dangerous HARD โ€” Reset vs Revert

Now here's where things get spicy.

git reset --hard <commit> This command makes the HEAD pointer go to the specified commit. But in the process, the commits after that are LOST. Like, if you have commits A -> B -> C -> D (HEAD) and you do git reset --hard B, commits C and D? Gone. PUFF. UN-REVERTABLE (well, technically recoverable with reflog but that's advanced shit).

git reset <commit> (without --hard) This also moves HEAD back, but the changes from those commits are kept in staging area. They're not deleted abruptly. So there's still scope to commit them again. Much safer.

git revert <commit> This is the SAFE way. Instead of deleting commits, it creates a NEW commit that undoes the changes from the specified commit. Say there's a bug in the 3rd commit, and after that you've done new feature updates. Using reset would lose those feature commits too. Using revert creates a new commit that just removes the buggy changes while keeping everything else.

Reset ka Problem: Commits after the reset point are LOST. Revert is the Good Boi: Creates a new commit without the buggy commit's changes.

Before revert:  O -- O -- BUG -- O -- O -- HEAD
After revert:   O -- O -- BUG -- O -- O -- FIX (new commit that undoes BUG)

Building Your Mental Model

Stop memorizing commands. Start understanding the model:

  • Git is a database of objects โ€” blobs, trees, commits

  • everything is identified by hashes โ€” content-addressable

  • branches are just pointers โ€” lightweight, instant

  • HEAD tells you where you are โ€” points to current branch

  • staging area (index) is your prep zone โ€” between working directory and commits

Once you understand this, commands start making sense:

  • git add -> creates blobs, updates index

  • git commit -> creates tree + commit objects, updates branch pointer

  • git checkout -> moves HEAD, updates working directory

  • git reset -> moves branch pointer (dangerous without care)

  • git revert -> creates new commit that undoes changes (safe)

Wrapping Up

The .git folder isn't magic. It's just a well-organized database of objects and pointers. Understanding this makes you a BETTER developer because you know WHY commands work the way they do, you can recover from mistakes, and you can debug Git issues instead of just deleting and re-cloning. Next time you run git commit, remember โ€” you're not just "saving". You're creating a blob, building a tree, generating a commit object, updating refs, and moving HEAD. Pretty cool when you think about it. Now go explore your .git folder. I dare you.