Git logoGitv2.56BEGINNER

Git

Git cheat sheet with commands for branching, merging, rebasing, stashing, cherry-picking, and advanced version control techniques.

8 min read
gitversion-controlgithubcommandsworkflow
First page of the Git PDF cheat sheet

PDF · 2 pages

Git PDF cheat sheet

A two-page Git reference for printing or offline use.

Open PDF
Loading your progress

Setup

Install Git, verify the CLI, and set the identity used in commits.

Install Git on your platform and complete the first-time identity setup.

bash
# macOS
brew install git

# Windows
winget install --id Git.Git -e --source winget
📌 Your Git identity is stored in commit metadata
💡 Use repository-level config when a project needs another identity
🔍 git config --global --list shows the active global settings
⚠️ Do not put access tokens in Git configuration values
installconfigidentityversion

Getting Started

Initial Setup

Configure Git for first time use with your identity

bash
# Set user info (required for commits)
git config --global user.name "Your Name"
git config --global user.email "email@example.com"

# Set default branch name
git config --global init.defaultBranch main

# Check settings
git config --list
💡 --global applies to all your repos (~/.gitconfig)
📌 Local config overrides global settings
⚡ Set your editor for commit messages and conflicts
📌 Without init.defaultBranch, Git still uses master

Start a new project or get an existing one

bash
# Create new repository
git init
git init <directory>

# Clone existing repository
git clone <url>
git clone <url> <directory>

# Clone and check out a specific branch
git clone -b <branch> <url>
💡 Clone creates a full copy with history
⚡ Use shallow clone for faster downloads
📌 Init creates a new .git directory
📌 --depth implies --single-branch

.gitignore

Tell Git which files and directories to ignore

bash
# Create .gitignore in repo root
# Common patterns:
node_modules/
.env
.env.local
dist/
build/
*.log
.DS_Store
.vscode/
.idea/

# Stop tracking a file that's already committed
git rm --cached <file>
git rm -r --cached <directory>
💡 .gitignore only affects untracked files
⚠️ Already-tracked files keep being tracked — use git rm --cached to stop
✅ Use a global ignore for OS/editor junk (.DS_Store, .vscode/)
📌 Commit .gitignore so the whole team shares it

Making Changes

See what has changed in your working directory

bash
# Check status
git status
git status -s  # Short format

# View changes
git diff              # Unstaged changes
git diff --staged     # Staged changes
git diff HEAD         # All changes
git diff <branch>     # Compare with branch
💡 Status shows staged, modified, and untracked files
⚡ Use -s for compact status output
📌 Diff shows line-by-line changes
📌 Plain git diff skips staged changes; add --staged

Save your work to the repository history

bash
# Stage files
git add <file>
git add .              # All changes in current dir
git add -A             # All changes in whole repo
git add -p             # Interactive staging

# Commit
git commit -m "message"
git commit -am "message"  # Add + commit tracked files
git commit --amend       # Modify last commit
💡 Stage files before committing
⚠️ Amend rewrites history - don't amend pushed commits
✅ Write clear, descriptive commit messages
⚡ Use -p for selective staging

Branching

Create, list, and delete branches for parallel development

bash
# List branches
git branch            # Local
git branch -r         # Remote
git branch -a         # All

# Create and switch (modern, Git 2.23+)
git switch -c <name>
git switch <branch>

# Older equivalents
git checkout -b <name>
git checkout <branch>

# Delete branch
git branch -d <branch>  # Safe (merged only)
git branch -D <branch>  # Force delete
💡 git switch is the modern verb for branches (Git 2.23+)
⚠️ -D force-deletes unmerged branches
✅ Delete branches after merging
⚡ Use descriptive prefixes (feature/, fix/, chore/)

Merging

Combine changes from one branch into another

bash
# Merge a branch into current
git merge <branch>

# Common variants
git merge --no-ff <branch>     # Always create a merge commit
git merge --ff-only <branch>   # Fail if can't fast-forward
git merge --squash <branch>    # Squash into one commit (then commit)

# Bail out of a merge in progress
git merge --abort
💡 Fast-forward keeps history linear; --no-ff records the merge explicitly
⚡ Use --squash when you want a clean single-commit history
✅ Test after merging before pushing
🔧 --abort returns to the pre-merge state

