Understanding the .git Directory Structure and Its Components
The hidden .git folder stores all repository data—including configuration, branch references, commit objects, logs, the staging index, and executable hooks—organized into subdirectories such as config, objects, refs, logs, info, hooks, and index, enabling Git to track history, manage branches, and automate workflows.
Every Git repository contains a hidden .git directory that stores the repository's internal data such as branches, commits, configuration, and logs.
The directory layout is relatively simple but powerful. Below is the full structure of a typical .git folder:
.git
|----config
|----objects
| |---0d
| | |---0d218acc58d857329cde3778d7429037079627
| | |---60436b1116e54b3ed9a4b9fec1f2f9916a73ca
| |---59
| | |----a10af7aa35f521b9a41569785d4481850192e3
| |---92
| | |---5f4810ed4da9873771f14f2ca1ab97db81283a
| | |---6c85f1ad90849159b2c616a9744ba62abe8f6a
| | |----c359f0b8d09e2fc137c865043d4f6951989cdd
|----HEAD
|----info
| |----exclude
|----logs
| |----HEAD
| |----refs
| |----heads
| | |----main
| |----remotes
| |----origin
| |----main
|----description
|----hooks
| |----commit-msg.sample
| |----pre-rebase.sample
| |----pre-commit.sample
| |----applypatch-msg.sample
| |----fsmonitor-watchman.sample
| |----pre-receive.sample
| |----prepare-commit-msg.sample
| |----post-update.sample
| |----pre-merge-commit.sample
| |----pre-applypatch.sample
| |----pre-push.sample
| |----update.sample
| |----push-to-checkout.sample
|----refs
| |----heads
| | |----main
| |----tags
| |----remotes
| |----origin
| |----main
|----index
|----COMMIT_EDITMSGHEAD (Current Branch)
The HEAD file records the name of the branch currently checked out. Its content looks like: ref: refs/heads/main or for another branch: ref: refs/heads/dev refs
Under .git/refs there are three sub‑directories— heads, tags, and remotes —that store references to the latest commit IDs for local branches, tags, and remote branches respectively.
|----refs
| |----heads
| | |----main
| |----tags
| |----remotes
| |----origin
| |----main.git/refs/heads
Each local branch has a file like .git/refs/heads/main containing the SHA‑1 of the latest commit on that branch, e.g.: 2ddc65b74a186f4332d7b218be0f18dd404c82ef.git/refs/remotes
This directory mirrors the state of remote branches, allowing Git to track changes on the remote repository.
.git/refs/tags
When you create a tag, a file is added here to point to the commit the tag references.
.git/refs/stash
If you use git stash, the stash information is stored in this directory.
Typical use cases for git stash include temporarily switching branches without committing unfinished work, or saving local changes while pulling upstream updates.
Commit Objects (.git/objects)
References in refs ultimately point to files in .git/objects. A commit object is stored as a two‑level path where the first two hex digits form a directory and the remaining characters form the filename, e.g.: .git/objects/2d/dc65b74a186f4332d7b218be0f18dd404c82ef You can inspect a commit with: git cat-file -p 2ddc65b74a186f4332d7b218be0f18dd404c82ef This displays the commit tree, author, committer, and message.
Similarly, you can view the tree object: git cat-file -p f8803d7d049edbbc981da732b855419d039f79ff and any blob (file) object with the same command.
Logs (.git/logs)
The .git/logs directory records every update to refs, including the previous and new SHA‑1, author, timestamp, and commit message.
|----logs
| |----HEAD
| |----refs
| |----heads
| |----main
| |----remotes
| |----origin
| |----mainconfig
The repository‑specific configuration resides in .git/config. It defines core settings, remote URLs, and branch merge information.
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/xxxx/xxxx-blog.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/mainindex (Staging Area)
The .git/index file stores the snapshot of files that have been staged with git add. When git commit runs, the index content becomes a new commit.
hooks
Git hooks are executable scripts located in .git/hooks that run at specific points in the workflow, such as pre-commit, post-commit, or pre-push, allowing custom automation.
Understanding these internal components helps developers troubleshoot, customize workflows, and gain deeper insight into how Git manages version history.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
