The eight git commands worth actually learning
Not a tutorial. A short list of the operations that separate people who fight git from people who use it.
Most developers use about six git commands and route around everything else by deleting the repository and cloning it again. That works. It is also leaving an enormous amount of leverage on the table for maybe two hours of investment.
Here is the short list. Not the complete list — the list where each item changes how you work.
1. git rebase -i#
The one that matters most. Interactive rebase lets you rewrite your local history before anyone sees it: squash the four "fix typo" commits, reorder, split a commit that did two things, reword a message you wrote badly at 6 p.m.
git rebase -i main # everything since you branchedThe rule that makes this safe: rewrite history that only exists on your machine or your own branch. Never rewrite a shared branch. That is the entire safety model and it is not complicated.
2. git add -p#
Stage hunks instead of files. This changes how you commit, because it removes the excuse for the giant mixed commit. You made an unrelated fix while working? Stage it separately, commit it separately.
y to stage, n to skip, s to split the hunk smaller, e to edit it by hand.
3. git log -S#
Search history by code, not by message. "When did this string get introduced?" "Who deleted this function?"
git log -S "retryPolicy" --oneline
git log -S "retryPolicy" -p -- src/http.ts # with diffsThis is the single fastest way to answer "why is this here," and it beats git blame because blame only shows you the last change to a line.
4. git bisect#
Binary search for the commit that broke something. It feels like a niche tool until the first time it saves you a day.
git bisect start
git bisect bad # current is broken
git bisect good v2.3.0 # this was fine
# git checks out a midpoint; test it; say good or bad
git bisect run ./test.sh # or automate it entirelyThat last form is the good one. Give it a script that exits nonzero on failure and it finds the culprit unattended.
5. git reflog#
The undo button for everything. Every position HEAD has occupied for the last ninety days, including states unreachable from any branch.
git reflog
git reset --hard HEAD@{4}Deleted a branch, botched a rebase, hard-reset over uncommitted work you meant to keep? Reflog. The number of people who have re-cloned a repository over something reflog would have fixed in ten seconds is very large.
6. git worktree#
Multiple branches checked out simultaneously in different directories, sharing one object store.
git worktree add ../myrepo-hotfix hotfix/urgentNo stashing, no switching, no rebuilding your entire dependency tree because you had to jump to a different branch for one review. This has become dramatically more useful in the age of coding agents, where you may want two working copies being edited at once.
7. git rerere#
"Reuse recorded resolution." Turn it on once and git remembers how you resolved a given conflict, then replays that resolution automatically the next time the same conflict appears.
git config --global rerere.enabled trueIf you maintain a long-lived branch that rebases repeatedly, this saves you from resolving the same three conflicts every single time.
8. git commit --fixup and --autosquash#
Found a problem in an earlier commit on your branch? Do not amend it out of order and do not write "fix review comment."
git commit --fixup=a1b2c3d
git rebase -i --autosquash main # squashes it into a1b2c3d automaticallythe meta-lesson#
Git's model is small: commits are immutable snapshots, branches are pointers, everything is content-addressed. The porcelain is inconsistent and the error messages are famously unhelpful, but the underlying model is simple enough to hold in your head completely.
Spend an afternoon learning the model rather than memorizing commands, and every one of the above becomes obvious rather than magic.
— Dom, March 7, 2025