Working Code
Example 1: From adding a file to committing
Initialize a repository and make your first commit:
git init
echo "# My Project" > README.md
git status
Output (file is Untracked):
Untracked files:
README.md
Stage it:
git add README.md
git status
Output (staged):
Changes to be committed:
new file: README.md
Commit:
git commit -m "feat: add README file"
Output:
[main (root-commit) a1b2c3d] feat: add README file
1 file changed, 1 insertion(+)
create mode 100644 README.md
What the output means:
main: Current brancha1b2c3d: Commit hash (unique ID)1 file changed, 1 insertion(+): Change statistics
Example 2: Viewing changes with git diff
Modify a file and check the diff:
echo "This project is for practicing Git." >> README.md
git diff
Output:
diff --git a/README.md b/README.md
index abc1234..def5678 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
# My Project
+This project is for practicing Git.
- Lines starting with
-: Removed content - Lines starting with
+: Added content - Lines starting with a space: Unchanged
Example 3: Checking diff after staging
git add README.md
git diff --staged
git diff shows unstaged changes. git diff --staged shows staged changes.
Commit:
git commit -m "docs: add project description"
Try It Yourself
Selective staging
You can pick only the related files to commit:
# Add 3 files
echo "// Login" > login.js
echo "// Signup" > signup.js
echo "body { margin: 0; }" > style.css
git status
Output:
Untracked files:
login.js
signup.js
style.css
# Stage only the login file
git add login.js
git status
Output:
Changes to be committed:
new file: login.js
Untracked files:
signup.js
style.css
git commit -m "feat: add login feature"
# Commit the rest
git add signup.js style.css
git commit -m "feat: add signup and styles"
Viewing history with git log
git log
Output (detailed):
commit e4f5g6h7i8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x (HEAD -> main)
Author: John Doe <john@example.com>
Date: Mon Jan 15 10:35:00 2024 +0900
feat: add signup and styles
commit a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t
Author: John Doe <john@example.com>
Date: Mon Jan 15 10:30:00 2024 +0900
feat: add login feature
# Compact one-line format
git log --oneline
Output:
e4f5g6h feat: add signup and styles
a1b2c3d feat: add login feature
abc1234 docs: add project description
a1b2c3d feat: add README file
# Include changed file names
git log --oneline --name-status
Output:
e4f5g6h feat: add signup and styles
A signup.js
A style.css
a1b2c3d feat: add login feature
A login.js
git commit --amend: Fix the last commit
When you spot a typo or forgot to include a file right after committing:
# Commit with a typo
git commit -m "feat: add login featrue" # typo in 'feature'
# Fix the message only
git commit --amend -m "feat: add login feature"
# Add a forgotten file and amend
git add forgotten-file.txt
git commit --amend --no-edit # Keep the existing message
Warning: Do not use --amend on commits that have already been pushed. It changes the commit hash, which causes problems for collaborators.
"Why?" -- Why have a staging area?
Why not commit directly? The staging step exists for a reason:
Selective commits are possible. Even if you modified 10 files, you can group related changes into separate commits.
# Modified files A, B, C
git add login.js auth.js # Stage only login-related files
git commit -m "fix: fix login bug"
git add profile.js # Commit profile changes separately
git commit -m "feat: add profile editing"
This keeps history organized by purpose, making it easier to trace changes later.
Writing good commit messages
type: summary of changes (under 50 characters)
Common types:
feat-- New featurefix-- Bug fixdocs-- Documentation changesrefactor-- Refactoring (no behavior change)chore-- Build, packages, and other maintenance
Good commit messages:
feat: add social login (Google)
fix: fix password reset email not sending
docs: add authentication section to API docs
Bad commit messages:
fix
update
aaaaa
WIP
stuff
diff flow summary
[Working Directory] <- git diff -> [Staging Area]
[Staging Area] <- git diff --staged -> [Repository (last commit)]
Common Mistakes
Mistake 1: The git add . trap
# Stages everything in the current directory
git add .
# This may include unwanted files (temp files, config files, etc.)
# Always check with git status first!
git status
git add .
Mistake 2: Committing without a message
git commit # No message -> editor opens
# Depending on your config, vim may open and confuse you
When starting out, always use -m for inline messages:
git commit -m "your commit message"
Mistake 3: Not checking diff before staging
# Bad workflow
git add .
git commit -m "update"
# Good workflow
git diff # Review changes
git add filename # Stage only what you need
git diff --staged # Final check of staged changes
git commit -m "clear message"
Deep Dive
Various git log options
# Graph view
git log --oneline --graph
# History for a specific file
git log --oneline README.md
# Include diffs
git log -p
# Limit number of commits
git log -3 # Last 3 only
# Date range
git log --after="2024-01-01" --before="2024-02-01"
# Specific author
git log --author="John Doe"
# Search commit messages
git log --grep="feat"
Unstaging with git restore
To unstage files or discard changes:
# Unstage (keep working directory changes)
git restore --staged filename
# Unstage everything
git restore --staged .
# Discard working directory changes (revert to last commit)
git restore filename # Warning: this cannot be undone!
Undoing commits with git reset
For commits that haven't been pushed yet:
# Undo last commit (changes stay staged)
git reset --soft HEAD~1
# Undo last commit (changes go to working directory)
git reset HEAD~1 # or git reset --mixed HEAD~1
# Undo last commit (changes are completely removed)
git reset --hard HEAD~1 # Warning: hard to recover!
Undoing pushed commits is more complex. That's covered in Lesson 11.
- Create a new repository and add
README.mdwith a first commit. - Modify
README.mdand check the changes withgit diff. - After
git add README.md, check staged changes withgit diff --staged. - Create 3 files. Stage 2 for the first commit and the remaining 1 for a second commit.
- Review the commit history with
git log --oneline.
Q1. What is the difference between git diff and git diff --staged?
- A)
git diffshows all changes,git diff --stagedshows only staged ones - B)
git diffshows unstaged changes,git diff --stagedshows staged changes - C)
git diffcompares files,git diff --stagedcompares commits - D) Both commands show the same result