Rebasing

Replay commits on top of another base for a linear history

bash
# Rebase current branch onto another
git rebase <branch>
git rebase main

# Interactive rebase (rewrite, reorder, squash)
git rebase -i HEAD~3

# Inside the interactive editor:
# pick    = keep commit
# reword  = change message
# edit    = stop to amend
# squash  = combine with previous (keep both messages)
# fixup   = combine with previous (drop this message)
# drop    = remove commit

# During a rebase
git rebase --continue   # After resolving conflicts
git rebase --skip       # Skip the current commit
git rebase --abort      # Cancel and reset
⚠️ Never rebase commits that are already pushed to a shared branch
💡 Rebase rewrites history; merge preserves it
✅ Use rebase locally to clean up before opening a PR
🔧 If you mess up, reflog has your back

Cherry-pick

Apply specific commits from another branch onto the current one

bash
# Apply a single commit
git cherry-pick <commit>

# Apply a range (exclusive..inclusive)
git cherry-pick <start>..<end>

# Apply without committing (stage only)
git cherry-pick -n <commit>

# After resolving conflicts
git cherry-pick --continue
git cherry-pick --abort
git cherry-pick --skip
💡 Cherry-pick copies a commit; it does not move it
⚡ Great for backporting fixes to release branches
⚠️ Creates a new commit with a different SHA than the source
✅ Use -x to leave a breadcrumb back to the original commit

Working with Remotes

Connect and sync with remote repositories

bash
# Show remotes
git remote
git remote -v

# Add remote
git remote add origin <url>

# Change remote URL
git remote set-url origin <new-url>

# Remove remote
git remote remove origin

# Rename remote
git remote rename origin upstream
💡 Origin is the default remote name
⚠️ Force push can overwrite others' work
✅ Use --force-with-lease for safer force pushing
⚡ Fetch updates remote tracking branches

Stashing Changes

Store uncommitted changes for later without committing

bash
# Stash changes
git stash
git stash push -m "description"

# View stashes
git stash list

# Apply stash
git stash apply         # Apply latest
git stash apply stash@{n}  # Apply specific
git stash pop           # Apply and delete

# Delete stash
git stash drop stash@{n}
git stash clear         # Delete all
💡 Stash is a stack - newest on top
⚡ Use stash to quickly switch branches
✅ Pop removes stash after applying
📌 Apply keeps stash for reuse

Fixing Mistakes

Undo Changes

Revert uncommitted changes in your working directory

bash
# Discard changes to a file (modern, Git 2.23+)
git restore <file>
git restore .             # All files

# Unstage a file (keep edits)
git restore --staged <file>

# Older equivalents
git checkout -- <file>
git reset HEAD <file>

# Nuke all local changes
git reset --hard HEAD
git clean -fd             # Remove untracked files/dirs
💡 git restore is the modern verb for files (Git 2.23+)
⚠️ --hard reset and clean -fdx are destructive — no undo
✅ Always git status first to confirm what you are discarding
📌 Soft reset keeps changes for recommit

Revert Commits

Undo committed changes by creating new commits

bash
# Revert a commit (safe — creates an inverse commit)
git revert <commit>
git revert HEAD          # Revert last commit

# Revert a range (exclusive..inclusive)
git revert <start>..<end>

# Revert a merge commit (-m 1 = keep first-parent line)
git revert -m 1 <merge-commit>

# Reset to a commit (⚠️ rewrites history)
git reset --hard <commit>
💡 Revert is safe for public/shared branches
⚠️ Reset rewrites history — avoid on shared branches
✅ For lost commits, see the Reflog item below
📌 For applying specific commits, see Cherry-pick under Branching

Find and recover commits that look "lost" after rewrites

bash
# Show the reflog (HEAD movement history)
git reflog
git reflog --all          # All refs, not just HEAD

# Entries look like:
# abc1234 HEAD@{0}: rebase (finish): returning to refs/heads/feature
# def5678 HEAD@{1}: rebase (pick): WIP fix
# 0123abc HEAD@{2}: rebase (start): checkout main

# Recover by SHA or HEAD@{n}
git reset --hard HEAD@{1}
git reset --hard <sha>

