Your pull request has commits called wip, fix typo and asdf. Before anyone reviews it, let's turn that mess into clean, meaningful commits with git rebase -i.
Every command and hash below came from a real repository I ran this in.
Video version:
Before: a messy branch
$ git log --oneline
2c27ca8 Add login tests
fc5d50d asdf
4ffd51f fix typo
3e5db2d wip
3d66ed5 Add login form
6b96e5f Initial commit
There's one real commit for the login form, three junk commits that are really part of it, and then the tests. We want two clean commits: "Add login form" and "Add login tests".
Step 1: start the interactive rebase
$ git rebase -i HEAD~5
Git opens your editor with one line per commit, oldest at the top:
pick 3d66ed5 Add login form
pick 3e5db2d wip
pick 4ffd51f fix typo
pick fc5d50d asdf
pick 2c27ca8 Add login tests
pick means "keep this commit as it is".
Step 2: change the commands, save and close
pick 3d66ed5 Add login form
squash 3e5db2d wip
squash 4ffd51f fix typo
squash fc5d50d asdf
pick 2c27ca8 Add login tests
| Command | What it does |
|---|---|
squash (s) |
merge into the commit above, and edit the combined message |
fixup (f) |
merge into the commit above, and discard this message |
reword (r) |
keep the commit, change its message |
drop (d) |
delete the commit |
| (move a line) | reorder commits |
Save and close the editor. Git replays the commits and asks you for the final message of the squashed commit.
After: clean history
Successfully rebased and updated refs/heads/main.
$ git log --oneline
65399a2 Add login tests
ae3841d Add login form
6b96e5f Initial commit
There are two clean commits now. Notice that the hashes changed: rebase creates brand-new commits, which is why the safety rules below matter.
Pro tip: --fixup + --autosquash
Found a bug in an older commit? Don't make a "fix typo" commit and clean it up later by hand. Tell Git which commit the fix belongs to:
$ git commit -a --fixup=ae3841d
$ git log --oneline
13275fc fixup! Add login form
65399a2 Add login tests
ae3841d Add login form
Later, rebase with --autosquash. Git moves the fix to the right place and marks it as fixup automatically:
$ git rebase -i --autosquash HEAD~3
pick ae3841d Add login form
fixup 13275fc fixup! Add login form
pick 65399a2 Add login tests
Just save and close. You don't have to edit anything by hand. Set git config --global rebase.autoSquash true to make it the default.
Safety rules
-
Only rebase commits that aren't on a shared branch. Never rewrite
mainafter others have pulled it. - Already pushed your own feature branch? Use
git push --force-with-lease, not--force. It refuses to overwrite commits someone else pushed in the meantime. - Conflict or panic mid-rebase?
git rebase --abortputs everything back. - Regret it after it's finished?
git reflogstill has your old commits.
Cheat sheet
-
git rebase -i HEAD~N: edit the last N commits -
squash/fixup: merge into the commit above -
reword: change a message ยทdrop: delete a commit -
git commit --fixup=<hash>+git rebase -i --autosquash -
--force-with-lease,--abort,reflog
Does your team squash commits, or keep them all? ๐
I post one tested coding tip every day on YouTube at Refactorly. The 30-second version of this one is here.
Top comments (0)