# How git clone Really Works: A Deep Dive into Git’s Object Database

> A deep, developer-focused walkthrough of what actually happens inside git clone, including Git’s object database, commit and tree structures, negotiation protocol, packfiles, delta compression, working tree materialization, and more.

Source: https://zop.dev/resources/blogs/how-git-clone-really-works-a-deep-dive-into-git-s-object-database
Published: 2025-12-11 · Author: chandra-prakash-singh · Tags: delta-compression, devops, distributed-systems, git, git-clone, git-internals, object-database, packfiles, software-engineering, version-control

---

Most developers use git clone daily, but very few understand what truly happens under the hood. Behind that single command lies a complex process of object negotiation, delta compression, and graph reconstruction that builds a complete local copy of another repository’s content-addressed universe.

This article walks through that process step by step, how Git transforms a remote repository into a fully materialized local clone. We’ll explore the object model, packfiles, negotiation protocol, and working tree checkout, supported by clear mental models and ASCII diagrams.

## What git clone Actually Does

When you run:
git clone https://github.com/user/repo.git

Git performs the following steps:

- Negotiates with the remote to discover available references (branches, tags).
- Downloads the full object graph — all commits, trees, and blobs reachable from those references — efficiently packed and delta-compressed.
- Writes these objects into .git/objects/pack/, sets up local refs and HEAD, and then checks out a working directory from the root tree of the checked-out commit.

In essence:
clone = copy the object graph + set references + checkout the working tree

## The Git Object Model: Core Building Blocks

Git is a content-addressed database, not a traditional filesystem.
Every file, directory, commit, and tag exists as an immutable object, identified by a cryptographic hash (SHA-1 or SHA-256).
This makes Git’s data model tamper-evident, deduplicated, and verifiable.

| Type   | Purpose             | Contains                                   |
|--------|---------------------|---------------------------------------------|
| Blob   | File data           | Raw bytes and a header                      |
| Tree   | Directory snapshot  | Mode, name, and object IDs for children     |
| Commit | Snapshot metadata   | Author, message, parent commits, root tree  |
| Tag    | Annotated reference | Tag message and pointer                     |

## The Object Graph

commit C
│  tree -> T_root
│            ├── mode 100644 "README.md" -> blob B1
│            ├── mode 100755 "build.sh"  -> blob B2
│            └── mode 040000 "src"       -> tree T_src
│                                                ├── "main.go" -> blob B3
│                                                └── "util.go" -> blob B4
│
└── parent -> commit P
               │ tree -> T_prev
               └── parent -> ...

### Key ideas:

- A commit points to a tree, which represents a snapshot of the repository.
- Trees point to blobs (files) or other subtrees (directories).
- Commits form a Directed Acyclic Graph (DAG) through parent references.
- Identical content produces identical hashes, so Git automatically reuses objects.

## How git clone Communicates with the Remote

The clone operation is essentially a structured conversation between your Git client and the remote server.

### 1. Advertisement Phase

The remote server advertises:

- Its available references (e.g., refs/heads/main, refs/tags/v1.0)
- Supported capabilities (e.g., side-band, ofs-delta, multi_ack)

### 2. Negotiation Phase

The client responds with:

- Wants: commits it needs
- Haves: commits it already has (for incremental clones)

The server analyzes the commit graph to determine exactly which objects the client lacks.

### 3. Packfile Transfer Phase

The server:

- Gathers all reachable objects from the requested commits
- Delta-compresses them for efficient transfer
- Streams a single .pack file to the client

The client writes this pack into:

- .git/objects/pack/pack-XXXX.pack
- .git/objects/pack/pack-XXXX.idx

## Protocol Flow Overview

```
Client                          Server
  |          ls-refs              |
  |------------------------------>|
  |       refs + capabilities     |
  |<------------------------------|
  |            want(s)            |
  |------------------------------>|
  |           have(s)             |
  |------------------------------>|
  |        ACK/NAK + pack         |
  |<==============================|
  |     write pack + index        |
```

## Inside the .git Directory After Cloning

A freshly cloned repository has a .git directory that looks like this:

```
.git
├── HEAD                 -> "ref: refs/heads/main"
├── config               -> [remote "origin"]
├── refs
│   ├── heads/main       -> <commit id>
│   ├── remotes/origin/main -> <same commit id>
│   └── tags/
└── objects
    ├── pack/
    │   ├── pack-XYZ.pack
    │   └── pack-XYZ.idx
    └── info/
```  

### Key components:

- .git/objects/pack: Packed object store
- .git/refs/heads: Local branches
- .git/refs/remotes/origin: Remote-tracking branches
- .git/index: Staging cache
- .git/HEAD: Symbolic reference to the current branch

## How Git Checkout Creates Files

The checkout process transforms database objects into real files:

- Read HEAD → resolve branch → resolve commit
- Read the commit’s root tree
- Traverse the tree and write each blob to the working directory
- Cache path–blob mappings in the index

```
HEAD -> refs/heads/main -> commit C -> tree T_root
                                       |-> blobs -> files
Working tree <= write blobs to disk
Index <= cache metadata for performance
```  

## Clone Variants and Optimizations

| Strategy                      | Description                                      | Use Case                     |
|------------------------------|--------------------------------------------------|------------------------------|
| Shallow clone (--depth 1)    | Clones only recent commits                      | CI pipelines, fast testing   |
| Filtered clone (blob:none)   | Fetches commits/trees first, lazy-loads blobs    | Large monorepos              |
| Sparse checkout              | Materializes only specific paths                 | Partial working directories  |

These approaches let you balance speed, bandwidth, and completeness.

## Packfiles and Delta Compression

Git uses packfiles to efficiently transfer and store data.

- A packfile bundles multiple objects into a single file.
- Similar objects are delta-compressed, where one is stored as a “difference” from another.
- The .idx file provides a fast lookup index for object retrieval.

Example structure:

[PACK header]
[OBJ_A full]
[OBJ_B delta -> base OBJ_A]
[OBJ_C full]
...
[checksum]

This mechanism significantly reduces both disk usage and network transfer size.

## Data Integrity and Security

Git ensures the integrity of all data through cryptographic hashing.

- Every object’s hash covers both its header and content — change any byte, and the hash changes.
- Commits link via parent hashes, creating a verifiable chain of trust.
- Tools such as git fsck and git verify-pack detect corruption.
- Signed commits and tags add cryptographic authenticity.

Git’s security model is mathematical: integrity is guaranteed by hash linkage.

## Example: Minimal Repository Flow

An example of the minimal repository flow:

- Initial commit C0 → tree T0 → blob B1 (README)
- Next commit C1 → modifies README → blob B2
- Server packs \{C1, C0, T1, T0, B2, B1\}
- Client writes pack → sets refs → checks out C1 → files appear

**Visual summary:**

refs/heads/main -> C3 -> C2 -> C1 -> C0

Each commit points to its root tree, trees link to blobs, and references point to commits — forming a single, content-addressed DAG.

## Key Mental Models

The key mental models -

- Git is a database, not a filesystem. Every file, directory, and commit is an immutable object in a key–value store.
- Cloning = graph download + reference binding. You fetch an object graph, then assign human-readable names (branches, tags).
- The working tree = a view of one tree object. Switching branches simply changes which tree object you’re viewing.
- The index = a performance cache. It speeds up diffing and staging by tracking file stats and blob IDs.

## Closing Thoughts

git clone doesn’t just copy files. It reconstructs a graph-based database of snapshots, hashes, and relationships.
Understanding this process gives you a more predictable, transparent view of how Git actually manages your code — and why it’s so efficient at doing so.

---
