DaleSchool

Staging and Committing

Beginner25min

Learning Objectives

  • Stage changes with git add
  • Create meaningful commits with git commit
  • Inspect changes with git diff and git diff --staged
  • View commit history with git log

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 branch
  • a1b2c3d: 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 feature
  • fix -- Bug fix
  • docs -- Documentation changes
  • refactor -- 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.

  1. Create a new repository and add README.md with a first commit.
  2. Modify README.md and check the changes with git diff.
  3. After git add README.md, check staged changes with git diff --staged.
  4. Create 3 files. Stage 2 for the first commit and the remaining 1 for a second commit.
  5. Review the commit history with git log --oneline.

Q1. What is the difference between git diff and git diff --staged?

  • A) git diff shows all changes, git diff --staged shows only staged ones
  • B) git diff shows unstaged changes, git diff --staged shows staged changes
  • C) git diff compares files, git diff --staged compares commits
  • D) Both commands show the same result