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.
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.
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
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 changesgit diff --staged — staged changes vs last commit
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).
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
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
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)
Remotes are named references to other repositories.
origin is the conventional name for the repo you
cloned from.
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
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
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
Navigating history. git log --oneline --graph gives
a compact visual overview of the branch topology.
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"
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)
Find which commit introduced a bug:git bisect startgit bisect bad / git bisect good v1.0
(binary search through history; git bisect reset to finish)
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)
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.
git restore file.txt # discard unstaged changes in a file
git restore . # discard all unstaged changes
git restore --staged file.txt # unstage (keep working tree changes)
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)
git clean -n # dry run — show what would be removed
git clean -fd # remove untracked files and directories
Stash saves uncommitted changes to a stack so you can switch context and come back later.
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
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.
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
Git config is layered: --system (all users),
--global (current user), --local (this repo).
Local overrides global overrides system.
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
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
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.unstage "restore --staged"
View all config:git config --list --show-origin