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

When we use Git, we usually run commands like git add and git commit without thinking what is going on behind the scenes. In this article, I will tell you what is going behind the scene when we use git commands so that after reading this blog you can confidently use git without the fear of what is actually happening internally.
How Git Works Internally
When we run git init command, Git creates a hidden .git folder which is used to track the changes in a Project. Git does not track the file based on their name or permissions you gave to the file. Git only tracks the content of the file.
Git stores the content using SHA-1 hash value. Every time we change our code, Git generates a new hash and compares it with the previous hash. If the hash is not the same, Git understands the file content is changed.
When we run git commit, Git does not store all files again. It only creates new hash values for the files whose content has changed. Files that have not changed keep their old hash values, so Git simply reuses them instead of creating duplicates.
In this way, Git efficiently tracks changes and prevents duplicate storage of unchanged files.
Understanding the .git Folder
.git/
├── HEAD
├── config
├── description
├── index
├── hooks/
├── info/
├── objects/
│ ├── 3a/
│ │ └── f9c2e1...
│ ├── ab/
│ │ └── cd1234...
├── refs/
│ ├── heads/
│ │ └── main
│ └── tags/
└── logs
This is the internal folder structure. Let’s look at each part one by one.
HEAD
It tells Git which branch you are working on. It is like a pointer pointing to the current branch.
config
Stores the configuration of the project made by the developer. Overrides default Git settings.
description
Stores the description of the repository in plain text. Does not affect tracking history.
index
Keeps track of files added to the staging area but not committed yet. Acts as a waiting area before commit.
hooks
Predefined scripts that run automatically. Example: checking code before commit.
info
Used to ignore files only on your local computer. Git will not track changes for these files. Useful for temporary files or local configs that should not be shared.
objects
Stores the actual data like file content, folder structure, and commits using hash numbers.
refs
Stores names of branches and tags. Each name points to a commit hash (latest commit on that branch or tag).
Inside refs/ there are two main folders:
heads/ → Stores branch names (like
main,feature1). Each branch points to its latest commit hash.tags/ → Stores tag names (like
v1.0,v2.0). Each tag points to a specific commit hash.
logs
Keeps a record of all changes made to branches and HEAD. Acts like Git’s diary tracking movements of branch pointers and commits.
Git Objects
Git does not just store files as they are. It converts everything into objects that it can track efficiently.
There are 3 main types of Git objects:
Blob (Binary Large Object)
Stores the content of a file in SHA-1 hash. Does not store the filename, only content. Git uses the hash to identify each blob.
Example: file index.html → Git stores content as blob with unique hash.
Tree
A tree is like a folder in your project. Keeps track of everything inside:
File name
File permissions
Which blob belongs there
Links to subfolders (other trees)
It does not store the content of the files, only the structure.
Commit
A snapshot of your project at a point in time.
Points to a tree object (the state of folders and files)
Contains metadata: author, commit message, timestamp, parent commit(s)
Example: git commit -m "Add homepage" → Git creates a commit object pointing to current tree.
What Happens Internally During git add and git commit
git add- Staging AreaWhen you run:
git add index.htmlInternally:
Git calculates the SHA-1 hash of the file content.
Git creates a blob object in
.git/objects/for the file content.The index (staging area) is updated to include this blob and the file path.
git commit- Saving a SnapshotWhen you run:
git commit -m "Add homepage"Internally:
Git looks at the index (staging area).
Creates a tree object representing the folder structure.
- The tree links to blobs for the staged files.
Creates a commit object:
Points to the tree object
Contains metadata: author, timestamp, commit message, parent commit
Updates the branch pointer to this new commit.
How Git Uses Hashes to Ensure Integrity
Git uses hash (a long string like f9c2e1...) to identify everything it stores like
file → BLOB
folder → Tree
commits → snapshot
A hash is unique to the content. Even one character change in the file changes the hash value.
Example:
If in index.html file has content and it SHA - 1 hash value is something f9c2e1….
<h1>Hello</h1>
If you change it to <h1>Hello World</h1>, hash becomes completely different: 7b8d9a2...
How Hash Ensure Integrity
Git never modify the existing object. when git read a object it recompute the hash value to make sure the content has not changed. if the content does not change the git use the same hash value and reuse the existing object.
That is why Git is safe and reliable as it know immediately if any file or commit is altered.
Mental Model: Git as a Content-Addressable File System
Think Git as a library in which every book (file) has a unique barcode (hash value) based on its content. Even if the book move to another shelf the barcode remains same.
If the content change in file, then git generate a new barcode (hash value) and so that library know which version is correct of that book (file).
You don’t have to memorize commands. Just understand:
Git tracks content, not filenames.
Every object is identified by its hash.
Commits are snapshots linking trees → blobs → content.