Part 3 - Other Useful Git Tools

Series: How to Suck Less at Git
Part 3 of 3
In parts 1 and 2 we covered the most basic tools in the developers Git toolbox after add and commit. This post dives a bit deeper into other lesser used but extremely powerful git tools; git rebase -i, git bisect, and git reflog.
Rebase Interactive
Section titled: Rebase Interactivegit rebase -i <commitish (exclusive)>Interactive rebase is an advanced technique. Even though -i looks like just a flag on the rebase command that we already talked about, it’s best to think of this as a completely separate tool from regular rebase.
When you run this command, git will present you with a prompt that looks something like this (I’ve trimmed this down slightly):
pick f7f3f6d Change my name a bitpick 310154e Update README formatting and add blamepick a5f4a0d Add cat-file
# Commands:# p, pick <commit> = use commit# r, reword <commit> = use commit, but edit the commit message# e, edit <commit> = use commit, but stop for amending# s, squash <commit> = use commit, but meld into previous commit# f, fixup <commit> = like "squash", but discard this commit's log message## These lines can be re-ordered; they are executed from top to bottom.# If you remove a line here THAT COMMIT WILL BE LOST.It shows you a list of commits and a list of commands. Change the command on a specific commit to modify that commit accordingly:
- pick: don’t modify this commit
- reword: edit this commit’s message
- edit: pause replay of the commits at this step so you can do something to it
- for example you can manually make additional changes and use
commit --amendto add those changes to this commit - or you can use
resetto “undo” this commit and then split it into multiple commits by usingadd --patchto only stage certain parts
- for example you can manually make additional changes and use
- squash: combine this commit with the previous one, kind of like
commit --amend - fixup: combine this commit with the previous one, and also delete its commit message (squash opens an editor for you to combine the commit messages)
- delete a line to
that commitdelete to change the order of the commitsreorder the lines
Git Bisect
Section titled: Git BisectBisect is an extremely powerful debugging tool that helps you find the source of a bug by tracking down (via binary search) the exact commit that created it.
- You give it start and end commits; one you know works (is “good”) and one you know has the bug (is “bad”).
- It goes to the commit in the middle
- You test that commit and tell Git if that commit is good or bad
- Git picks a new commit and you repeat step #3.
Bisect works best when:
- You have a linear history (every commit comes before and after exactly 1 other commit)
- Every commit compiles. This process takes much much longer if you have to make code compile before testing a commit.
- Your commits are small. If the commit that introduced the bug is 5,000 lines, you haven’t narrowed it down all that much.
Git Reflog
Section titled: Git ReflogThere are very few truly destructive actions in Git. If you commit something, no matter what you do next (apart from deleting the .git folder), it will always be possible (for someone who knows what they’re doing) to recover that commit for at least 30 days. After 30 days “hanging” commits that no branch points to can be garbage collected.
Until then, you can find it in the reflog!
git reflog
97299e1 (HEAD -> main, origin/main, origin/HEAD) HEAD@{0}: pull: Fast-forward7d5fb7d HEAD@{1}: commit: fix(mac-setup): Cleanshot preview don't move between screensd570c6c HEAD@{2}: commit: fix(mac-setup): Less scrolling issueb783846 HEAD@{3}: commit: fix(jargon-prod): Add \"going live\" synonymbf4b5c2 HEAD@{4}: checkout: moving from zp/learnability to mainYou can think of reflog as the Git graveyard. When you’ve lost something, the reflog is where you can recover it. Specifically, reflog is a list of every action that you’ve performed in Git for the last month. It lists every hash that your HEAD has pointed to.
I like to use it in conjunction with grep to filter the results:
git reflog | grep scroll
d570c6c HEAD@{2}: commit: fix(mac-setup): Less scrolling issue