Core Concepts
Almost everything in git, no matter how advanced, is built on three commands you'll use constantly: git init, git add, and git commit. This chapter is entirely about understanding what each one actually does — not just memorising the syntax, but understanding the three-stage model underneath them, because that model is what makes the rest of git make sense.
The Three Stages
Every file in a git project exists in one of three places at any given moment. Understanding this is the single most important concept in the entire series — branching, merging, and almost every git command is really just moving files between these three areas.
Starting a New Project — git init
git init turns an ordinary folder into a git repository. It creates a hidden .git folder inside it — that hidden folder is the entire repository: every commit, every branch, the full history. Delete .git and you've deleted the repository (the files in your working directory remain, but all history is gone — this is exactly the situation we ran into during the website→debserver reorg, where a `.git` folder went missing and broke a nested repository link).
$ cd my-project
$ git init
Initialized empty Git repository in /home/you/my-project/.git/
git init inside a folder that's already inside a git repository creates a nested repository — git will treat the inner folder strangely, often showing it as a single unexplained "modified" entry rather than its actual file changes. If you only ever run git init once per project, at the top level, this never comes up.
Checking Status — your most-used command
git status tells you, at any moment, which files are in the working directory only, which are staged, and which haven't changed since the last commit. You will run this command more than any other — get comfortable reading its output.
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.html
style.css
"Untracked" means git has noticed these files exist but isn't watching them for changes yet — they haven't been staged or committed.
Staging Changes — git add
git add moves a file's current state from the working directory into the staging area. It's a snapshot of that file right now — if you edit it again after staging, you need to run git add again to update what's staged.
$ git add index.html
$ # Stage everything that's changed
$ git add .
$ git status
Changes to be committed:
new file: index.html
new file: style.css
git add .git add . stages every changed file in the current directory and below — convenient, but it can accidentally stage files you didn't mean to commit (temporary files, local config, accidentally-saved secrets). git add <specific-file> or reviewing with git status first is the safer habit, especially on a shared project. Chapter 6 covers .gitignore, which prevents this class of mistake entirely for files that should never be tracked.
Recording a Snapshot — git commit
git commit takes everything currently in the staging area and saves it permanently as a new point in the project's history, along with a message describing what changed and why.
[master (root-commit) a1b2c3d] Add initial homepage and stylesheet
2 files changed, 48 insertions(+)
create mode 100644 index.html
create mode 100644 style.css
That a1b2c3d is the commit's unique ID (a SHA-1 hash) — every commit gets one, and it's how git refers to that exact snapshot anywhere else in the system (covered more in Chapter 8 when undoing commits, and Chapter 3 when viewing history).
Writing a good commit message
- Summarise what changed, in the imperative mood: "Add login form" not "Added login form" or "Adding login form" — this matches git's own generated messages (merge commits, reverts) and reads cleanly in history.
- Keep the first line under ~50 characters where practical — many tools (including GitHub's interface) truncate longer summaries.
- One logical change per commit. "Fix login bug and update homepage copy" should usually be two commits, not one — it keeps history searchable and makes problems easier to isolate later.
- For more detail, omit
-mentirely — running plaingit commitopens your configured editor, where you can write a short summary line, a blank line, then a longer explanation.
Command Reference So Far
| Command | What it does |
|---|---|
| git init | Turns the current folder into a new git repository |
| git status | Shows what's changed, staged, or untracked right now |
| git add <file> | Moves a file's current state into the staging area |
| git add . | Stages all changed files in the current directory and below |
| git commit -m "msg" | Permanently records everything staged as a new snapshot |
git init, you'll see "No commits yet" in git status — that's expected, not an error. The repository exists and is tracking the folder; it simply has no history yet until your first commit.
Chapter 2 Quick Reference
- Three stages: Working Directory → Staging Area → Repository (History)
- git init — creates the hidden .git folder; run once, at the project's top level
- git status — your most-used command; shows untracked, staged, and unstaged changes
- git add <file> — stage a specific file; git add . — stage everything (use deliberately)
- git commit -m "message" — permanently records the staged snapshot
- Commit messages: imperative mood, under ~50 chars first line, one logical change per commit
- Next chapter: viewing your history — log, diff, status, and show in depth