Skip to content

Instantly share code, notes, and snippets.

@gregdeane
Last active February 16, 2022 09:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregdeane/92e3b0b045319f8304ebac2951ced197 to your computer and use it in GitHub Desktop.
Save gregdeane/92e3b0b045319f8304ebac2951ced197 to your computer and use it in GitHub Desktop.

Squash your commits using git interactive rebase

The steps below assume that:

  • you use command-line for git and are using MacOS
  • you are working on a feature branch
  • vim is the default editor.

Notes

  • While in interactive rebase mode, the commits are in the opposite order of the way git log shows them.
  • When you see a command like SHIFT + :, the plus sign should not be pressed.

Important
Before starting interactive rebase, you may want to duplicate your feature branch to safely save it. This is because rebase can have dire (and irreversible) effects if you do it wrong. Once saved, you can switch back to your original branch and begin the rebase.

Warning!
Don't force push your branch to Github until you are certain you have done everything correctly.

Steps

  1. Find the hash of your first commit and copy the hash
  2. git rebase -i <your commit hash> (this will open vim)
  3. At this point you might see many commits (depending on how you normally handle merging)
    • Many of the commits will be yours but there may be some or many that aren't yours

Some commits are not yours

  1. To make rebasing your commits easier, we want to drop all of the commits that aren't yours.
  2. Move your cursor to the first line of the commit that is not yours. Press SHIFT + V to enter "visual line" mode
  3. Press the up/down arrow key (depending on where your cursor is) to highlight all of the "not your commits" lines

Some commits are not yours - highlighted

  1. Press SHIFT + : to enter command mode. Type s/pick/drop
    • Your command prompt will look like this: :'<,'>s/pick/drop
  2. Press ENTER. The lines should now look like this:

Commits are marked with drop

  1. Continue doing steps 5, 6, 7, and 8 for all commit lines that aren't yours.
  2. Press SHIFT + : to enter command mode. Type wq to save and quit. Rebasing will continue.
    • At this point, you may have merge conflicts for files not in your feature branch
    • Since we don't want to include these files in your rebase, we can skip them.
  3. Type git rebase --skip, then press ENTER:
    • You may have to do this multiple times if there are multiple merge conflicts.
    • Continue doing this step until all merge conflicts are skipped.
    • Once all the skips are done, you have successfully dropped the commits that aren't yours. These commits are no longer shown in git log.
  4. Type git rebase -i <your commit hash> and press ENTER again.
    • The only lines you should see in vim are your commits.
  5. Place your cursor on the bottommost line (e.g. the last commit in the list) and press SHIFT + V to enter "visual line" mode. Press the up arrow key until all of the lines are highlighted EXCEPT the very first line.
  6. Press SHIFT + : to enter command mode. Type s/pick/fixup and press ENTER.
  7. Move your cursor to the very first line (the one that wasn't changed in the last step). Press SHIFT + V to enter "visual line" mode.
  8. The line should be highlighted. Press SHIFT + : to enter command mode. Type s/pick/reword and press ENTER.
    • The lines should now look like this:

Lines after adding fixup and reword

  1. Press SHIFT + :. Type wq and press ENTER to continue with rebase.
  2. A new vim window will open. The commit you marked as reword in the above steps will appear

Old commit message before edit

  1. Change the commit message to a new one.

New commit message after edit

  1. Press SHIFT + :. Type wq and press ENTER. You're all done! 🎉

Helpful commands

  • If during interactive rebase you make a mistake, type: SHIFT + : to enter command mode. Then type cq and press ENTER.
    • This will cause vim to exit with an error and thus, nothing from that rebase session will be saved.

Resources

Rebase

vim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment