Git
Verified against git 2.43.0, flags verified via `git <cmd> -h` and tested against a live repo, 2026-08-20 · official docs
The daily-driver subset of Git — branching, rebasing, stashing, filtering history, diffing, and recovering from mistakes with the reflog. Not the full manpage; just the commands that actually come up while working.
Branching#
Create, switch, rename, and clean up branches.
git branch # list local branches git branch -a # list local + remote-tracking branches git branch --show-current # print the current branch name git switch -c feature/new-thing # create and switch to a new branch git switch main # switch to an existing branch git branch -m old-name new-name # rename a branch git branch -d feature/done # delete a branch (only if merged) git branch -D feature/abandoned # force-delete a branch (even if not merged)
git switch is the modern, safer replacement for git checkout <branch> — it only touches branches, so it can't accidentally discard file changes the way checkout can. Prefer it for branch operations.
Stashing changes#
Shelve work-in-progress without committing it.
git stash # stash tracked changes git stash push -u -m "wip: auth" # stash including untracked files, with a message git stash list # show all stashes git stash show -p stash@{0} # view a stash's diff git stash pop # apply the most recent stash and drop it git stash apply stash@{1} # apply a specific stash without dropping it git stash drop stash@{1} # delete a specific stash git stash branch new-branch stash@{0} # create a branch from a stash (useful after a conflict)
stash pop fails and leaves the stash in place if applying it produces a conflict — resolve the conflict, then git stash drop manually.
Rebasing#
Rewrite a branch's history onto a new base, or clean it up before merging.
git rebase main # replay current branch's commits onto main git rebase -i HEAD~5 # interactively squash/reorder/reword the last 5 commits git rebase --onto main old-base feature # move a branch to a different base commit git rebase --continue # after resolving a conflict mid-rebase git rebase --skip # skip the commit currently causing a conflict git rebase --abort # bail out and restore the branch to its pre-rebase state
Never rebase a branch other people have already pulled — it rewrites commit hashes, so anyone with the old history will get diverged/duplicate commits on their next pull. Rebase local/unshared branches only.
Viewing history#
Filter and format commit history for what you're actually looking for.
git log --oneline --graph --decorate # compact visual history git log --author="jane" # commits by a specific author git log --since="2 weeks ago" --until="yesterday" # commits in a date range git log --grep="fix" # commits whose message matches a pattern git log -- path/to/file.py # history of a single file git log -p -2 # full diff for the last 2 commits git log --stat -1 # files changed + line counts for the last commit
git log -S"someFunction" (the "pickaxe") finds commits that changed the number of times a string appears — useful for finding when a specific line of code was introduced or removed, which plain --grep (message text only) can't do.
Diffing#
git diff # unstaged changes vs the index git diff --staged # staged changes vs HEAD git diff main..feature # diff between two branches git diff HEAD~3 HEAD # diff between two points in history git diff --stat # summary (files + line counts) instead of full diff git diff -- path/to/file.py # diff limited to one file
Cherry-picking#
git cherry-pick <commit-sha> # apply a single commit onto the current branch git cherry-pick -n <commit-sha> # apply the changes but don't auto-commit git cherry-pick --continue # after resolving a conflict mid-cherry-pick git cherry-pick --abort # bail out of an in-progress cherry-pick
Undoing changes and recovering with the reflog#
git restore --staged path/to/file.py # unstage a file (keep the changes) git restore path/to/file.py # discard unstaged changes to a file git reset --soft HEAD~1 # undo the last commit, keep changes staged git reset --mixed HEAD~1 # undo the last commit, keep changes unstaged (default mode) git reset --hard HEAD~1 # undo the last commit and discard the changes entirely git revert <commit-sha> # create a new commit that undoes a prior commit (safe for shared history) git reflog # show a log of everywhere HEAD has pointed, including "lost" commits git reset --hard HEAD@{2} # recover to a state from the reflog (e.g. before a bad reset/rebase)
reset --hard is destructive to your working tree, but it is not destructive to the repository — every commit it seems to throw away still exists and is recoverable via git reflog until git's garbage collector eventually prunes unreferenced commits (default ~90 days for reflog entries). If you ever do a reset --hard or a rebase you regret, git reflog is the first thing to check, not a last resort.
For a branch already pushed and pulled by others, use git push --force-with-lease instead of git push --force after a rebase — it aborts the push if the remote has commits you haven't seen yet, preventing you from silently clobbering someone else's work.