I was streaming this past week and there was a good question about re-ordering Git commits that I thought would be worth sharing here.
Let’s say you have commits in the order of a
, b
, d
, and c
, and you want their order to be a
, b
, c
, and d
, instead.
This is a job for git rebase
! The “official” description for rebasing is “reapply commits on top of another base tip” which is… kind of helpful. There are docs. Let’s just go over our use case because there’s a lot you can do with rebase and not enough time to go through it all.
Start an interactive rebase
In this case, you use what’s called an “interactive rebase”! A regular rebase is used to move commits to a new base commit, which is typically for keeping a branch up to date with another branch. An interactive rebase lets you do much more, like reordering, editing, removing, or squashing commits.
Anyway, first, we’ll start an interactive rebase for the range of commits we want to reorder:
git rebase -i HEAD~4
Edit the order
This will open a text editor (for me it opens vim, but depending on your setup it could be something else). The commits will look something like this:
pick <commit-c> Commit message for c
pick <commit-d> Commit message for d
pick <commit-b> Commit message for b
pick <commit-a> Commit message for a
Re-order the commits in that file!
pick <commit-d> Commit message for d
pick <commit-c> Commit message for c
pick <commit-b> Commit message for b
pick <commit-a> Commit message for a
(if it opens vim and you aren’t sure how to edit things, you can move your cursor down and up with j
and k
respectively, and type ddp
to move a line up, ddkP
to move a line down. Use :w
to save and :q
to quit. It sounds jank but I promise it’s a really intuitive editor once you give it a chance!!)
If there’s something wrong
If everything works at this point with no issues, skip this section!
Otherwise, when you save and edit the text editor, if there are issues, Git will shout at you a bit and tell you about conflicts.
Open each conflicting file and resolve the conflicts manually. The conflicts will be marked with conflict markers (e.g., <<<<<<<
, =======
, >>>>>>>
) and you have to pick which pieces of code you want to keep.
After you resolve a conflict in a file, write in the terminal:
git add <file name>
git rebase --continue
Then, repeat this until all of the conflicts are resolved!
Cancelling all these changes
If at any point during the rebase you’re like “wait, this was a bad move,” (been there) you can type:
git rebase --abort
This will return your repository back to its original state!
Pushing all these changes
Blammo, you made it to the end! Push your changes with a git push
at this point and be free. You might have to add the --force
flag to your push, depending on your setup.
I mentioned before that this came up while I was streaming! If you’d like you can watch on GitHub’s Twitch or YouTube every Thursday! It’s a new series I started called Rubber Duck Thursdays, which is basically my excuse to hack and yap in public on their channels, heh. See you next time!
Top comments (2)
This is a great breakdown but I’m curious, what’s the real-world use case for reordering commits like this?
It can really depend, but when I've seen it it's mostly been for cases that are more self-documenting, like "oh I want [some other person looking at this] to know that you should do X before Y" or something.