iZONE

Git Cheatsheet

A practical Git guide covering commits, branching, merging, rebasing, and workflows.

Resources

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 status

key 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 now

Starting 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 commit

git 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 everything

git 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 file

Searching 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 word

Branching

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 merged

git 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 merge

git 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 branches

Never 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 remote

git 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 -f

git 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 main

Undoing & 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 everything

git 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 mind

git 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/main

Only 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 GitHub

Tags 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 --abort

git 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 done

git 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 pushing

Config & 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 ~/.gitconfig

useful 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 auto

git 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 staged

Add 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-auth

keeping 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 main

GitHub 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 PR

Tips & 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~3

never 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 HEAD

Rewriting 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.git

handy 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.ts

Troubleshooting 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 stuck

detached 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 commit

undo 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 -f
Was this helpful?

No login required to share feedback

More Cheatsheets

Keep your reference handy

Explore more zero-to-hero cheatsheets for the tools you use daily.