Skip to main content

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,?]?
KeyAction
yStage this hunk
nSkip this hunk
sSplit into smaller hunks
qQuit (don't stage remaining)
eEdit 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"
PrefixWhen 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);
SymbolMeaning
---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 WantCommand
Stage a specific filegit add <file>
Stage everythinggit add -A
Stage parts of a filegit add -p <file>
Commit with a messagegit commit -m "message"
Stage + commit tracked filesgit commit -am "message"
Fix the last commitgit commit --amend
See unstaged changesgit diff
See staged changesgit diff --staged
See change summarygit diff --stat

Troubleshooting

ProblemCauseFix
nothing to commitNo staged changesRun git add first
Changes not staged for commitFiles modified but not addedRun git add <file>
Committed wrong filesAdded too broadlyUse git reset HEAD <file> to unstage
Commit message typoJust committedgit commit --amend -m "corrected"
Giant diff outputToo many changesUse git diff --stat for summary

Best Practices

  • Stage selectively — Don't blindly git add .; review with git status first
  • Commit often — Small, focused commits are easier to understand and revert
  • Use conventional commits — Structured messages enable automated changelogs
  • Review diffs before committinggit diff --staged catches mistakes early
  • One logical change per commit — Don't mix a bug fix with a feature in one commit

What's Next

  1. log & history — Navigate and search your commit history
  2. stash & clean — Save work temporarily or clean up