Jump to section
Git Cheatsheet
A practical Git guide covering commits, branching, merging, rebasing, and workflows.
What is Git?
Git is a tool that tracks every change you make to your files so you can go back in time, work on multiple things at once, and collaborate without overwriting each other.
the three areas — where your code lives
Bash
# the flow:
# Edit files → git add → git commit
# (Working) (Staging) (Repository)
# check what Git sees — safe, never changes anything
git statuskey words you'll see constantly
Bash
# repository (repo) — the .git folder, stores all history
# commit — a saved snapshot at one moment in time
# branch — a separate line of work
# staging area — where you decide what goes into the next commit
# remote — a copy of your repo hosted online (e.g. GitHub)
# HEAD — a pointer to where you are right nowStarting a Repository
Two ways to start: create a new repo from scratch, or copy an existing one from GitHub.
git init and git clone
Bash
# git init — new project
git init
# turn current folder into a repo
git init my-project
# create a new folder AND make it a repo
git status
# always safe — only shows info
# git clone — existing project
git clone https://github.com/user/repo.git
# custom folder name
git clone https://github.com/user/repo.git my-folder
# SSH — faster, no password prompts
git clone git@github.com:user/repo.git.gitignore — tell Git what to ignore
Bash
# create .gitignore in your project root
node_modules/ # dependencies — re-installable
dist/ # build output — re-generatable
build/
.env # secrets — NEVER commit these
.env.local
.DS_Store # macOS system files
Thumbs.db # Windows system files
.vscode/ # editor settings
.idea/
# stop tracking a file you already committed
git rm --cached .env
git rm --cached -r node_modules/
git commit -m "chore: stop tracking .env"If you accidentally commit a secret (.env, API key), treat it as compromised — change the key immediately. Removing it from Git does not erase it from history.
Core Workflow
The daily Git loop: check what changed → stage what you want to save → commit the snapshot. These three commands are 80% of everyday Git.
git status and git diff
Bash
# git status
git status
# full view — staged, changed, and untracked files
git status -s
# short view — one line per file
# M = modified, A = staged, ? = new untracked
# git diff
git diff
# changes you HAVEN'T staged yet
git diff --staged
# changes you HAVE staged (what will be committed)
git diff HEAD
# ALL changes since last commitgit add — choose what to save
Bash
git add file.txt # stage one file
git add src/ # stage everything in a folder
git add . # stage everything in current directory
git add *.js # stage all .js files
# changed your mind? unstage (edits are kept)
git restore --staged file.txt
git restore --staged . # unstage everythinggit commit — save the snapshot
Bash
git commit -m "feat: add login page"
# stage ALL tracked files and commit in one step
git commit -am "fix: correct typo in header"
# fix the last commit before pushing
git commit --amend -m "fix: corrected message"
# ✅ good — clear and specific
git commit -m "feat: add dark mode toggle"
git commit -m "fix: stop form submitting when fields are empty"
git commit -m "docs: add examples to README"
# ❌ bad — tells you nothing
git commit -m "fix"
git commit -m "stuff"Never write vague messages like 'fix', 'stuff', or 'WIP' on shared branches. Write what changed and why.
git log — look back at history
Bash
git log
# full history with details
git log --oneline
# compact — one line per commit
git log --oneline --graph
# ASCII diagram showing branches
git log --oneline -10
# last 10 commits only
git log --author="Alice"
# commits by one person
git log --grep="login"
# commits whose message contains 'login'
git log -- src/auth.ts
# commits that touched one specific fileSearching History
Git can search through your entire project history — across files, commit messages, and code changes — in milliseconds.
git grep and log search
Bash
# git grep — search inside tracked files
git grep "TODO"
# find every TODO in the project
git grep -n "TODO"
# show line numbers
git grep -i "todo"
# case insensitive
git grep -l "TODO"
# list file names only
# search commit history
git log -S "passwordHash" --oneline
# commits that added or removed this text
git log -- src/auth.ts --oneline
# commits that touched one specific file
git log --author="Alice" --since="2024-01-01" --oneline
# by author and time period
git log --grep="login" --oneline
# message contains a wordBranching
A branch is a separate line of work. Create one for every feature or fix so your main branch stays clean and working.
create and switch branches
Bash
git branch
# list local branches (* = current)
git branch -a
# list ALL branches (local + remote)
# ✅ create AND move in one step
git switch -c feature-login
git switch main
# go back to main
git switch -
# go back to the previous branch
# delete a branch (once its work is merged)
git branch -d feature-login
# safe — refuses if not merged
git branch -D feature-login
# force — even if not mergedgit merge
Bash
# step 1: go to the branch to merge INTO
git switch main
# step 2: merge the feature branch
git merge feature-login
# conflict markers look like this:
# <<<<<<< HEAD
# your current version
# =======
# incoming version from other branch
# >>>>>>> feature-login
# fix it:
# 1. Edit the file — keep what you want, delete markers
# 2. Save the file
git add file.txt # mark conflict as resolved
git commit # complete the merge
git merge --abort # cancel the whole mergegit rebase
Bash
# you're on feature-login, main has moved ahead
git switch feature-login
git rebase main
# puts your commits AFTER the latest main commits
# if conflicts happen during rebase:
# 1. fix the conflict in your editor
# 2. git add <fixed-file>
git rebase --continue
git rebase --abort
# cancel — go back to before the rebase
# ✅ safe to rebase: your own private branch
# ❌ never rebase: main, develop, shared branchesNever rebase main, develop, or any branch others have pulled. Only rebase your own private feature branches.
Remotes — GitHub & Beyond
A remote is a copy of your repo hosted online. 'origin' is the conventional name for it. Push to share your work — pull to get others' work.
manage remotes
Bash
git remote -v
# list remotes and their URLs
git remote add origin https://github.com/user/repo.git
# add a remote
# change URL (e.g. switch from HTTPS to SSH)
git remote set-url origin git@github.com:user/repo.git
git remote remove origin
# remove a remotegit push — send commits to GitHub
Bash
# first push — -u links branch to remote
git push -u origin main
# every push after that
git push
# push a specific branch
git push origin feature-login
# delete a branch on the remote
git push origin --delete feature-login
# force push — ONLY on your own private branches
git push --force-with-lease
# safer than -fgit fetch and git pull
Bash
# fetch — download but don't apply yet
git fetch origin
# see what's waiting before applying
git log origin/main --oneline
# pull — download AND apply
git pull
# pull with rebase — cleaner history
git pull --rebase origin mainUndoing & Fixing Mistakes
Git almost never permanently deletes anything. Almost every mistake has a clean recovery path — the right command depends on what stage the mistake is at.
discard and unstage changes
Bash
# discard changes — cannot be undone
git restore file.txt
# throw away changes in one file
git restore .
# throw away ALL unsaved changes
# remove new untracked files
git clean -fdn
# dry run first — preview what would be deleted
git clean -fd
# -f = force, -d = include folders
# unstage — edits are kept, this is safe
git restore --staged file.txt
git restore --staged . # unstage everythinggit revert — safely undo a pushed commit
Bash
# undo the most recent commit
git revert HEAD
# creates a new 'undo' commit
# undo a specific older commit
git revert a3f8c2d
# preview the reversal without committing yet
git revert HEAD --no-commit
git revert --continue # commit after reviewing
git revert --abort # cancel if you changed your mindgit reset — move the branch pointer backward
Bash
# --soft: undo commit, keep changes staged
git reset --soft HEAD~1
# HEAD~1 = one commit back
# --mixed (default): undo commit, unstage changes
git reset HEAD~1
# --hard: undo commit AND discard all changes
git reset --hard HEAD~1
# match your local branch exactly to remote
git reset --hard origin/mainOnly use `git reset` on commits you haven't pushed yet. Use `git revert` for anything already on GitHub.
git reflog — your ultimate safety net
Bash
git reflog
# output:
# a3f8c2d HEAD@{0}: commit: feat: add dark mode
# 9b12e1f HEAD@{1}: reset: moving to HEAD~1
# 7c4da3a HEAD@{2}: commit: fix: header typo
# recover after a bad reset
git reset --hard HEAD@{2}
# save recovered commits in a new branch
git switch -c recovery-branch HEAD@{2}Stashing
Stash saves your unfinished work to a temporary pocket so you can switch branches or pull updates — then bring it back later.
save and restore a stash
Bash
git stash
# save current work-in-progress
git stash push -m "WIP: login form"
# save with a descriptive name
git stash list
# see all your stashes
git stash pop
# restore latest stash AND remove it
git stash apply stash@{1}
# restore a specific stash, keep in list
git stash drop stash@{0}
# delete one stash
git stash clear
# delete ALL stashes
# preview without applying
git stash show stash@{0} -p
# create a branch from a stash
git stash branch feature-wip stash@{0}stash specific files
Bash
# stash one specific file
git stash push -m "WIP: auth only" src/auth.ts
# stash multiple specific files
git stash push -m "WIP: two files" src/auth.ts src/api.ts
# include new untracked files too
git stash push -u -m "WIP: new file" src/newfeature.ts
# stash everything EXCEPT one file
# (stage what you want to keep, stash the rest)
git add src/keep-this.ts
git stash push --keep-index -m "WIP: everything else"Tagging
Tags mark important points in history — like release versions. Unlike branches, tags don't move when you make new commits.
create and push tags
Bash
# annotated tag — recommended for releases
git tag -a v1.0.0 -m "Release version 1.0.0"
# lightweight tag — just a bookmark
git tag v1.0.0-beta
# tag an older commit by hash
git tag -a v0.9.0 -m "Beta release" a3f8c2d
# list all tags
git tag
git tag -l "v1.*" # filter — only v1.x tags
# push tags — not pushed automatically!
git push origin v1.0.0 # push one tag
git push origin --tags # push all tags
# delete a tag
git tag -d v1.0.0-beta
# delete locally
git push origin --delete v1.0.0-beta
# delete on GitHubTags are NOT pushed automatically with `git push` — push them separately with `git push origin --tags`.
Advanced Commands
These commands solve specific problems that come up regularly. Each one is powerful — understand what it does before running it.
git cherry-pick — copy one commit to another branch
Bash
# apply one specific commit to your current branch
git cherry-pick a3f8c2d
# apply it but don't commit yet — review first
git cherry-pick a3f8c2d --no-commit
# cancel if something went wrong
git cherry-pick --abortgit bisect — find which commit introduced a bug
Bash
git bisect start
git bisect bad # current commit HAS the bug
git bisect good v1.0.0 # this version was fine
# Git checks out a middle commit — test your app, then:
git bisect bad # this commit has the bug
git bisect good # this commit is fine
# Git keeps narrowing until it finds the culprit
git bisect reset
# go back to where you started when donegit blame and interactive rebase
Bash
# git blame — who wrote each line
git blame src/auth.ts
git blame -L 10,25 src/auth.ts
# only look at lines 10 to 25
# interactive rebase — rewrite recent commits
git rebase -i HEAD~3
# rewrite the last 3 commits
# Git opens an editor — choose what to do:
# pick = keep as-is
# reword = keep commit, edit message
# squash = combine with the commit above
# fixup = combine, discard this message
# drop = delete this commit entirely
# common use: squash WIP commits into one
# clean commit before pushingConfig & Aliases
Aliases are shortcuts for commands you type dozens of times a day. Set them once and save hours over time.
first-time setup
Bash
# set your name and email — used in every commit
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
# set default branch name to 'main'
git config --global init.defaultBranch main
# check your current settings
git config --global --list
# open your config file directly
cat ~/.gitconfiguseful global settings
Bash
# cleaner history when pulling
git config --global pull.rebase true
# shows all three versions in merge conflicts
git config --global merge.conflictstyle diff3
# auto-correct typos in commands
git config --global help.autocorrect 3
# colourful output
git config --global color.ui autogit aliases — type less, do more
Bash
git config --global alias.st "status -s"
git config --global alias.co "switch"
git config --global alias.cb "switch -c"
git config --global alias.br "branch -vv"
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.last "log -1 HEAD --stat"
git config --global alias.undo "reset --soft HEAD~1"
git config --global alias.unstage "restore --staged"
# now you can type:
git st # short status
git co main # switch to main
git cb feat # create and switch to feat
git lg # visual history of all branches
git undo # undo last commit, keep changes stagedAdd these aliases once and they work in every project on your machine forever.
GitHub Workflow
The standard team flow: create a branch → do your work → open a Pull Request → get it reviewed → merge it in.
feature branch workflow
Bash
# 1. start from an up-to-date main
git switch main
git pull
# 2. create a branch for your work
git switch -c feat/user-auth
# 3. do your work, commit in small steps
git add .
git commit -m "feat: add login form"
git commit -m "feat: add auth validation"
# 4. keep your branch updated as main moves forward
git fetch origin
git rebase origin/main
# 5. push and open a PR on GitHub
git push -u origin feat/user-auth
# 6. after the PR is merged, clean up
git switch main
git pull
git branch -d feat/user-authkeeping a fork in sync
Bash
# one-time setup: add the original repo as 'upstream'
git remote add upstream https://github.com/original/repo.git
# pull in the latest from the original
git fetch upstream
git switch main
git rebase upstream/main
# push the updated main to YOUR fork
git push origin mainGitHub CLI — manage GitHub from your terminal
Bash
# install
brew install gh # macOS
winget install GitHub.cli # Windows
gh auth login # log in to GitHub
# create a PR from your current branch
gh pr create --title "feat: add login" --body "Closes #42"
gh pr list # see all open PRs
gh pr checkout 42 # check out someone else's PR locally
gh pr merge 42 --squash # merge a PRTips & Good Habits
Hard-won lessons that make Git a pleasure instead of a pain. These are the habits that separate experienced developers from beginners.
commit small and often
Bash
# ❌ bad — one giant commit does too many things
git commit -m "add login, fix header, update styles, refactor API"
# ✅ good — three focused commits
git commit -m "feat: add login page"
git commit -m "fix: correct header padding on mobile"
git commit -m "refactor: move API calls into service layer"
# WIP commits are fine locally
git commit -m "WIP: login form in progress"
# squash before pushing
git rebase -i HEAD~3never do these on shared branches
Bash
# ❌ never force push to main
git push -f origin main
# ❌ never rebase a shared branch
git switch main
git rebase feature
# ❌ never reset --hard on pushed commits
git reset --hard HEAD~3
# ✅ use revert instead — safe for everyone
git revert HEADRewriting history that others have already pulled breaks their local repos and causes painful conflicts for everyone on the team.
SSH setup — stop typing your password
Bash
# 1. generate an SSH key
ssh-keygen -t ed25519 -C "[email protected]"
# press Enter to accept the default location
# 2. copy your public key
cat ~/.ssh/id_ed25519.pub
# copy the output
# 3. add it to GitHub:
# Settings → SSH and GPG keys → New SSH key → Paste
# 4. test it works
ssh -T git@github.com
# "Hi username! You've successfully authenticated."
# 5. use SSH URLs going forward
git clone git@github.com:user/repo.githandy one-liners worth bookmarking
Bash
# visual diagram of all branches
git log --all --oneline --graph --decorate
# show what files changed in the last commit
git show --stat HEAD
# rename a branch
git branch -m old-name new-name
# see what changed between two release tags
git log v1.0.0..v1.1.0 --oneline
# count commits per author
git shortlog -sn
# export a file from another branch without switching
git show main:src/config.ts > config-backup.tsTroubleshooting Common Problems
Every Git user hits these problems. Here are the fast, clean solutions.
merge conflicts — how to fix them step by step
Bash
# Git marks the conflict like this:
# <<<<<<< HEAD
# your version of the line
# =======
# the incoming version
# >>>>>>> feature-login
# fix it:
# 1. open the file — choose what to keep
# 2. delete ALL marker lines: <<<, ===, >>>
# 3. save the file
git add file.txt # mark conflict as resolved
git commit # complete the merge
git merge --abort # cancel the whole merge if stuckdetached HEAD, wrong branch, and deleted branch
Bash
# detached HEAD — git status shows "HEAD detached at a3f8c2d"
# option 1: just go back to your branch
git switch main
# option 2: you made commits you want to keep
git switch -c my-new-branch
# creates a branch at your current position
# accidentally committed to main
git branch feat/my-feature
# create branch at current position
git reset --hard origin/main
# reset main back to remote
git switch feat/my-feature
# ⚠️ only works if you haven't pushed yet
# recover a deleted branch
git reflog
# find the last commit hash of the deleted branch
git switch -c recovered a3f8c2d
# recreate the branch at that commitundo a commit that's already on GitHub
Bash
# ✅ safe — creates a new commit that undoes the mistake
git revert HEAD
# undo the most recent pushed commit
git push
# push the undo commit to GitHub
# undo a specific older commit
git revert a3f8c2d
git push
# ❌ never do this on a shared branch
# git reset --hard HEAD~1
# git push -fNo login required to share feedback
More Cheatsheets
Keep your reference handy
Explore more zero-to-hero cheatsheets for the tools you use daily.