# Safer: branch off the recovered commit
git switch -c recovery HEAD@{1}
💡 Reflog records every HEAD movement — your safety net for rewrites
✅ Commits dropped by reset or rebase stay recoverable 30+ days
⚡ Use HEAD@{n} or time syntax (HEAD@{2.days.ago})
🔧 Branch off the recovered commit instead of reset --hard

Merge Conflicts

Handle and fix merge conflicts when combining branches

bash
# During merge conflict
git status              # See conflicted files

# Resolve conflicts manually, then:
git add <resolved-file>
git commit             # Complete merge

# Abort merge
git merge --abort

# Use specific version
git checkout --ours <file>    # Keep current branch
git checkout --theirs <file>  # Take other branch
💡 Conflicts show both versions in the file
✅ Always test after resolving conflicts
🔧 Use a merge tool for complex conflicts
⚡ --ours/--theirs for quick resolution

Viewing History

Log & History

Explore repository history and find specific commits

bash
# View log
git log
git log --oneline
git log --graph --all
git log -n 5           # Last 5 commits

# Search commits
git log --grep="keyword"
git log --author="name"
git log --since="2 weeks ago"

# File history
git log -- <file>
git log -p <file>      # With changes
git blame <file>       # Line-by-line authorship
💡 Use --graph for visual branch history
⚡ Combine flags for powerful searches
📌 Blame shows who changed each line
✅ Use shortlog for contribution summary

Tags & Releases

Version Tagging

Mark specific commits as releases or milestones

bash
# List tags
git tag
git tag -l "v1.*"     # Pattern matching

# Create tag
git tag v1.0.0
git tag -a v1.0.0 -m "Version 1.0.0"  # Annotated

# Tag specific commit
git tag v1.0.0 <commit>

# Push tags
git push origin v1.0.0
git push origin --tags

# Delete tag
git tag -d v1.0.0
git push origin --delete v1.0.0
💡 Use annotated tags for releases
✅ Follow semantic versioning (v1.2.3)
📌 Tags don't push by default
⚡ Lightweight tags for temporary marks

Advanced Techniques

Submodules

Include other Git repositories within your project

bash
# Add submodule
git submodule add <url> <path>

# Clone with submodules
git clone --recurse-submodules <url>

# Update submodules
git submodule update --init
git submodule update --remote
💡 Submodules link to specific commits
⚠️ Remember to update submodules after pull
📌 Each submodule is a separate repository
⚡ git config submodule.recurse true makes pull and switch update them

Binary search through history to find the commit that introduced a bug

bash
# Start bisect
git bisect start
git bisect bad          # Current commit is bad
git bisect good <commit>  # Known good commit

# Test each commit
git bisect good         # Mark as good
git bisect bad          # Mark as bad

# Finish
git bisect reset
💡 Finds bugs using binary search
⚡ Automate with test scripts
✅ Efficiently narrows down problem commits
📌 For bisect run: exit 0 = good, 125 = skip, 1-127 = bad

Worktrees

Work on multiple branches simultaneously in different directories

bash
# Add worktree
git worktree add <path> <branch>
git worktree add ../feature-branch feature

# List worktrees
git worktree list

# Remove worktree
git worktree remove <path>
💡 Each worktree is a separate working directory
⚡ Work on multiple branches without stashing
✅ Great for testing while developing
⚠️ A branch can be checked out in only one worktree at a time

Quick Reference

Daily Workflow

Common Git workflow for everyday development

bash
# Start your day
git pull origin main

# Create feature branch
git switch -c feature/new-feature

# Make changes
git add .
git commit -m "Add new feature"

# Push to remote
git push -u origin feature/new-feature

# Create pull request (on GitHub/GitLab)

# After PR merged
git switch main
git pull origin main
git branch -d feature/new-feature
💡 Always pull before starting new work
✅ Use descriptive branch names
⚡ Commit often with clear messages
📌 Delete branches after merging

Useful Aliases

Set up shortcuts for common Git commands

bash
# Set up aliases
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.last 'log -1 HEAD'
git config --global alias.unstage 'reset HEAD --'

# Advanced aliases
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
💡 Aliases save time on common commands
⚡ Create aliases for your workflow
✅ Share useful aliases with your team
📌 Global aliases are saved under [alias] in ~/.gitconfig