The commands you reach for every day — and the ones you Google every time. This reference covers everything from first-time setup to advanced undo operations.
Quick reference
The 20 commands that cover 90% of daily work.
| Command | What it does |
|---|---|
git init |
Create a new local repo |
git clone <url> |
Clone a remote repo |
git status |
Show working tree status |
git add <file> |
Stage a file |
git add . |
Stage all changes |
git commit -m "msg" |
Commit staged changes |
git push |
Push to remote |
git pull |
Fetch + merge from remote |
git branch |
List local branches |
git branch <name> |
Create a branch |
git checkout <branch> |
Switch branch |
git checkout -b <name> |
Create and switch branch |
git merge <branch> |
Merge branch into current |
git log --oneline |
Compact commit history |
git diff |
Show unstaged changes |
git diff --staged |
Show staged changes |
git stash |
Stash working changes |
git stash pop |
Restore last stash |
git reset HEAD~1 |
Undo last commit (keep changes) |
git revert <hash> |
Create undo commit |
Setup
Configure Git before your first commit.
# Identity (stored in ~/.gitconfig)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Default branch name
git config --global init.defaultBranch main
# Editor for commit messages
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim" # Vim
# View all config
git config --list
# View one setting
git config user.name
Starting a repo
# New repo from scratch
git init
git init my-project # Creates and enters folder
# Clone existing
git clone https://github.com/user/repo.git
git clone https://github.com/user/repo.git my-folder # Into specific folder
git clone --depth 1 https://github.com/user/repo.git # Shallow clone (faster)
Staging and committing
# Stage files
git add file.txt # Stage one file
git add src/ # Stage a directory
git add . # Stage everything
git add -p # Stage interactively (chunk by chunk)
# Commit
git commit -m "feat: add login page"
git commit -am "fix: typo" # Stage + commit tracked files
git commit --amend -m "new message" # Fix last commit message (before push)
git commit --amend --no-edit # Add staged changes to last commit
# Status and diff
git status
git status -s # Short format
git diff # Unstaged changes
git diff --staged # Staged changes
git diff HEAD # All changes since last commit
git diff main..feature # Diff between branches
Branches
# List
git branch # Local branches
git branch -r # Remote branches
git branch -a # All branches
# Create and switch
git branch feature-login # Create
git checkout feature-login # Switch
git checkout -b feature-login # Create + switch (old style)
git switch -c feature-login # Create + switch (modern)
git switch main # Switch (modern)
# Rename
git branch -m old-name new-name
# Delete
git branch -d feature-login # Safe delete (merged only)
git branch -D feature-login # Force delete
# Track remote branch
git checkout --track origin/feature-login
Merging
# Merge branch into current
git merge feature-login
# Merge with a commit even if fast-forward is possible
git merge --no-ff feature-login
# Abort a merge in progress
git merge --abort
# After resolving conflicts manually
git add resolved-file.txt
git commit
Merge conflict markers look like this:
<<<<<<< HEAD
Your changes here
=======
Their changes here
>>>>>>> feature-login
Edit the file to keep what you want, then remove the markers, stage, and commit.
Rebasing
# Rebase current branch onto main
git rebase main
# Interactive rebase — rewrite last 3 commits
git rebase -i HEAD~3
# During interactive rebase, options per commit:
# pick = keep as-is
# reword = change message
# edit = pause to amend
# squash = meld into previous commit
# drop = delete commit
# Abort a rebase in progress
git rebase --abort
# Continue after resolving conflicts
git rebase --continue
Rule of thumb: never rebase commits that are already pushed to a shared branch.
Remote
# View remotes
git remote -v
# Add remote
git remote add origin https://github.com/user/repo.git
# Change remote URL
git remote set-url origin https://github.com/user/new-repo.git
# Remove remote
git remote remove origin
# Fetch (download but don't merge)
git fetch
git fetch origin main
# Pull (fetch + merge)
git pull
git pull origin main
git pull --rebase # Pull with rebase instead of merge
# Push
git push
git push origin main
git push -u origin main # Push + set upstream (first time)
git push --force-with-lease # Force push safely (checks for remote changes)
git push origin --delete feature-login # Delete remote branch
Stash
# Save work in progress
git stash
git stash push -m "work in progress: login form" # Named stash
# List stashes
git stash list
# Apply stash
git stash pop # Apply and remove top stash
git stash apply stash@{1} # Apply specific stash (keep it)
# Drop stash
git stash drop stash@{0}
git stash clear # Delete all stashes
# Stash including untracked files
git stash push -u
Log and history
# Basic log
git log
git log --oneline # Compact — one line per commit
git log --oneline --graph --decorate --all # Visual branch graph
# Filter
git log --author="Name"
git log --since="2024-01-01" --until="2024-12-31"
git log --grep="fix:" # By commit message
git log -p # Show diffs
git log -n 10 # Last 10 commits
# File history
git log -- path/to/file.txt
git log --follow -- path/to/file.txt # Track file renames
# Who changed what line
git blame file.txt
git blame -L 10,25 file.txt # Lines 10–25 only
# Show a commit
git show abc1234
git show HEAD~2 # Two commits back
Undo operations
The most important table to understand:
| Scenario | Command | Keeps changes? |
|---|---|---|
| Unstage a file | git restore --staged file.txt |
Yes |
| Discard working changes | git restore file.txt |
No — permanent |
| Undo last commit | git reset HEAD~1 |
Yes (staged) |
| Undo last commit + unstage | git reset --mixed HEAD~1 |
Yes (unstaged) |
| Undo last commit + discard | git reset --hard HEAD~1 |
No — permanent |
| Revert a pushed commit | git revert <hash> |
N/A (new commit) |
# Discard unstaged changes
git restore file.txt # One file
git restore . # Everything
# Unstage
git restore --staged file.txt
# Undo commits
git reset HEAD~1 # Soft by default: keeps staged
git reset --hard HEAD~1 # Discards changes — use carefully
# Safe undo for pushed commits
git revert abc1234 # Creates a new "undo" commit
git revert HEAD~3..HEAD # Revert last 3 commits
# Recover a deleted branch
git reflog # Find the hash
git checkout -b recovered abc1234
Tags
# Create
git tag v1.0.0
git tag -a v1.0.0 -m "Release 1.0.0" # Annotated tag
# List
git tag
git tag -l "v1.*"
# Push tags
git push origin v1.0.0
git push origin --tags # Push all tags
# Delete
git tag -d v1.0.0
git push origin --delete v1.0.0
.gitignore
# Files
.env
.env.local
# Directories
node_modules/
dist/
.next/
__pycache__/
# Extensions
*.log
*.tmp
*.DS_Store
# Negation (force-include a file in an ignored dir)
!important.log
# Apply .gitignore to already-tracked files
git rm -r --cached .
git add .
git commit -m "chore: apply .gitignore"
6 common mistakes
1. Committed to the wrong branch
git log --oneline -1 # Note the commit hash
git reset HEAD~1 # Undo commit on wrong branch
git stash
git checkout correct-branch
git stash pop
git commit -m "..."
2. Accidentally staged a secret
git restore --staged .env # Unstage before committing
If already committed, rotate the secret immediately — it is in your history.
3. Force push overwrote a teammate's work
Use --force-with-lease instead of --force. It aborts if the remote has commits you haven't fetched.
git push --force-with-lease
4. Lost commits after reset --hard
git reflog keeps a log of where HEAD has been for ~30 days.
git reflog
git checkout -b recovery abc1234
5. Merge conflicts on every pull
Switch to rebase-on-pull to keep history linear:
git config --global pull.rebase true
6. Huge file committed by accident
Remove it from history with git filter-repo (the maintained replacement for filter-branch):
pip install git-filter-repo
git filter-repo --path huge-file.zip --invert-paths
6 frequently asked questions
What is the difference between fetch and pull?
fetch downloads commits from the remote but doesn't touch your working directory. pull is fetch + merge (or fetch + rebase with pull.rebase true). Use fetch when you want to inspect remote changes before integrating them.
When should I rebase vs merge?
Rebase for local/feature branches to keep history linear and clean before merging into main. Merge for integrating finished branches where preserving the merge point matters. Never rebase shared branches.
What does HEAD mean?
HEAD is a pointer to your current commit — usually the tip of the checked-out branch. HEAD~1 is one commit back, HEAD~2 is two back. HEAD^ is the first parent (same as HEAD~1).
How do I undo a commit that is already pushed?
Use git revert <hash>. This creates a new commit that undoes the changes without rewriting history, which is safe for shared branches. Reserve git reset --hard + force push for branches only you use.
How do I see what changed in a commit?
git show abc1234
git show HEAD # Latest commit
git show HEAD --stat # File list only
What is git stash and when should I use it?
Stash temporarily shelves changes you're not ready to commit. Use it when you need to switch branches mid-task, pull updates, or run a quick hotfix without losing your current work.