Lesson 96 of 12120 min read

The .git Directory: What Each File and Folder Does

Take a complete, guided tour of the .git folder's actual contents, revisiting and deepening what was briefly introduced back in Module 1.

Author: CodersNexus

The .git Directory: What Each File and Folder Does

Module 1's `git init` lesson gave a brief first look inside the `.git` folder — HEAD, objects, refs, config. Now that you've used Git extensively across seven modules, this lesson returns to that same folder for a complete, deeper tour, explaining exactly what every major file and directory actually contains and does, building the mental foundation for the rest of this module on Git's internal object model.

Learning Objectives

  • Identify every major file and folder inside .git and its specific purpose.
  • Explain what HEAD, refs, and objects each represent in relation to each other.
  • Understand the difference between the index file and the working directory.
  • Recognize which parts of .git are safe to inspect versus never safe to edit manually.

Key Terms to Know Before Touring the .git Directory

  • .git directory: The hidden folder, created by git init, containing everything Git needs to track a repository's history, configuration, and current state.
  • objects/: The directory storing every piece of content ever committed — files, trees, and commits — as compressed, hash-identified objects (the focus of the next lesson).
  • refs/: The directory storing pointers to commits, organized into heads/ (branches) and tags/ (tags).
  • index: A binary file representing the current state of the staging area, tracking exactly what's staged for the next commit.
  • HEAD: A file pointing to whatever branch or commit is currently checked out.

How the .git Directory Is Actually Structured

Running `ls -la .git` on any repository reveals a consistent set of files and folders, each with a specific, well-defined role:

**`HEAD`** — A plain text file containing a reference to your current position, typically `ref: refs/heads/main`, pointing at a branch (which in turn points at a commit), exactly as covered in Module 3's branch/HEAD lesson. In a detached HEAD state, this file instead contains a raw commit hash directly.

**`objects/`** — The heart of Git's actual data storage. Every file's content, every directory snapshot, and every commit ever made is stored here as a compressed object, named by its SHA hash. This directory is the subject of the next lesson's deep dive into Git's object model.

