Git - Adding & Staging
The staging area (also called the "index") is Git's unique feature that lets you carefully choose which changes to include in your next commit. Mastering git add
and staging gives you precise control over your project history.
Understanding the Staging Area
Think of the staging area as a "loading dock" where you prepare changes before committing them:
Working Directory → Staging Area → Repository
(modified) (staged) (committed)
↓ ↓ ↓
[file.txt] [file.txt ready] [file.txt saved]
[for commit] [permanently]
This three-step process lets you:
- Review changes before committing
- Commit only related changes together
- Skip temporary or experimental changes
- Create clean, logical commits
Basic git add Commands
Adding Specific Files
# Add single file
git add README.md
# Add multiple files
git add file1.txt file2.txt file3.txt
# Add files with wildcards
git add *.js # All JavaScript files
git add src/*.py # All Python files in src/
git add docs/**/*.md # All Markdown files in docs/ and subdirectories
Adding Directories
# Add entire directory
git add src/
# Add multiple directories
git add src/ tests/ docs/
Adding All Changes
# Add all changes in current directory and subdirectories
git add .
# Add all changes in entire repository (from any location)
git add -A
# or
git add --all
# Add only tracked files (skip new files)
git add -u
# or
git add --update
Practical Staging Examples
Let's work through realistic scenarios:
Scenario 1: Web Development Project
mkdir web-project && cd web-project
git init
# Create files
echo "# My Website" > README.md
echo "Home Welcome
" > index.html
echo "body { font-family: Arial; }" > style.css
echo "console.log('Hello World!');" > script.js
echo "Temporary notes..." > temp.txt
git status
On branch main
No commits yet
Untracked files:
(use "git add ..." to include in what will be committed)
README.md
index.html
script.js
style.css
temp.txt
nothing added to commit but untracked files present (use "git add" to track)
git add README.md index.html style.css script.js
git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: README.md
new file: index.html
new file: script.js
new file: style.css
Untracked files:
(use "git add ..." to include in what will be committed)
temp.txt
Scenario 2: Selective Changes
# Modify existing file
echo "New paragraph
" >> index.html
# Create new feature file
echo "function newFeature() { return 'awesome'; }" > feature.js
# Create configuration file
echo "DEBUG=true" > config.env
# Modify CSS
echo "h1 { color: blue; }" >> style.css
git status
On branch main
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes to working directory)
modified: index.html
modified: style.css
Untracked files:
(use "git add ..." to include in what will be committed)
config.env
feature.js
temp.txt
no changes added to commit (use "git add" or "git commit -a")
git add feature.js index.html
Now you can commit the feature separately from the CSS styling changes.
Advanced Staging Techniques
Interactive Staging
For even more control, use interactive mode:
git add -i
staged unstaged path
1: +4/-0 nothing index.html
2: unchanged +1/-0 style.css
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
Patch Mode (Partial File Staging)
Stage only parts of a file:
git add -p filename
echo "function oldFunction() { return 'old'; }" > functions.js
echo "function newFunction() { return 'new'; }" >> functions.js
echo "function buggyFunction() { return 'bugs'; }" >> functions.js
git add functions.js
git commit -m "Add function definitions"
# Now modify the file
sed -i '' 's/old/updated/' functions.js
sed -i '' 's/bugs/fixed/' functions.js
git add -p functions.js
@@ -1,3 +1,3 @@
-function oldFunction() { return 'old'; }
+function oldFunction() { return 'updated'; }
function newFunction() { return 'new'; }
function buggyFunction() { return 'bugs'; }
(1/1) Stage this hunk [y,n,q,a,d,e,?]?
Patch mode commands:
y
- Yes, stage this hunkn
- No, don't stage this hunkq
- Quit, don't stage this or remaining hunksa
- Stage this and all remaining hunksd
- Don't stage this or remaining hunkss
- Split this hunk into smaller onese
- Edit the hunk manually
Working with .gitignore
Some files should never be tracked. Use .gitignore
to exclude them:
# Operating system files
.DS_Store
Thumbs.db
# IDE and editor files
.vscode/
.idea/
*.swp
*.swo
# Language-specific
node_modules/
*.pyc
__pycache__/
target/
*.class
# Build outputs
dist/
build/
*.o
*.exe
# Logs and databases
*.log
*.db
*.sqlite
# Environment and secrets
.env
.env.local
config/secrets.json
*.key
# Create ignored files
touch .DS_Store
mkdir node_modules
touch debug.log
# Check status - these files won't show up
git status
Global .gitignore
Set up patterns for all your repositories:
# Create global gitignore
echo ".DS_Store" > ~/.gitignore_global
echo "*.swp" >> ~/.gitignore_global
# Configure Git to use it
git config --global core.excludesfile ~/.gitignore_global
Forcing Ignored Files
Sometimes you need to track normally-ignored files:
# Force add ignored file
git add -f debug.log
# Check what's ignored
git check-ignore -v debug.log
Unstaging Files
Made a mistake? Remove files from staging area:
git restore --staged filename
git restore --staged .
# Unstage specific file
git reset HEAD filename
# Unstage all files
git reset HEAD
Viewing Staged Changes
See What's Staged
# Show staged changes
git diff --staged
# or
git diff --cached
See What's Not Staged
# Show unstaged changes
git diff
Compare Working, Staged, and Committed
# Working vs staged
git diff
# Staged vs last commit
git diff --staged
# Working vs last commit (skip staging)
git diff HEAD
Staging Strategies
Feature-Based Staging
# Work on multiple features
# Feature A: User login
git add auth.js login.html
git commit -m "Add user login feature"
# Feature B: Dashboard
git add dashboard.js dashboard.html dashboard.css
git commit -m "Add user dashboard"
File-Type Staging
# Stage by file type
git add *.html # HTML first
git commit -m "Update HTML structure"
git add *.css # Then CSS
git commit -m "Improve styling"
git add *.js # Finally JavaScript
git commit -m "Add interactive features"
Common Staging Patterns
The "Add Everything" Anti-Pattern
git add .
git commit -m "stuff"
This creates messy commits with unrelated changes.
git add src/user-auth.js tests/auth.test.js
git commit -m "Add user authentication with tests"
git add src/styles.css
git commit -m "Update button styling for accessibility"
Review Before Staging
# 1. See what changed
git status
git diff
# 2. Stage thoughtfully
git add specific-files
# 3. Review staged changes
git diff --staged
# 4. Commit with good message
git commit -m "Descriptive message"
Troubleshooting Staging
File Not Staging
git check-ignore -v filename
Unexpected Files in Status
git status --ignored
Staging Area Corruption
git reset
Performance Tips
Large Repositories
# Use pathspecs for large repos
git add src/components/ # Instead of git add .
# Skip expensive operations
git add --ignore-removal . # Don't check for deleted files
Summary
You now understand Git staging:
- ✅ The staging area acts as a preparation zone for commits
- ✅
git add
has many variations for different needs - ✅ Interactive staging with
-p
allows partial file commits - ✅
.gitignore
prevents unwanted files from being tracked - ✅
git restore --staged
unstages files - ✅ Always review staged changes before committing
- ✅ Strategic staging creates cleaner project history
Next Steps
Now that you can stage changes precisely, let's learn about creating great commits: