🔧 Git

← Back to Cheatsheets

A quick-reference for Git version control. Git tracks changes as a directed acyclic graph of commits; each commit is a snapshot, not a diff. The working tree, staging area (index), and repository are the three layers you move changes through.

Type: Distributed Version Control Model: Snapshots · DAG of commits Layers: Working tree · Staging area (index) · Repository
Resources: git-scm.com — Reference Pro Git (free book) Oh Shit, Git! — recovery guide Confusing git terminology

Basics

▼

The everyday workflow: initialise or clone a repo, stage changes, commit, and repeat. Stage only what belongs in a commit — git add -p lets you stage hunks interactively.

Set up a repo
git init                      # create new repo in current dir
git clone https://github.com/user/repo.git
git clone repo.git mydir      # clone into custom directory
Stage and commit
git status                    # show working tree state
git add file.txt              # stage a file
git add -p                    # interactively stage hunks
git add .                     # stage all changes in current dir
git commit -m "message"
git commit -am "message"      # stage all tracked files + commit
git commit --amend            # edit last commit message (local only)
git commit --amend --no-edit  # amend last commit, keep message
Check what you're about to commit
git diff          # unstaged changes
git diff --staged # staged changes vs last commit

Branching & Merging

▼

Branches are just pointers to commits — they're cheap to create. Prefer git switch and git restore over git checkout for clarity (available since Git 2.23).

Create and switch branches
git switch -c feature/my-feature  # create + switch
git switch main                    # switch to existing branch
git branch                         # list local branches
git branch -a                      # list all (including remote)
git branch -d feature/done         # delete merged branch
git branch -D feature/unmerged     # force delete
Merge
git merge feature/my-feature       # merge into current branch
git merge --no-ff feature/my-feature  # always create merge commit
git merge --abort                   # abort a conflicted merge
Rebase
git rebase main                    # rebase current branch onto main
git rebase -i HEAD~3               # interactive: squash/edit last 3 commits
git rebase --abort
Never rebase commits that have been pushed to a shared branch.
Cherry-pick
git cherry-pick <commit-hash>
Apply the changes from a specific commit onto the current branch.
Fix up a specific past commit (fixup + autosquash)

Stage your correction, then create a fixup commit targeting the SHA you want to amend:

git add file.txt
git commit --fixup=<sha>          # creates a commit named "fixup! <original message>"

Then replay history so the fixup is squashed in automatically, skipping the editor:

GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash <parent-of-sha>
--autosquash moves the fixup commit next to its target and sets the action to fixup (squashes silently, discarding the fixup message). GIT_SEQUENCE_EDITOR=true accepts the rebase plan as-is without opening an editor. Rewrites history — only use on local / unshared commits.

Remote

▼

Remotes are named references to other repositories. origin is the conventional name for the repo you cloned from.

Fetch, pull, push
git fetch origin                # download without merging
git pull                        # fetch + merge (or rebase with --rebase)
git pull --rebase               # apply remote changes before local commits
git push origin main
git push -u origin my-branch    # push + set upstream tracking
git push --force-with-lease     # safer force push; fails if remote has new commits
Manage remotes
git remote -v                                        # list remotes
git remote add upstream https://github.com/orig/repo.git
git remote set-url origin git@github.com:user/repo.git
Tags
git tag v1.0.0                          # lightweight tag
git tag -a v1.0.0 -m "Release 1.0.0"   # annotated tag
git push origin v1.0.0                  # push a tag
git push origin --tags                  # push all tags

History & Diff

▼

Navigating history. git log --oneline --graph gives a compact visual overview of the branch topology.

Log
git log --oneline
git log --oneline --graph --all
git log -p file.txt                  # commits + diffs for a file
git log --author="Name"
git log --since="2 weeks ago"
Diff
git diff main..feature               # between two branches
git diff HEAD~2                      # vs 2 commits ago
git show abc1234                     # show a specific commit
Blame
git blame file.txt
Shows the commit and author for each line.
Bisect — find which commit introduced a bug
git bisect start
git bisect bad
git bisect good v1.0
git bisect reset            # finish and return to HEAD
Binary search through history; Git checks out the midpoint commit each step.
Reflog — your safety net
git reflog
Shows a log of all HEAD movements; use it to recover "lost" commits or branches after a bad reset.

Undo

▼

Three distinct tools depending on what you want to preserve. revert is the safe option for shared branches — it creates a new commit rather than rewriting history.

Discard changes in working tree
git restore file.txt          # discard unstaged changes in a file
git restore .                 # discard all unstaged changes
Unstage
git restore --staged file.txt  # unstage (keep working tree changes)
Reset (moves HEAD)
git reset --soft HEAD~1   # undo last commit, keep changes staged
git reset --mixed HEAD~1  # undo last commit, keep changes unstaged (default)
git reset --hard HEAD~1   # undo last commit, discard all changes
Never use --hard or force-push on shared/published commits.
Revert (safe for shared branches)
git revert abc1234
Creates a new commit that undoes the specified commit.
Clean untracked files
git clean -n   # dry run — show what would be removed
git clean -fd  # remove untracked files and directories

Stash

▼

Stash saves uncommitted changes to a stack so you can switch context and come back later.

Basic stash
git stash                        # stash working tree + index
git stash -u                     # also stash untracked files
git stash push -m "description"  # stash with a label
git stash pop                    # apply most recent stash + remove it
git stash apply stash@{2}        # apply without removing
git stash list
git stash drop stash@{0}         # delete a specific stash

Worktree

▼

Worktrees let you check out multiple branches simultaneously, each in its own directory, all linked to the same repository. Useful for working on a feature while fixing a bug on main without stashing or switching branches.

Basic worktree usage
git worktree add ../hotfix main  # check out 'main' in a new folder
git worktree add ../feature -b feature/new  # new branch in new folder
git worktree list                # show all linked worktrees
git worktree remove ../hotfix    # remove a worktree
git worktree prune               # clean up stale .git metadata

Config & Aliases

▼

Git config is layered: --system (all users), --global (current user), --local (this repo). Local overrides global overrides system.

Identity (required for commits)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
View all config
git config --list --show-origin
Shows each setting alongside the file it was set in.
Useful defaults
git config --global core.editor "nvim"
git config --global pull.rebase true       # rebase on pull instead of merge
git config --global push.autoSetupRemote true  # auto -u on first push
git config --global init.defaultBranch main
Aliases
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.unstage "restore --staged"