**`refs/`** — Contains pointers to commits, organized into two key subdirectories: `refs/heads/` (one file per local branch, each containing that branch's current commit hash) and `refs/tags/` (one file per tag, similarly). This is literally where branches and tags 'live' as actual files.

**`index`** — A single binary file representing the current state of the **staging area** (Module 1's three-states model). When you run `git add`, Git updates this file to reflect exactly what's staged, ready for the next commit. It's not human-readable directly, but tools like `git status` and `git diff --staged` read from it to report what's currently staged.

**`config`** — The repository's **local-level** configuration file (Module 1's `git config` lesson), storing settings specific to this one repository, such as `core.editor` overrides or `user.email` if set locally rather than globally.

**`hooks/`** — A directory containing sample and (once configured) active hook scripts — small programs Git runs automatically at specific points in its workflow, such as before a commit is finalized. This is the subject of several upcoming lessons in this module.

**`logs/`** — Contains the actual data behind `git reflog` (Module 7), recording every movement of HEAD and branch references over time.

**`COMMIT_EDITMSG`** — A temporary file holding the most recently used (or currently being composed) commit message, useful for recovering a message if a commit is interrupted.

**`description`** — A largely legacy file, mostly relevant to certain older Git web interfaces (like the classic GitWeb), rarely touched in modern workflows.

A critical, repeatedly worth-emphasizing point: while it's genuinely educational to *look inside* `.git` (as this lesson encourages), you should almost never **manually edit** its contents directly — nearly everything in this folder should only ever be modified through Git's own commands, since manual edits can easily corrupt a repository's internal consistency. Reading and exploring is safe and instructive; editing is not, with the arguable exception of the `config` and `hooks/` files, which are specifically designed to be human-edited (and which upcoming lessons cover in depth).

.git Directory Structure: Visual Walkthrough

Draw a file tree rooted at '.git/' with labeled branches: 'HEAD (file) → points to current branch/commit', 'config (file) → local repository settings', 'index (file) → current staging area state', 'COMMIT_EDITMSG (file) → most recent commit message', 'objects/ (folder) → ALL committed content, hash-addressed', 'refs/heads/ (folder) → one file per local branch', 'refs/tags/ (folder) → one file per tag', 'hooks/ (folder) → automation scripts', 'logs/ (folder) → reflog data'. Add a warning banner across the bottom: 'SAFE to explore/read. NEVER manually edit — always use Git commands instead (except config and hooks, designed to be edited directly).'

.git Directory Contents: Quick Reference Table

.git ItemTypePurpose
HEADFilePoints to the currently checked-out branch or commit
objects/DirectoryStores all committed content as hash-addressed, compressed objects
refs/heads/, refs/tags/DirectoryOne file per branch/tag, each containing a commit hash
indexFileBinary representation of the current staging area
configFileLocal (repository-specific) configuration settings
hooks/DirectoryAutomation scripts run at specific points in Git's workflow
logs/DirectoryUnderlying data for git reflog

Exploring .git: Command Syntax and Examples

# Explore the .git directory structure (safe, read-only)
ls -la .git

# Read HEAD directly
cat .git/HEAD
# ref: refs/heads/main

# Read a specific branch's reference file directly
cat .git/refs/heads/main
# a1b2c3d4e5f6...  (the commit hash 'main' currently points to)

# Confirm this matches what git rev-parse reports
git rev-parse refs/heads/main

# List the objects directory (hash-named subdirectories, covered next lesson)
ls .git/objects

# View the local repository config
cat .git/config

Breaking Down the .git Directory Example

Each command directly reads a piece of `.git`'s actual internal state, confirming the conceptual explanations above with real, concrete output. `cat .git/HEAD` reveals the raw text pointing at `refs/heads/main`. `cat .git/refs/heads/main` shows that a branch really is just a file containing a single commit hash, as first established in Module 3. `git rev-parse refs/heads/main` provides the same information through Git's own command-line interface, confirming these direct file reads are accurate. `ls .git/objects` previews the object storage explored in depth in the very next lesson.

How Understanding .git Internals Helps in Real Engineering Work

  • Debugging genuinely confusing Git problems — a repository behaving unexpectedly, or recovering from a botched operation — often benefits from directly inspecting .git's actual contents rather than relying purely on higher-level command output.
  • Understanding .git's file-based structure demystifies GUI Git tools (like GitKraken or the VS Code Git panel), which are ultimately just visual interfaces reading and writing to these exact same underlying files.
  • Interview questions probing for genuine Git depth (beyond just knowing commands) frequently ask candidates to explain what's inside .git, since this reveals whether someone understands Git's actual mechanics or just its command-line surface.
  • Advanced tooling and scripts that integrate with Git sometimes read .git's internal files directly for performance or specific low-level needs, rather than shelling out to the git command for every single operation.

.git Directory Interview Questions and Answers

Q1. What does the HEAD file inside .git contain, and what does it typically point to?

HEAD is a plain text file containing a reference to your current position in the repository. Typically, this is a reference to a branch, such as 'ref: refs/heads/main', which in turn points to a commit. In a detached HEAD state, it instead contains a raw commit hash directly.

Q2. What is the difference between the objects/ directory and the refs/ directory inside .git?

The objects/ directory stores the actual content of everything ever committed — files, directory snapshots, and commits — as compressed, hash-addressed objects. The refs/ directory stores pointers (references) to specific commits, organized into refs/heads/ for branches and refs/tags/ for tags, essentially acting as human-readable labels for specific object hashes.

Q3. Why is it generally unsafe to manually edit files inside .git?

Nearly everything in .git is meant to be modified only through Git's own commands, which carefully maintain the internal consistency of the repository's data. Manual edits can easily corrupt this consistency, potentially causing hard-to-diagnose problems, with config and hooks being the notable exceptions specifically designed for direct, manual editing.

.git Directory Quiz: Test Your Understanding

1. What does the HEAD file inside .git typically contain?

  1. A copy of the entire project's source code
  2. A reference pointing to the currently checked-out branch or commit
  3. A list of all repository collaborators
  4. The repository's remote URL

Answer: B. A reference pointing to the currently checked-out branch or commit

Explanation: HEAD is a simple text file that stores a reference to your current position — typically a branch reference, which itself points to a commit.

2. What is stored in the .git/refs/heads/ directory?

  1. One file per local branch, each containing that branch's current commit hash
  2. The full commit history of the repository
  3. A list of all files ever committed
  4. The repository's configuration settings

Answer: A. One file per local branch, each containing that branch's current commit hash

Explanation: Each local branch is represented by its own file inside refs/heads/, and that file's content is simply the commit hash the branch currently points to.

3. Which files inside .git are specifically designed to be edited directly by a user?

  1. objects and refs
  2. config and hooks
  3. HEAD and index
  4. logs and COMMIT_EDITMSG

Answer: B. config and hooks

Explanation: Unlike most of .git's internal files, which should only be modified through Git commands, config (settings) and hooks (automation scripts) are specifically intended for direct, manual editing.

Common Misunderstandings About the .git Directory

  • Manually editing files inside objects/ or refs/ directly, risking corruption of the repository's internal consistency.
  • Assuming the .git folder is just Git's internal bookkeeping with no practical relevance, missing valuable debugging and learning opportunities.
  • Confusing the index (staging area representation) with the actual working directory content, when they represent genuinely different states.
  • Not realizing config and hooks are the two intentional exceptions to the general 'never edit .git manually' guidance.

The .git Directory: Exam-Ready Quick Notes

  • HEAD: points to current branch/commit. refs/heads/, refs/tags/: one file per branch/tag, containing a commit hash.
  • objects/: all committed content, hash-addressed (next lesson's focus).
  • index: binary representation of the current staging area.
  • config: local repository settings. hooks/: automation scripts. Both are safe/intended for direct editing.

The .git Directory: Key Takeaways

  • Every major Git concept covered in this course — branches, staging, HEAD, history — corresponds to an actual, inspectable file inside .git.
  • Understanding .git's real structure demystifies what every higher-level Git command and GUI tool is actually doing underneath.
  • While exploring .git is safe and educational, manually editing its contents (outside of config and hooks) risks corrupting the repository.

Frequently Asked Questions About the .git Directory

Q1. What is inside the .git folder?

It contains everything Git needs to manage a repository: HEAD (your current position), objects/ (all committed content), refs/ (branch and tag pointers), the index (current staging area state), config (repository settings), hooks/ (automation scripts), and logs/ (reflog data).

Q2. What is the difference between HEAD and refs/heads/main?

refs/heads/main is a file containing the commit hash that the main branch currently points to. HEAD is a separate file that typically points at a branch reference like refs/heads/main (rather than directly at a commit), indicating which branch you currently have checked out.

Q3. Is it safe to look inside the .git folder?

Yes, reading and exploring .git's contents is completely safe and can be genuinely educational for understanding what Git is actually doing. What you should avoid is manually editing most of its files, since this can corrupt the repository's internal consistency.

Q4. What is the index file inside .git?

It's a binary file representing the current state of the staging area — exactly what's been staged with git add and is ready to be included in the next commit, distinct from both the working directory and the actual committed history.

Q5. Which parts of .git am I actually supposed to edit directly?

The config file (for repository settings) and the hooks/ directory (for automation scripts) are the two intentional exceptions, specifically designed for direct, manual editing — nearly everything else should only be modified through Git's own commands.

Summary

The `.git` directory contains everything Git needs to track a repository, with each file and folder serving a specific, well-defined role: `HEAD` points to the current branch or commit; `objects/` stores all committed content as hash-addressed objects (the focus of the next lesson); `refs/heads/` and `refs/tags/` store one file per branch and tag, each containing a commit hash; `index` represents the current staging area's state; `config` holds local repository settings; `hooks/` contains automation scripts; and `logs/` powers `git reflog`. While exploring and reading these files directly is safe and genuinely instructive — revealing exactly what higher-level Git commands and every branch, commit, and staging operation actually corresponds to underneath — manually editing most of `.git`'s contents should be avoided, since Git's own commands carefully maintain internal consistency that manual edits can easily corrupt. `config` and `hooks/` are the two notable, intentional exceptions designed for direct editing.

Frequently Asked Questions

It contains everything Git needs to manage a repository: HEAD (your current position), objects/ (all committed content), refs/ (branch and tag pointers), the index (current staging area state), config (repository settings), hooks/ (automation scripts), and logs/ (reflog data).

refs/heads/main is a file containing the commit hash that the main branch currently points to. HEAD is a separate file that typically points at a branch reference like refs/heads/main (rather than directly at a commit), indicating which branch you currently have checked out.

Yes, reading and exploring .git's contents is completely safe and can be genuinely educational for understanding what Git is actually doing. What you should avoid is manually editing most of its files, since this can corrupt the repository's internal consistency.

It's a binary file representing the current state of the staging area — exactly what's been staged with git add and is ready to be included in the next commit, distinct from both the working directory and the actual committed history.

The config file (for repository settings) and the hooks/ directory (for automation scripts) are the two intentional exceptions, specifically designed for direct, manual editing — nearly everything else should only be modified through Git's own commands.