Git Commands Every Junior Developer Should Master
23/09/2025
|
9 mins to read
|
Share article
Introduction
When I started as a developer, I thought I knew Git. I could git add, git commit, and git push. But then came my first merge conflict, my first accidental commit to main, and my first "oh no, I need to undo that." Suddenly, basic Git wasn't enough.
This guide covers the Git commands that transformed me from a nervous beginner to a confident contributor. No fluff—just the commands you'll actually use in real projects.
Level 1: Beyond the Basics
The Commit Message That Matters
Bad habits I had to break:
# ❌ Don't do this
git commit -m "fixed stuff"
git commit -m "updates"
git commit -m "asdf"
What I learned to do:
# ✅ Good commit messages
git commit -m "fix: resolve null pointer in user login
- Add null check before accessing user.email property
- Add test case for login with missing email
- Fixes #247"
# Follow conventional commits
git commit -m "feat: add dark mode toggle to navigation"
git commit -m "refactor: simplify authentication logic"
git commit -m "docs: update API documentation for v2 endpoints"
git commit -m "test: add unit tests for payment validation"
Commit Message Template:
<type>: <short summary>
<optional body>
- Bullet point changes
- Be specific about what changed
<optional footer>
Fixes #issue-number
Checking Status and Differences
Commands I use every day:
# See what's changed
git status
# See what's different (before staging)
git diff
# See what's staged for commit
git diff --staged
# Compare branches
git diff main..feature-branch
# See changes in a specific file
git diff path/to/file.ts
Pro tip: Use git status -s for a cleaner, shorter output.
Level 2: Branching Like a Pro
Creating and Switching Branches
The evolution of my workflow:
# Old way (still works)
git branch feature-login
git checkout feature-login
# Better way
git checkout -b feature-login
# Modern way (Git 2.23+)
git switch -c feature-login
# Switch to existing branch
git switch main
Branch Management
# List all branches
git branch -a
# List remote branches only
git branch -r
# Delete a local branch
git branch -d feature-login
# Force delete (if not merged)
git branch -D feature-login
# Delete remote branch
git push origin --delete feature-login
# Rename current branch
git branch -m new-branch-name
My Branching Strategy:
# Feature development
git switch -c feature/user-authentication
# Bug fixes
git switch -c fix/login-validation-error
# Hotfix for production
git switch -c hotfix/security-patch
Level 3: Syncing with Remote
Fetch vs Pull (The Difference That Matters)
# Fetch: Download changes but don't merge
git fetch origin
# See what's new
git log HEAD..origin/main
# Pull: Fetch + Merge
git pull origin main
# Pull with rebase (cleaner history)
git pull --rebase origin main
When I use each:
git fetch: When I want to see what's changed before merginggit pull: When I'm ready to merge remote changesgit pull --rebase: When I want to keep my commits on top
Pushing with Confidence
# Push current branch
git push
# Set upstream and push
git push -u origin feature-login
# Force push (use with caution!)
git push --force-with-lease
# ⚠️ Never use on shared branches!
git push --force
Level 4: Undoing Mistakes (Lifesavers)
Unstaging Files
# Unstage a specific file
git restore --staged file.ts
# Unstage all files
git restore --staged .
# Old way (still works)
git reset HEAD file.ts
Discarding Changes
# Discard changes in a specific file
git restore file.ts
# Discard all changes (be careful!)
git restore .
# Old way
git checkout -- file.ts
Undoing Commits
# Undo last commit, keep changes staged
git reset --soft HEAD~1
# Undo last commit, keep changes unstaged
git reset HEAD~1
# Undo last commit, discard all changes ⚠️
git reset --hard HEAD~1
# Undo multiple commits
git reset --soft HEAD~3
Real scenario I faced:
# Oops, committed to main instead of a feature branch!
# 1. Create the feature branch (keeps the commits)
git branch feature-my-work
# 2. Reset main to match remote
git reset --hard origin/main
# 3. Switch to feature branch
git switch feature-my-work
# 4. Now your commits are safe on the feature branch!
The Magic of Revert
# Create a new commit that undoes changes
git revert abc123
# Revert multiple commits
git revert abc123 def456
# Revert without committing yet
git revert --no-commit abc123
When to use revert vs reset:
- Reset: For local commits not pushed yet
- Revert: For commits already pushed (safe for shared branches)
Level 5: Advanced Workflows
Stashing: Your Secret Weapon
Scenario: You're working on a feature, but need to quickly fix a bug on main.
# Save current work
git stash
# Or with a message
git stash save "WIP: user authentication form"
# List stashes
git stash list
# Apply most recent stash
git stash pop
# Apply specific stash
git stash apply stash@{1}
# Apply and keep in stash
git stash apply
# Delete stash
git stash drop stash@{0}
# Clear all stashes
git stash clear
My typical workflow:
# Working on feature-login
git stash save "half-done: login form validation"
# Switch to main and fix bug
git switch main
git pull
# ... make fixes ...
git commit -m "fix: critical security patch"
git push
# Back to feature
git switch feature-login
git stash pop
# Continue working
Interactive Rebase: Clean Up Your History
# Rebase last 3 commits
git rebase -i HEAD~3
# This opens an editor with:
# pick abc123 feat: add login form
# pick def456 fix: typo
# pick ghi789 feat: add validation
Available commands in interactive rebase:
# pick = use commit
# reword = change commit message
# edit = pause to amend commit
# squash = combine with previous commit
# fixup = like squash, but discard commit message
# drop = remove commit
Example: Cleaning up commits before a PR
pick abc123 feat: add login form
fixup def456 fix: typo in login form
fixup ghi789 fix: another small fix
reword jkl012 feat: add validation
# Results in 2 clean commits instead of 4 messy ones
Cherry-Picking Commits
# Apply a specific commit from another branch
git cherry-pick abc123
# Cherry-pick multiple commits
git cherry-pick abc123 def456
# Cherry-pick without committing
git cherry-pick --no-commit abc123
Use case:
# You made a hotfix on main that's also needed on develop
git switch develop
git cherry-pick <hotfix-commit-hash>
Level 6: Investigating History
Git Log: More Than You Think
# Basic log
git log
# One line per commit
git log --oneline
# Last 5 commits
git log -5
# Show commits with diffs
git log -p
# Graph view (amazing for branches)
git log --graph --oneline --all
# Commits by specific author
git log --author="Your Name"
# Commits in date range
git log --since="2 weeks ago"
# Search commit messages
git log --grep="login"
# See what changed in a file
git log -p path/to/file.ts
My favorite alias:
# Add to ~/.gitconfig
[alias]
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
# Then use: git lg
Git Blame: Find Who Changed What
# See who modified each line
git blame file.ts
# Blame for specific lines
git blame -L 10,20 file.ts
# Ignore whitespace changes
git blame -w file.ts
Git Show: Inspect Commits
# Show commit details
git show abc123
# Show changes in a commit
git show abc123 --stat
# Show specific file from a commit
git show abc123:path/to/file.ts
My Essential Git Aliases
Add these to ~/.gitconfig:
[alias]
# Short status
s = status -s
# Add all and commit
ac = !git add -A && git commit
# Commit with message
cm = commit -m
# Amend last commit
amend = commit --amend --no-edit
# Pretty log
lg = log --graph --oneline --decorate --all
# Undo last commit
undo = reset HEAD~1 --mixed
# List branches sorted by last modified
br = branch --sort=-committerdate
# Show current branch
current = branch --show-current
The Commands That Saved My Project
Scenario 1: Accidentally committed sensitive data
# Remove file from last commit
git rm --cached .env
git commit --amend --no-edit
# If already pushed (⚠️ rewrites history)
git push --force-with-lease
Scenario 2: Need to find when a bug was introduced
# Binary search through commits
git bisect start
git bisect bad # Current commit is bad
git bisect good abc123 # This commit was good
# Git checks out middle commit, test it
git bisect bad # or git bisect good
# Repeat until found
git bisect reset
Scenario 3: Lost commit after hard reset
# View all reference changes
git reflog
# Find your lost commit
git reflog show HEAD
# Restore it
git cherry-pick abc123
Best Practices I Live By
- Commit often, push daily - Small commits are easier to review and revert
- Never force push to shared branches - Use
--force-with-leaseif you must - Write meaningful commit messages - Your future self will thank you
- Keep main/develop protected - Always use feature branches
- Pull before you push - Avoid conflicts
- Review before you commit - Use
git diff --staged
Conclusion
Git is more than just version control—it's a time machine, a collaboration tool, and a safety net. Master these commands, and you'll spend less time fighting Git and more time building amazing things.
Start with the basics, practice regularly, and gradually add more commands to your toolkit.
The difference between a junior and senior developer isn't knowing every Git command—it's knowing which command to use when, and having the confidence to use it.
Happy coding! 🚀
Quick Reference Card
# Daily workflow
git status # Check status
git add . # Stage all changes
git commit -m "message" # Commit
git push # Push to remote
# Branching
git switch -c feature-name # Create new branch
git switch main # Switch branch
git branch -d feature-name # Delete branch
# Syncing
git pull # Update current branch
git fetch # Download updates
# Fixing mistakes
git restore file.ts # Discard changes
git reset HEAD~1 # Undo last commit
git stash # Save work for later
# History
git log --oneline # View commits
git diff # See changes