Track Changes with git add and commit
Learn to track changes in Git using git add and commit. This lesson covers the core concepts, step-by-step walkthrough, and troubleshooting for effectively staging and saving your work.
Focus: track changes with git add and commit
You've just written a brilliant piece of code, saved the file, and closed your editor with a satisfied sigh. But somewhere in the back of your mind, a nagging question haunts you: "What changed?" If that code breaks an hour later, can you look back and see exactly what you did? Without a system to track changes, you're flying blind — every edit becomes a gamble. Git's add and commit commands are your safety net, the first two steps toward a complete, auditable history of your project. In this lesson, you'll stop hoping you remember and start knowing what changed, when, and why.
The problem this lesson solves
You've probably been in this situation: you tweak a config file, adjust a function, delete a debug line — and the next day, the app is broken. You have no idea which of those tiny edits caused the disaster. You're left grepping through files, tearing your hair out, and wishing you had a time machine.
Git is that time machine, but only if you use it correctly. The raw power of Git lies in its commit history — a permanent record of every meaningful change you've made. However, Git doesn't automatically snapshot your work like a security camera. You have to tell it what to capture and when to capture it. That's exactly what git add and git commit do.
Without these commands, you're working without a net. You lose the ability to: - Revert a single feature that turned out to be a mistake. - Compare your current code to a working version from last week. - Collaborate with teammates without clobbering each other's work. - Understand the evolution of a file to spot when a bug was introduced.
By the end of this lesson, you'll have the mental model and hands-on skills to capture your work with precision. You'll never have to say "I should have committed that" again.
Core concept / mental model
Think of Git as a photographer for your project. The files in your working directory are the live scene — constantly changing, chaotic, and ephemeral. To capture a moment, you need two things: a composition and a shutter click.
git addis the staging area — it's like arranging your subjects and setting the focus. You choose exactly which files (or even lines within files) will appear in the next snapshot. This is called staging.git commitis the shutter click — it permanently saves the staged snapshot to your project's history database. Each commit gets a unique ID (like a photo number) and a timestamp.

