Lesson 2: Essential Commands — Daily Workflow
Master the fundamental Git commands you'll use every day: init, clone, add, commit, status, log, diff. Learn to write meaningful commit messages and configure .gitignore properly.
Lesson 2: Essential Commands — Daily Workflow 💻
Introduction
Now that you understand Git's mental model of snapshots, it's time to put that knowledge into practice. In this lesson, we'll cover the essential commands that form 90% of your daily Git workflow. These aren't random incantations to memorize—each command connects directly to the snapshot model you learned in Lesson 1.
Think of Git commands as a camera workflow: init sets up your camera, add frames your shot, commit takes the picture, status shows what's in frame, log displays your photo album, and diff compares images. Once you internalize this workflow, Git becomes intuitive rather than intimidating.
💡 Pro Tip: You'll use these seven commands (init, clone, add, commit, status, log, diff) for most of your Git work. Everything else is special cases and advanced techniques.
Core Concepts
🎬 Starting a Repository: git init vs git clone
Every Git workflow begins with establishing a repository. You have two options:
git init creates a brand new repository from scratch. Use this when you're starting a new project:
$ mkdir my-project
$ cd my-project
$ git init
Initialized empty Git repository in /Users/you/my-project/.git/
What just happened? Git created a hidden .git directory that stores all snapshots, branches, and metadata. Your project folder is now the working directory, and that .git folder is the repository.
my-project/
├── .git/ ← The repository (database of snapshots)
│ ├── objects/ ← Where snapshots are stored
│ ├── refs/ ← Branch pointers
│ └── HEAD ← Current branch pointer
└── (your files here) ← Working directory
git clone copies an existing repository from somewhere else (usually GitHub, GitLab, or a coworker's machine):
$ git clone https://github.com/user/project.git
Cloning into 'project'...
remote: Counting objects: 100, done.
Receiving objects: 100% (100/100), done.
Cloning downloads the entire history—every snapshot ever taken. You get a complete working copy plus all the project's history.
🧠 Memory Aid: Init = Initialize a new project. Clone = Copy an existing one.
📸 The Three-Stage Workflow: Working Directory → Staging Area → Repository
This is the heart of daily Git usage. Understanding these three areas prevents 90% of confusion:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ WORKING │ │ STAGING │ │ REPOSITORY │
│ DIRECTORY │ │ AREA │ │ (.git dir) │
│ │ │ (Index) │ │ │
│ Your files as │ │ Files ready │ │ Committed │
│ they exist now │ │ for snapshot │ │ snapshots │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ git add │ git commit │
└────────────────────────>└────────────────────────>│
│ │ │
│<──────────── git status shows differences ────────│
Working Directory: Your actual project files where you edit, create, and delete.
Staging Area (also called the Index): A preparation zone where you assemble changes for the next snapshot. This is Git's unique feature—it lets you carefully curate what goes into each commit.
Repository: The .git directory containing all committed snapshots (your permanent history).
💡 Why the staging area? It lets you commit logical chunks even when you've changed multiple files. You might fix three bugs, but stage and commit them separately for a cleaner history.
➕ git add — Staging Changes
The add command moves changes from your working directory to the staging area. You're not committing yet—you're saying "I want this in my next snapshot."
# Stage a specific file
$ git add index.html
# Stage multiple files
$ git add index.html styles.css script.js
# Stage all changes in current directory
$ git add .
# Stage all changes in entire repository
$ git add -A
# Stage only modified and deleted files (not new files)
$ git add -u
⚠️ Common Mistake: git add doesn't just add new files—it stages any changes to tracked files. Think of it as "add to the next commit" not "add to Git."
🔧 Try This: Create a file, run git add, then modify the file again. Run git status. You'll see the file listed twice—once staged, once not staged! You've staged the old version. Run git add again to stage the new changes.
✅ git commit — Taking the Snapshot
Once you've staged changes, commit takes the snapshot and permanently stores it in the repository:
# Commit with inline message
$ git commit -m "Add user login feature"
# Open editor for longer message
$ git commit
# Stage all tracked files AND commit (skip git add)
$ git commit -a -m "Fix navigation bug"
Each commit creates a permanent snapshot with:
- A unique SHA-1 hash (like
a3f2b8c...) serving as its ID - Your author name and email
- A timestamp
- A commit message
- A pointer to the parent commit (creating the chain)
- The actual file snapshots
commit a3f2b8c91d4e6f2a1b3c5d7e9f0a2b4c6d8e0f1
Author: Jane Dev <jane@example.com>
Date: Mon Jan 15 14:32:10 2024 -0500
Add user login feature
- Created login form component
- Added authentication service
- Integrated with backend API
📝 Writing Good Commit Messages
Commit messages are documentation for your future self and teammates. Follow these guidelines:
The Golden Rule: Complete this sentence: "If applied, this commit will ___"
✅ Good: "Add user login feature"
✅ Good: "Fix null pointer in payment processor"
✅ Good: "Refactor database connection handling"
❌ Bad: "Changed stuff"
❌ Bad: "Fixed bug"
❌ Bad: "Updates"
Structure for longer messages:
Short summary (50 chars or less)
More detailed explanation if needed. Wrap at 72 characters.
Explain WHAT and WHY, not HOW (the code shows how).
- Use bullet points for multiple changes
- Reference issue numbers: Fixes #123
- Explain any non-obvious decisions
🧠 Memory Aid: S-W-E-A-T: Short summary, Why you did it, Explain context, Add references, Tell the impact.
🔍 git status — What's Happening Now?
The most important command for beginners. Run it constantly—it shows the current state of all three areas:
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: index.html
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes)
modified: styles.css
Untracked files:
(use "git add <file>..." to include in what will be committed)
script.js
This tells you:
- Changes to be committed: Staged in the staging area
- Changes not staged: Modified but not added yet
- Untracked files: New files Git isn't tracking yet
💡 Pro Tip: Use git status -s for a compact view:
M index.html ← Staged modification
M styles.css ← Unstaged modification
?? script.js ← Untracked file
📖 git log — Viewing History
The log command displays your commit history—your album of snapshots:
# Standard log
$ git log
# Compact one-line format
$ git log --oneline
# Show last 5 commits
$ git log -5
# Show commits with file changes
$ git log --stat
# Visual branch diagram
$ git log --graph --oneline --all
Example output:
$ git log --oneline --graph
* a3f2b8c (HEAD -> main) Add user login feature
* 7d1e9f4 Fix navigation styling
* 2b4c6d8 Update homepage content
* 9f0a2b4 Initial commit
Each line shows:
- The commit hash (shortened)
- The branch pointer locations (HEAD, main)
- The commit message
🤔 Did You Know? Git's SHA-1 hashes are so unique that in a repository with thousands of commits, you can usually identify a commit with just the first 7 characters.
🔬 git diff — Comparing Changes
The diff command shows exactly what changed between versions:
# Show unstaged changes (working directory vs staging area)
$ git diff
# Show staged changes (staging area vs last commit)
$ git diff --staged
# Compare two commits
$ git diff a3f2b8c 7d1e9f4
# Show changes in specific file
$ git diff index.html
Example output:
diff --git a/index.html b/index.html
index 2b4c6d8..7d1e9f4 100644
--- a/index.html
+++ b/index.html
@@ -10,7 +10,7 @@
<body>
- <h1>Welcome</h1>
+ <h1>Welcome to Our Site</h1>
<p>This is the homepage.</p>
+ <p>Check out our new features!</p>
</body>
Lines starting with - were removed, + were added. The @@ shows line numbers.
💡 Pro Tip: Use git diff --color-words to see word-by-word changes instead of line-by-line, great for prose and documentation.
🚫 .gitignore — Files to Exclude
Not everything should be tracked. The .gitignore file tells Git what to ignore:
# Comments start with #
# Ignore all .log files
*.log
# Ignore node_modules directory
node_modules/
# Ignore all files in build/ directory
build/
# But don't ignore build/README.md
!build/README.md
# Ignore .env files (contain secrets)
.env
.env.local
# Ignore OS files
.DS_Store
Thumbs.db
# Ignore editor files
.vscode/
.idea/
*.swp
What should you ignore?
- ✅ Generated files (compiled code, build artifacts)
- ✅ Dependencies (node_modules, vendor/)
- ✅ Secrets (API keys, passwords, .env files)
- ✅ OS files (.DS_Store, Thumbs.db)
- ✅ Editor settings (personal preferences)
- ❌ Don't ignore: source code, documentation, configuration templates
⚠️ Critical: Create .gitignore BEFORE your first commit. If you accidentally commit secrets, they're in history forever (and require special tools to remove).
🔧 Try This: Visit gitignore.io and generate a .gitignore for your language/framework. It's a time-saver!
Practical Examples
Example 1: Starting a New Project from Scratch 🎬
Let's create a simple website project:
# Step 1: Create project directory
$ mkdir my-website
$ cd my-website
# Step 2: Initialize Git
$ git init
Initialized empty Git repository
# Step 3: Create .gitignore first
$ echo "node_modules/" > .gitignore
$ echo ".DS_Store" >> .gitignore
# Step 4: Create initial files
$ echo "<h1>My Website</h1>" > index.html
$ echo "body { margin: 0; }" > styles.css
# Step 5: Check status
$ git status
Untracked files:
.gitignore
index.html
styles.css
# Step 6: Stage all files
$ git add .
# Step 7: Verify what's staged
$ git status
Changes to be committed:
new file: .gitignore
new file: index.html
new file: styles.css
# Step 8: Commit
$ git commit -m "Initial commit: Add basic HTML and CSS files"
[main (root-commit) a3f2b8c] Initial commit: Add basic HTML and CSS files
3 files changed, 3 insertions(+)
# Step 9: Verify history
$ git log --oneline
a3f2b8c (HEAD -> main) Initial commit: Add basic HTML and CSS files
What happened?
- Created a working directory with
mkdir - Initialized the Git repository (created
.git/) - Created
.gitignoreto exclude unwanted files - Added content files
- Staged everything with
git add . - Committed the first snapshot
- Verified with
git log
Example 2: The Daily Development Cycle 🔄
This is what your typical work session looks like:
# Morning: Start work, check status
$ git status
On branch main
nothing to commit, working tree clean
# Make some changes to index.html
$ echo "<p>New paragraph</p>" >> index.html
# Check what changed
$ git diff
+<p>New paragraph</p>
# Looks good, stage it
$ git add index.html
# Make more changes to styles.css
$ echo "p { color: blue; }" >> styles.css
# Check status: one staged, one unstaged
$ git status
Changes to be committed:
modified: index.html
Changes not staged:
modified: styles.css
# Stage the CSS too
$ git add styles.css
# Commit both together
$ git commit -m "Add new paragraph with blue styling"
# Continue working...
$ echo "<footer>Copyright 2024</footer>" >> index.html
$ git add index.html
$ git commit -m "Add footer section"
# End of day: review what you did
$ git log --oneline
7d1e9f4 (HEAD -> main) Add footer section
2b4c6d8 Add new paragraph with blue styling
a3f2b8c Initial commit: Add basic HTML and CSS files
Key workflow pattern:
- ✏️ Edit files (working directory)
- 🔍 Check changes with
git diffandgit status - ➕ Stage with
git add - ✅ Commit with descriptive message
- 🔁 Repeat
This cycle happens dozens of times per day!
Example 3: Cloning and Contributing to Existing Project 🤝
# Clone a project from GitHub
$ git clone https://github.com/team/project.git
Cloning into 'project'...
remote: Counting objects: 523, done.
Receiving objects: 100% (523/523), done.
# Navigate into the project
$ cd project
# Check the commit history
$ git log --oneline -5
9f0a2b4 (HEAD -> main) Update README
6d8e0f1 Fix login bug
4c6d8e0 Add user dashboard
2b4c6d8 Refactor authentication
a3f2b8c Initial commit
# Create a new feature file
$ touch feature.js
$ echo "console.log('New feature');" > feature.js
# Stage and commit
$ git add feature.js
$ git commit -m "Add new feature module"
# View updated history
$ git log --oneline -3
1a2b3c4 (HEAD -> main) Add new feature module
9f0a2b4 Update README
6d8e0f1 Fix login bug
Explanation: Cloning gives you the entire project history. You can immediately see what's been done, then add your own commits to the chain.
Example 4: Using git diff to Review Before Committing 🔍
# Made several changes, want to review before committing
$ git status
modified: index.html
modified: styles.css
modified: script.js
# See all unstaged changes
$ git diff
# diff --git a/index.html b/index.html
# ... shows line-by-line changes ...
# Stage one file
$ git add index.html
# Now diff shows nothing (already staged)
$ git diff
# Use --staged to see what's about to be committed
$ git diff --staged
# ... shows staged changes to index.html ...
# Decide to stage the rest
$ git add styles.css script.js
# Final review of everything staged
$ git diff --staged
# All looks good, commit
$ git commit -m "Redesign homepage layout"
Why this matters: git diff lets you review your work before making it permanent. Catch mistakes, verify logic, ensure you're committing what you intend.
Common Mistakes ⚠️
Mistake 1: Not Running git status Frequently
❌ Problem: Making changes without checking the current state, leading to accidental commits or confusion.
✅ Solution: Make git status a reflex. Run it before and after every command when learning. It's impossible to run it too much.
$ git status # Before making changes
$ # ... edit files ...
$ git status # After editing
$ git add .
$ git status # After staging
$ git commit -m "..."
$ git status # After committing
Mistake 2: Forgetting to Stage Changes Before Committing
❌ Problem: Editing files, running git commit, and wondering why changes didn't save.
$ echo "new content" > file.txt
$ git commit -m "Update file" # ❌ Nothing happens!
On branch main
Changes not staged for commit:
modified: file.txt
no changes added to commit
✅ Solution: Always git add before git commit, OR use git commit -a to auto-stage tracked files:
$ git add file.txt
$ git commit -m "Update file" # ✅ Works!
# Or in one step:
$ git commit -a -m "Update file" # ✅ Also works!
⚠️ Warning: git commit -a only stages modified tracked files. It won't add new untracked files.
Mistake 3: Vague Commit Messages
❌ Problem: Messages like "fix", "update", "changes" tell you nothing 6 months later.
$ git log --oneline
f1e2d3c fix # Fix what?
4c5b6a7 updates # What updates?
8e9f0a1 changes # What changed?
✅ Solution: Be specific. Future you will be grateful.
$ git log --oneline
f1e2d3c Fix null pointer exception in payment processor
4c5b6a7 Update user profile validation rules
8e9f0a1 Change header background to match brand colors
🧠 Memory Aid: Would you understand this message without any context in 6 months?
Mistake 4: Committing Secrets or Large Files
❌ Problem: Accidentally committing .env files with API keys or huge video files.
$ git add . # ❌ Added .env with secret keys!
$ git commit -m "Update config"
# Your secrets are now in permanent history!
✅ Solution: Create .gitignore as your FIRST commit:
# First thing in new project
$ git init
$ echo ".env" > .gitignore
$ echo "*.mp4" >> .gitignore
$ git add .gitignore
$ git commit -m "Add .gitignore"
# Now safe to add other files
$ git add .
💡 Pro Tip: If you accidentally commit secrets, you must rewrite history (advanced topic) or rotate those credentials immediately.
Mistake 5: Not Understanding What git add . Does
❌ Problem: Running git add . and staging files you didn't intend to commit (temp files, personal notes, etc.).
✅ Solution: Either:
- Run
git statusBEFOREgit add .to see what will be staged - Use
git addwith specific filenames for better control - Maintain a good
.gitignore
# Check what's changed first
$ git status
modified: index.html
modified: notes.txt (personal notes, don't want)
# Add selectively
$ git add index.html # ✅ Only what you want
# Or add to .gitignore
$ echo "notes.txt" >> .gitignore
Mistake 6: Confusing git diff and git diff --staged
❌ Problem: Running git diff after staging, seeing no output, thinking changes disappeared.
$ git add file.txt
$ git diff
# (no output) ← Changes are staged, not in working directory!
✅ Solution: Remember the two flavors:
git diff= working directory vs staging area (unstaged changes)git diff --staged= staging area vs last commit (staged changes)
$ git add file.txt
$ git diff # Shows nothing (no unstaged changes)
$ git diff --staged # ✅ Shows your staged changes
Key Takeaways 🎯
git initcreates a new repository;git clonecopies an existing oneThree-stage workflow is fundamental:
- Working Directory (your files)
- Staging Area (prepared changes)
- Repository (committed snapshots)
Daily command cycle:
edit → status → add → status → commit → loggit statusis your best friend—run it constantly to understand your current stategit addstages changes for commit (doesn't mean "add to Git")git commitcreates a permanent snapshot with a messagegit logshows commit history; use--onelinefor compact viewgit diffshows changes:- Plain
diff= unstaged changes diff --staged= staged changesdiff <commit1> <commit2>= between commits
- Plain
Good commit messages are specific and complete the sentence: "If applied, this commit will ___"
.gitignoreshould be your first commit—exclude generated files, dependencies, and secrets
🤔 Did You Know? Git was created by Linus Torvalds in 2005 out of frustration with existing version control systems. He built the core functionality in just a few days!
📋 Quick Reference Card
┌─────────────────────────────────────────────────────────────────┐
│ ESSENTIAL GIT COMMANDS │
├─────────────────────────────────────────────────────────────────┤
│ STARTING │
│ git init Create new repository in current dir │
│ git clone <url> Copy existing repository │
│ │
│ DAILY WORKFLOW │
│ git status Show working tree status ★ USE OFTEN │
│ git add <file> Stage specific file │
│ git add . Stage all changes in current directory │
│ git add -A Stage all changes in repository │
│ git commit -m "msg" Commit staged changes with message │
│ git commit -a -m "" Stage tracked files + commit │
│ │
│ VIEWING HISTORY │
│ git log Show commit history │
│ git log --oneline Compact one-line format │
│ git log --graph Visual branch diagram │
│ git log -<n> Show last n commits │
│ │
│ COMPARING │
│ git diff Unstaged changes (work vs staging) │
│ git diff --staged Staged changes (staging vs last commit) │
│ git diff <commit> Changes since commit │
│ │
│ THREE AREAS │
│ Working Directory → Staging Area → Repository │
│ (edit) (git add) (git commit) │
│ │
│ COMMIT MESSAGE TEMPLATE │
│ Short summary (50 chars) │
│ │
│ Longer explanation wrapped at 72 chars. │
│ - What and why, not how │
│ - Reference issues: Fixes #123 │
└─────────────────────────────────────────────────────────────────┘
📚 Further Study
Official Git Documentation - Basics: https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository Comprehensive guide to fundamental Git commands with detailed explanations.
GitHub's Git Handbook: https://guides.github.com/introduction/git-handbook/ Beginner-friendly overview of Git concepts and essential commands.
gitignore.io: https://www.toptal.com/developers/gitignore Generate
.gitignorefiles for any language, framework, or editor combination.
Next Lesson Preview: Now that you've mastered the daily workflow, we'll explore branches—Git's killer feature that lets you work on multiple features simultaneously without interference. You'll learn why "branching is cheap" and how to fearlessly experiment without breaking your main codebase. 🌿