Stage 2 · Tools
Git Fundamentals
What is Git?
Content-addressable storage, SHA hashes, and why Git is different from other VCS tools.
Git in One Sentence
Git is a distributed version control system that tracks content as a directed acyclic graph (DAG) of immutable snapshots. Every commit is a pointer to a complete tree of files, and every tree is identified by a SHA-1 hash of its content. If even a single byte changes, the hash changes, which means integrity is built into the data model itself.
Unlike tools that store patches (delta-based systems), Git snapshots the entire working tree at each commit. It then compresses identical objects behind the scenes, so storage stays efficient without requiring deltas.
Because every object is identified by its content hash, Git can verify integrity instantly. A corrupted object will fail a hash check. This is fundamentally different from systems like SVN where revision numbers are arbitrary sequential integers.
Distributed vs Centralized
Centralized version control systems (SVN, CVS, Perforce) store the canonical repository on a single server. Developers check out files and must be connected to the server to commit. Git gives every clone the full history — commits, branches, tags, and all metadata. You can commit, branch, and diff locally without any network access.
| Feature | Centralized (SVN/CVS) | Distributed (Git) |
|---|---|---|
| History storage | Server only | Every clone has full history |
| Commit offline | No | Yes |
| Branching speed | Slow (server-side copy) | Instant (pointer swap) |
| Merge capability | Server performs merge | Client-side merge or rebase |
| Single point of failure | Yes — server goes down = no work | No — every clone is a backup |
This distributed architecture means every developer's machine is a full backup of the repository. If the server dies, any clone can restore the entire history.
Content-Addressable Storage
Git stores every piece of data — file content, directory structure, commit metadata — as a named object in .git/objects. The name is the SHA-1 hash of the object's content. This is content-addressable storage: the address (hash) is derived from the content itself.
mkdir my-project && cd my-project
git init
ls .git/objectsAfter git init, the objects directory contains only info/ and pack/ subdirectories. As soon as you add files, Git creates objects here — one per blob, tree, and commit.
echo "Hello, Git" > greeting.txt
git add greeting.txt
git cat-file -t $(git hash-object greeting.txt)git hash-object computes the SHA-1 of a file's content and stores it as a blob. git cat-file -t prints the object type. You will see blob — Git's term for raw file content.
Git historically uses SHA-1 (160-bit), but SHA-1 is cryptographically weak. Git 2.29+ supports SHA-256 as the hash algorithm. In practice, SHA-1's collision resistance is sufficient for content addressing — no one is crafting malicious commits in a normal workflow — but SHA-256 is the forward-looking choice.
The Three States
Every file in a Git repository exists in one of three states. Understanding these states is the foundation for every Git command you will ever run.
| State | Location | Description |
|---|---|---|
| Working Tree | Your filesystem | The files you see and edit directly |
| Staging Area (Index) | .git/index | A prepared snapshot of changes, ready for the next commit |
| Repository | .git/objects | Committed snapshots — the permanent history |
You edit files in the working tree. When a change is ready, you git add it to the staging area (also called the index). When you git commit, the staging area becomes a new repository commit. This three-step workflow — edit, stage, commit — gives you precise control over what goes into each commit.
echo "version 1" > README.md
git status # README.md is untracked (working tree only)
git add README.md
git status # README.md is staged (in the index)
git commit -m "initial commit"
git status # working tree is clean (nothing to commit)Each git status shows which state your files are in. Untracked → Staged → Committed. The staging area is the middle step that gives you control.
What Git Ignores
Not everything belongs in version control. Build artifacts, dependencies, OS files, and secrets should stay out of the repository. Git uses .gitignore to specify patterns for files and directories it should never track.
# Dependencies
node_modules/
vendor/
# Build output
dist/
build/
*.o
*.exe
# OS files
.DS_Store
Thumbs.db
# Secrets
.env
*.pemPatterns use glob syntax. A trailing / matches directories. A leading ! negates a pattern (e.g., !vendor/important.txt to force-track a file inside an ignored directory).
Once a file is tracked by Git, adding it to .gitignore does not untrack it. You need git rm --cached <file> to stop tracking. Create .gitignore in your first commit and keep it updated.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.