Making Meaningful Commits
Commits are the building blocks of Git history. Each commit is a snapshot of your project at a point in time. Learning to make good commits is essential for maintaining a useful project history.
What is a Commit?
A commit is a permanent snapshot that contains:
┌────────────────────────────────────────┐
│ Commit Object │
├────────────────────────────────────────┤
│ SHA: a1b2c3d4e5f6... │
│ Author: Jane Doe <jane@example.com> │
│ Date: 2025-01-15 10:30:00 │
│ Parent: 9876543210... │
│ Message: "Add user authentication" │
│ Tree: (snapshot of all files) │
└────────────────────────────────────────┘
Commit Components
| Component | Description |
|---|---|
| SHA Hash | Unique 40-character identifier |
| Author | Who created the changes |
| Committer | Who made the commit (usually same as author) |
| Date | When the commit was made |
| Parent | The previous commit (or commits for merges) |
| Message | Description of the changes |
| Tree | Snapshot of the entire project |
Creating Commits
Basic Commit
# Stage changes first
git add filename.js
# Commit with a message
git commit -m "Add login validation"
Multi-line Commit Messages
# Opens your editor
git commit
# Or inline with -m (use multiple -m flags)
git commit -m "Add login validation" -m "This includes email format checking and password strength requirements."
Stage and Commit Together
# Only works for already-tracked files
git commit -am "Update all tracked files"
Note: This won't add new files—only modified ones that Git already knows about.
Anatomy of a Good Commit
A well-structured commit message has:
Short summary (50 chars or less)
More detailed explanation if needed. Wrap at 72 characters.
Explain the what and why, not the how (code shows how).
- Bullet points are okay
- Keep them concise
Resolves: #123
The 50/72 Rule
- First line: 50 characters or less (summary)
- Blank line: Separates summary from body
- Body: Wrap at 72 characters
Why These Limits?
- Git commands truncate at 50 chars:
git log --oneline - Email and terminal displays work well at 72 chars
- Forces concise, thoughtful messages
Commit Message Best Practices
1. Use Imperative Mood
Write as if giving a command:
✅ Good:
- "Add user authentication"
- "Fix memory leak in parser"
- "Update dependencies to latest versions"
❌ Bad:
- "Added user authentication"
- "Fixes memory leak"
- "Updated dependencies"
Think: "This commit will... [your message]"
2. Be Specific
✅ Good:
- "Fix null pointer exception in UserService.getUser()"
- "Add email validation to signup form"
❌ Bad:
- "Fix bug"
- "Update code"
- "Changes"
3. Explain Why, Not Just What
Add rate limiting to API endpoints
Users were experiencing 503 errors during peak traffic.
Rate limiting prevents server overload by capping
requests at 100/minute per IP address.
4. Reference Issues
Fix login redirect loop
Users were stuck in redirect loop when session expired.
Now properly clears cookies before redirecting.
Fixes #234
Closes #235
Viewing Commits
# Full log
git log
# One line per commit
git log --oneline
# Show diffs
git log -p
# Last 3 commits
git log -3
# Show stats (files changed)
git log --stat
# Pretty format
git log --pretty=format:"%h %an %ar - %s"
# Graphical branch history
git log --oneline --graph --all
Reading git log Output
commit a1b2c3d4e5f6789012345678901234567890abcd (HEAD -> main)
Author: Jane Doe <jane@example.com>
Date: Mon Jan 15 10:30:00 2025 -0500
Add user authentication
This commit adds login and logout functionality using JWT tokens.
Includes middleware for protected routes.
Amending Commits
Fix the Last Commit Message
git commit --amend -m "New message"
Add Forgotten Files to Last Commit
git add forgotten-file.js
git commit --amend --no-edit
Warning: Only amend commits that haven't been pushed!
Exercise: Create Good Commits
Practice creating well-structured commits:
Atomic Commits
An atomic commit is a self-contained unit of change:
Characteristics of Atomic Commits
- Single purpose: One logical change per commit
- Complete: The project works after each commit
- Independent: Can be reverted without side effects
- Reviewable: Easy to understand and review
Example: Refactoring
❌ Bad (one big commit):
git commit -m "Refactor user module, fix bugs, add tests, update docs"
✅ Good (atomic commits):
git commit -m "Extract user validation into separate function"
git commit -m "Fix null check in user lookup"
git commit -m "Add unit tests for user validation"
git commit -m "Update user module documentation"
Empty Commits
Sometimes you need a commit without file changes:
git commit --allow-empty -m "Trigger CI build"
Use cases:
- Triggering CI/CD pipelines
- Marking milestones
- Documentation-only commits
Signing Commits
For security, you can sign commits with GPG:
# Configure GPG key
git config --global user.signingkey YOUR_KEY_ID
# Sign a commit
git commit -S -m "Signed commit"
# Always sign commits
git config --global commit.gpgsign true
Commit Templates
Create a template for consistent messages:
# Create template file
cat > ~/.gitmessage << 'EOF'
# Title: Summary, imperative, 50 chars or less
# Body: Explain *what* and *why* (not *how*). Wrap at 72 chars.
# Issue references:
# Fixes #
EOF
# Configure Git to use it
git config --global commit.template ~/.gitmessage
Summary
- Commits are permanent snapshots of your project
- Use imperative mood: "Add feature" not "Added feature"
- Follow the 50/72 rule for message length
- Explain why, not just what
- Make atomic commits (one logical change each)
- Reference issues when applicable
- Use
git commit --amendto fix the last commit (before pushing)
In the next lesson, we'll learn how to view and explore commit history.

