Git Commands I Wish I Knew Earlier
These git commands save me time every single day. Learn them now, thank me later.
The Basics Everyone Knows
git init # Initialize repo
git add . # Stage changes
git commit -m "msg" # Commit
git push # Push to remote
git pull # Pull from remote
git status # Check status
git diff # See unstaged changes
git log # View history
The Commands That Actually Matter
Viewing History (Better Ways)
# Pretty log (my favorite)
git log --oneline --graph --all --decorate
# * a1b2c3d (HEAD -> main) Add feature X
# * e4f5g6h Fix bug Y
# | * i7j8k9l (origin/feature) Feature branch work
# Log with stats (what changed)
git log --stat
# Log for specific file
git log --follow -p src/utils.js # + show actual diffs!
# Who changed this line?
git blame src/utils.js # Line-by-line authorship
# Search commits by message
git log --grep="bug fix" # Commits with "bug fix" in message
git log --grep="auth" --oneline # Quick list
# Search commits by code change
git log -S "functionName" --oneline # Commits that added/removed "functionName"
git log -G "pattern" --oneline # Commits where regex matches diff
# Show commit details
git show a1b2c3d # Full diff of one commit
git show a1b2c3d --stat # Just file summary
Stashing (Save Work Temporarily)
# Save current uncommitted work
git stash push -m "WIP: feature X"
# List stashes
git stash list
# stash@{0}: On main: WIP: feature X
# stash@{1}: On main: WIP: other thing
# Restore stash (removes it from list)
git stash pop # Apply + remove most recent
git stash apply # Apply but keep in list
# Apply specific stash
git stash apply stash@{1}
# Drop a stash (discard)
git stash drop stash@{0}
# Clear all stashes
git stash clear
# Stash with untracked files too
git stash push -u -m "WIP including new files"
# Stash specific files only
git stash push -m "just utils" src/utils.js
Interactive Staging
# Stage parts of a file (NOT the whole file!)
git add -p
# Stage this hunk [y,n,q,a,d,e,?]?
# y = yes, stage this hunk
# n = no, skip this hunk
# q = quit, done staging
# a = stage this and all remaining
# d = don't stage this or any remaining
# e = edit this hunk manually
# ? = help
# Reset parts of a file (unstage specific hunks)
git reset -p
# Commit with interactive staging
git commit -p # Combines add -p + commit
Undoing Mistakes
# Undo last commit (keep changes staged)
git reset --soft HEAD~1
# Undo last commit (keep changes UNSTAGED)
git reset HEAD~1
# Undo last commit AND discard changes (DANGEROUS!)
git reset --hard HEAD~1
# Unstage a file (keep changes)
git reset HEAD path/to/file
# Discard all changes to a file (go back to last commit)
git checkout -- path/to/file
# Or newer:
git restore path/to/file
# Discard ALL uncommitted changes
git restore .
# Or dangerous:
git checkout -- .
# Fix the last commit message (if not pushed yet)
git commit --amend -m "New message"
# Fix something you forgot in the last commit
git add forgotten-file.js
git commit --amend --no-edit # Keeps same message, adds new file
Branching Done Right
# Create and switch to new branch
git checkout -b feature/new-feature
# Or modern equivalent:
git switch -c feature/new-feature
# List branches (local + remote)
git branch -a
# * main
# feature/new-feature
# remotes/origin/main
# remotes/origin/feature/other
# Rename branch
git branch -m old-name new-name
# Delete local branch (must not be on it)
git branch -d feature/done # Safe (checks if merged)
git branch -D feature/abandoned # Force delete
# Delete remote branch
git push origin --delete feature/done
# Compare branches
git diff main...feature // What changed between main and feature?
git log main..feature // Commits in feature that aren't in main
git log main..feature --oneline
# Merge vs Rebase
git merge feature-branch // Merge commit (preserves history)
git rebase main // Linear history (rewrites commits)
# When to use which:
# Merge: Shared branches (main, develop) — preserves public history
# Rebase: Local feature branches before merging — clean linear history
Cherry-Picking
# Apply one commit from another branch
git cherry-pick a1b2c3d
# Cherry-pick without committing (edit first)
git cherry-pick -n a1b2c3d
# Make changes...
git cherry-pick --continue
# Cherry-pick multiple commits
git cherry-pick a1b2c3d e4f5g6h i7j8k9l
# If conflict occurs:
# 1. Resolve conflicts in files
# 2. git add <resolved-files>
# 3. git cherry-pick --continue
# Or abort: git cherry-pick --abort
Bisect (Find Which Commit Broke Something)
# Start bisect (when did this bug appear?)
git bisect start
git bisect bad # Current version has the bug
git bisect good v1.0.0 # This version was fine
# Git will check out a middle commit
# You test it:
# git bisect good # This version is fine → bug is after this
# git bisect bad # This version has bug → bug is before this
# Repeat until git finds the exact commit!
# Then:
git bisect reset # Exit bisect mode
Cleaning Up
# Remove untracked files (dry run first!)
git clean -nd # n=dry-run, d=show-directories
git clean -fd # f=force remove files+dirs
# Remove ignored files too
git clean -fdx # x=remove ignored files
# Prune merged local branches
git branch --merged main | grep -v '^\*' | xargs git branch -d
# Garbage collection (clean up orphaned objects)
git gc # Full garbage collection
git prune # Remove unreachable objects
# Large file storage (LFS for big repos)
git lfs install # Initialize LFS
git lfs track "*.psd" # Track PSD files via LFS
git add .gitattributes
Aliases I Use Daily
[alias]
co = checkout
br = branch
ci = commit
st = status -sb
lg = log --oneline --graph --all --decorate -15
unstage = reset HEAD --
amend = commit --amend --no-edit
recent = log --oneline -10
save = !git add -A && git commit -m \"WIP: $(date +%s)\"
prune = !git branch --merged main | grep -v '\\*\\|main' | xargs git branch -d
diffc = diff --cached
rbc = rebase --continue
aba = bisect abort
My Workflow Example
# Start new work
git co main && git pull origin main
git co -b feature/user-auth
# ... write code ...
git add -p # Review each change
git ci -m "feat(auth): add login form"
# ... more code ...
git add src/auth/login.test.ts
git ci -m "test(auth): add login form tests"
# Sync before pushing
git fetch origin
git rebase origin/main # Clean history
# Push
git push -u origin feature/user-auth
# After PR merge:
git co main && git pull
git br -d feature/user-auth
git push origin --delete feature/user-auth
Which git command changed your life?
Follow @armorbreak for more developer content.
Top comments (0)