git add, git commit & git diff
Quick Summary
add moves changes to the staging area. commit saves staged changes as a permanent snapshot. diff shows you exactly what changed. These three commands are the heartbeat of every Git workflow — you'll use them dozens of times per day.
git add — Stage Changes
Selects which changes to include in your next commit.
Syntax
git add <file> # Stage a specific file
git add <directory>/ # Stage all changes in a directory
git add . # Stage everything in current directory (recursive)
git add -A # Stage everything (including deletions)
git add -p # Interactive: choose hunks to stage
Examples
# Stage a single file
git add README.md
# Stage multiple files
git add src/app.js src/utils.js
# Stage all changes (new, modified, deleted)
git add -A
# Stage only modified and deleted files (not new files)
git add -u
Interactive Staging (-p)
Lets you choose which parts of a file to stage:
git add -p src/app.js
@@ -10,6 +10,8 @@ function login(user) {
const token = generateToken(user);
+ const expiry = Date.now() + 3600000;
+ logger.info('Login successful');
return token;
}
Stage this hunk [y,n,q,a,d,s,e,?]?
| Key | Action |
|---|---|
y | Stage this hunk |
n | Skip this hunk |
s | Split into smaller hunks |
q | Quit (don't stage remaining) |
e | Edit the hunk manually |
Why use
-p?When you've made multiple unrelated changes in one file, -p lets you split them into separate, focused commits. This produces a cleaner, more reviewable history.
git commit — Save a Snapshot
Creates a permanent record of the staged changes.
Syntax
git commit -m "message" # Commit with inline message
git commit # Opens editor for message
git commit -am "message" # Add all tracked files + commit (skip git add)
git commit --amend # Modify the last commit
git commit --amend --no-edit # Amend without changing the message
Commit Message Best Practices
# Good: specific, actionable
git commit -m "Fix login timeout by increasing JWT expiry to 24h"
git commit -m "Add input validation for user registration form"
git commit -m "Remove deprecated API endpoint /v1/users"
# Bad: vague, useless
git commit -m "fix"
git commit -m "update"
git commit -m "changes"
git commit -m "WIP"
Conventional Commits (Industry Standard)
git commit -m "feat: add user avatar upload"
git commit -m "fix: resolve null pointer in payment handler"
git commit -m "docs: update API authentication guide"
git commit -m "refactor: extract validation into separate module"
git commit -m "chore: update dependencies to latest versions"
git commit -m "test: add unit tests for login flow"
| Prefix | When to Use |
|---|---|
feat: | New feature |
fix: | Bug fix |
docs: | Documentation only |
style: | Formatting (no logic change) |
refactor: | Code restructure (no behavior change) |
test: | Adding/fixing tests |
chore: | Maintenance (deps, config, CI) |
perf: | Performance improvement |
Amending the Last Commit
# Made a typo in the message?
git commit --amend -m "Fix: correct the error message for login failures"
# Forgot to include a file?
git add forgotten-file.js
git commit --amend --no-edit
Amend only unpushed commits
If you've already pushed the commit, amending changes its SHA hash. You'd need git push --force, which can disrupt collaborators.
git diff — See What Changed
Shows the exact differences between files, commits, or branches.
Syntax
git diff # Working directory vs staging area
git diff --staged # Staging area vs last commit
git diff HEAD # Working directory vs last commit
git diff <commit1> <commit2> # Between two commits
git diff <branch1>..<branch2> # Between two branches
git diff --stat # Summary of changes (files + lines)
Reading Diff Output
diff --git a/src/auth.js b/src/auth.js
index a1b2c3d..d4e5f6a 100644
--- a/src/auth.js
+++ b/src/auth.js
@@ -10,7 +10,9 @@ function login(user, password) {
const isValid = validateCredentials(user, password);
- if (!isValid) return null;
+ if (!isValid) {
+ logger.warn(`Failed login attempt for user: ${user.email}`);
+ return { error: 'Invalid credentials' };
+ }
const token = generateToken(user);
| Symbol | Meaning |
|---|---|
--- | Old file (before changes) |
+++ | New file (after changes) |
- (red) | Line removed |
+ (green) | Line added |
@@ | Location marker (line numbers) |
Practical Examples
# What did I change since last commit? (unstaged)
git diff
# What have I staged for the next commit?
git diff --staged
# Quick summary: which files changed and how many lines?
git diff --stat
# Compare two branches
git diff main..feature/login
# Compare a specific file between branches
git diff main..feature/login -- src/auth.js
The Complete Stage-Commit Flow
sequenceDiagram
participant WD as Working Directory
participant SA as Staging Area
participant REPO as Repository
Note over WD: You edit files
WD->>WD: Edit src/app.js
WD->>WD: Create new-file.js
Note over WD,SA: Review changes
WD->>WD: git diff (see changes)
WD->>WD: git status (see state)
Note over WD,SA: Stage changes
WD->>SA: git add src/app.js
WD->>SA: git add new-file.js
Note over SA: Review staged
SA->>SA: git diff --staged
Note over SA,REPO: Commit
SA->>REPO: git commit -m "Add feature"
Decision Guide
| What You Want | Command |
|---|---|
| Stage a specific file | git add <file> |
| Stage everything | git add -A |
| Stage parts of a file | git add -p <file> |
| Commit with a message | git commit -m "message" |
| Stage + commit tracked files | git commit -am "message" |
| Fix the last commit | git commit --amend |
| See unstaged changes | git diff |
| See staged changes | git diff --staged |
| See change summary | git diff --stat |
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
nothing to commit | No staged changes | Run git add first |
Changes not staged for commit | Files modified but not added | Run git add <file> |
| Committed wrong files | Added too broadly | Use git reset HEAD <file> to unstage |
| Commit message typo | Just committed | git commit --amend -m "corrected" |
| Giant diff output | Too many changes | Use git diff --stat for summary |
Best Practices
- Stage selectively — Don't blindly
git add .; review withgit statusfirst - Commit often — Small, focused commits are easier to understand and revert
- Use conventional commits — Structured messages enable automated changelogs
- Review diffs before committing —
git diff --stagedcatches mistakes early - One logical change per commit — Don't mix a bug fix with a feature in one commit
What's Next
- log & history — Navigate and search your commit history
- stash & clean — Save work temporarily or clean up