The key insight: a commit is not a copy of your entire project. It's a set of changes (a diff) from the previous commit. This makes Git incredibly efficient — you can view the history as a series of snapshots, but internally it stores the differences between them.
Let's clarify the three main areas you'll work with:
| Area | What it is | Your command |
|---|---|---|
| Working Directory | Your current files on disk | (just edit files) |
| Staging Area (Index) | Snapshot of what you've chosen to commit next | git add |
| Repository (.git) | The full, permanent history | git commit |
Think of it like this: git add is the shopping cart, git commit is the checkout. You don't take the whole store home — you only take what you put in your cart.
How it works step by step
Here's the logical flow that turns chaos into history:
- Modify your files — Edit content in your working directory. Git notices these changes, but does nothing with them until you tell it to.
- Stage the changes — Run
git add <file>orgit add .to move the current state of those files into the staging area. You can stage all files, specific files, or even parts of a file (usinggit add -p). - Check what's staged — Use
git statusandgit diff --cachedto review exactly what you're about to commit. This is your last chance to make sure everything is correct. - Commit the snapshot — Run
git commit -m "Your commit message"to save the staged changes to the repository. A new commit object is created with a unique SHA-1 hash, your name, your email, and a timestamp. - Repeat — Continue this cycle for every logical unit of work.
This two-step process (add, then commit) is what gives you granular control. You might have made changes to five files, but only one of those changes is related to a bug you're fixing. You can stage just that file and commit it with a clear message, keeping your history clean and easy to follow.
Pro tip: Commit early and often. Each commit should represent one logical change — like "fix typo in README" or "add login form validation". This makes it trivially easy to pinpoint and revert a specific change later.
Hands-on walkthrough
Let's put this into practice with a real (if small) example. We'll create a simple Python script, modify it, and watch Git track every step.
First, initialize a new Git repository and create a file:
mkdir git-practice && cd git-practice
git init
printf 'print("Hello, world!")\n' > hello.py
git status
You should see something like:
On branch master
No commits yet
Untracked files:
(use "git add <file>" to include in what will be committed)
hello.py
nothing added to commit but untracked files present (use "git add" to track)
Now, stage and commit your first version:
# Stage the file
git add hello.py
# See what you're about to commit (still uncommitted)
git status
# Commit it with a message
git commit -m "Initial commit: hello.py prints greeting"
The git status output now shows Changes to be committed with hello.py listed. After the commit, you'll see:
[master (root-commit) 1a2b3c4] Initial commit: hello.py prints greeting
1 file changed, 1 insertion(+)
Now let's modify the file and see the full cycle:
# Edit hello.py
printf 'print("Hello, Git!")\n' > hello.py
# Check status
git status
# Notice: hello.py is modified, but NOT staged
# Stage it
git add hello.py
# Review the difference between staging area and last commit
git diff --cached
# Commit the change
git commit -m "Update greeting to be more Git-friendly"
# View the full history
git log --oneline
Your git log should look like this:
2b5f8d1 Update greeting to be more Git-friendly
1a2b3c4 Initial commit: hello.py prints greeting
Congratulations — you've just mastered the core loop of version control! Every commit you make is now a permanent, recoverable point in time.
Compare options / when to choose what
There are several ways to use git add and git commit, and knowing when to use each can save you a lot of pain.
Staging options
| Command | What it does | Use it when |
|---|---|---|
git add <file> |
Stages a single file | You want to commit a specific file independently |
git add . |
Stages all changed files in the current directory (and subdirectories) | You're sure every change belongs in this commit |
git add -p |
Stages parts of a file (patch mode) | You made multiple unrelated changes in one file and want to split them into separate commits |
git add -A |
Stages all changes, including deletions, in the entire repo | You want to commit everything, everywhere |
Committing options
| Command | What it does | Use it when |
|---|---|---|
git commit -m "Message" |
Creates a commit with an inline message | Most of the time — simple and fast |
git commit (without -m) |
Opens your default text editor for a multi-line message | You need a detailed explanation with a body |
git commit -am "Message" |
Stages tracked files and commits in one go | You're only modifying files that are already tracked, and you want to skip the separate add step |
git commit --amend |
Replaces the last commit with a new one | You made a typo in the commit message or forgot to stage a tiny change that belongs to that commit |
git add . vs git add -A
The difference is subtle but important:
- git add . stages changes in the current directory recursively, but does not stage deletions of files that were explicitly deleted (in older Git versions).
- git add -A (or git add --all) stages everything in the whole repository, including deletions, renames, and new files.
For a beginner, git add -A is often safer if you're in the root directory. But be careful — it can accidentally stage large binaries or secret files if you haven't set up a .gitignore.
Troubleshooting & edge cases
"nothing added to commit but untracked files present"
This happens when you try to commit without staging. Git's commit command only saves what's in the staging area, not the working directory. Fix it with git add <file> first.
"Changes not staged for commit"
You modified a tracked file, but didn't stage it yet. git status will show this in a red "Changes not staged". Run git add to stage it, or use git commit -am to skip staging for tracked files.
You staged the wrong file
If you accidentally ran git add . and staged everything, but only want to commit one file, you can unstage with git reset <file>. This moves the file back to the working directory while keeping your changes intact.
git reset HEAD hello.py
You made a typo in the commit message
Use git commit --amend. This will open your editor with the last message so you can fix it. It's safe as long as you haven't pushed that commit to a shared repository.
"file deleted but I want to restore"
If you deleted a file and haven't committed yet, you can restore it with git checkout -- <file> (or git restore in Git 2.23+). If you already committed the deletion, you'd use git revert or git reset (discussed in a later lesson).
Large repo slowing down
If you've committed large binary files (like images or build artifacts), your repository will grow huge. Mitigate by using a .gitignore file and not committing those files in the first place. The lesson on .gitignore in this track covers this in depth.
What you learned & what's next
You've now unlocked the fundamental rhythm of Git: modify → stage → commit. You understand that git add builds a snapshot of intended changes in the staging area, while git commit permanently burns that snapshot into your project's history. You can confidently stage specific files, review what's about to be committed, write meaningful messages, and navigate the most common pitfalls.
You've met the learning objectives:
- Explain the core idea — You know Git tracks changes via a two-step process of staging and committing.
- Complete a practical exercise — You made multiple commits and viewed the log with git log.
Next step: You're ready to dig into git diff and git log to inspect those changes more deeply. Soon you'll be branching, merging, and collaborating like a pro. The next lesson in this track covers viewing and comparing changes. See you there!
Practice recap
Practice what you learned: Create a new directory, init a Git repo, and add a small text file. Make at least three separate edits and commit each one with a descriptive message. Use git log --oneline to see your history, and try git diff to see what changed between commits. This will cement the staging workflow into muscle memory.
Common mistakes
- Forgetting to stage files before committing — you'll get 'nothing added to commit' error. Always run
git statusfirst. - Using
git commit -amwhen you have new untracked files — it only commits tracked files, so new files will be left out silently. - Running
git add .indiscriminately and committing secrets, large binaries, or build artifacts. Use a.gitignoreor stage specific files. - Writing vague commit messages like 'fix stuff' — make each commit a descriptive note that explains why the change was made.
Variations
- Use
git add -pto selectively stage hunks of a file, letting you split multiple logical changes into separate commits. - Use
git commit --amendto update the last commit message or add a missed change without creating a new commit (only before pushing). - Use
git commit -amto skip the explicit staging step when editing tracked files only — a faster workflow for solo projects.
Real-world use cases
- Daily development workflow: you implement a new feature and commit it with a descriptive message so teammates and future-you can review changes via
git log. - Incident rollback: when a production bug is found, you trace the history with
git log -pto pinpoint the exact commit that introduced it, then revert it cleanly. - Code review preparation: you stage and commit changes in logical chunks (e.g., refactor vs. feature), making each commit a self-contained unit that reviewers can approve or reject separately.
Key takeaways
- Git tracks changes via a two-step process:
git addstages files,git commitsaves them permanently. - The staging area gives you granular control over what goes into each snapshot.
- Commit early and often, with each commit representing one logical change.
- Use
git statusandgit diff --cachedto review before you commit. - You can recover from mistakes using
git resetto unstage andgit commit --amendto fix messages. - The
git logcommand lets you view your complete history of changes.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.