Interactive rebase
Author:
Richard Hughes
Published: October 21, 2021
9 minutes to read
The purpose of this article is to document the steps involved in performing an interactive rebase as an easy reference for clients without paid tools to simplify the process. By the end a git novice should be able to follow along unassisted.
Pre-requisites
Rebase can be executed from Visual Studio Code, many IDEs or the command line. The following tools can be used to simplify the process:
- Git graph viewer: VS Code with mhutchie.git-graph extention
- Some means of doing git commands from the CLI from here
What is Rebase
A rebase is a way of integrating work to branches as an alternative to using a standard merge. The difference between the two is as time goes on normal merges can lead to a very messy git graph and make it difficult or impossible to find how work was merged. The way that rebase simplifies this issue is by actually re-writing the history so that it is as though the changes were made right on top of some later commit.
Unfortunately rebases can be more complicated making many people scared of them despite the advantages. But a rebase can be as simple as a couple of commands which I’ll put below before I get into the more complicated topic of the interactive rebase. To do a standard rebase:
- Checkout the branch to be rebased
- Run
git rebase origin/target-branch
- If there are no conflicts and the process completes run
git push origin --force
A lot of the time those two commands are all that is required. However many commits you have made are replayed on top of the target branch. When complete it will look like you have made your changes starting from the last commit of your target branch rather than some earlier point in the history.
Guide to interactive rebase
Chances are that you will always try to do it the easy way first as above. The first thing is to cancel the rebase using git rebase --abort
.
The next thing you should do is check the graph to see what work is actually yours. It may take time to learn this part but eventually you should be able to quickly glance through the nodes of your branch and determine what is your work vs. stuff that you have merged in.
Now comes the fun bit. You run git rebase --interactive origin/target-branch
while on your branch. This will open a vim editor in your terminal. To make life easier here are some commands that will help make use of it.
Vim commands | Description |
---|---|
i | Press the i key when not in interactive mode to enter interactive mode and edit the commits list. |
Esc | Press the Esc key when in interactive mode to exit and use other key commands. |
:wq | While NOT in interactive mode press this key sequence to save changes and close the vim editor. |
:q! | While NOT in interactive mode press this key sequence to close vim without saving changes. This is useful in case the edits do not look correct. |
So in the vim editor that opens you will see something that looks like the following example. It is already telling you how to do a few interesting things, but your changes will ultimately come down to putting a d or drop next to the commits that you don’t want to be rebased. NOTE When you run the rebase there will be instructions as well which I’ve omitted for brevity, but read it through for a full understanding of what can be done in an interactive rebase.
pick 442a48288 Adding publication form
pick 9e4588745 Publication date component
pick b503173d8 Test updates for form
pick 460c79b2f Portal settings integration with publication dates service
# Rebase e7403349a..460c79b2f onto e7403349a (4 commands)
In the example above the branch that is being rebased consists of 4 different commits and will default to rebasing all commits. But if the target branch already had the final commit I could do the following:
- Start the interactive rebase from the branch to rebase. This will open a vim session in the CLI
- You will see something resembling the example above. Press i to enter interactive mode
- Update the commits that are no longer required with drop e.g.
drop 460c79b2f Portal settings integration with publication dates service
- Press Esc to return to command mode
- Press :wq to close the editor and save the changes
- The rebase will now continue automatically
- If there are conflicts you will need to resolve them
As many commits as are necessary can be dropped from the rebase. Identifying those that are already committed in the target should be fairly trivial in a lot of cases. To help use a git graph tool to look at the commits and identify commits that can be dropped without issue.
What about conflicts
If you have conflicts then they will need to be resolved. To do this you need some tool to compare the changes in your branch and the target and decide how to resolve it. Broadly there are 4 options to resolve it:
When you have a conflict in a file you should be able to see it in the git tab of VS Code. If you click on the file there you will see a diff of the file with the conflicts highlighted in blocks like this:
The current commit of the rebased branch’s changes will be here.
The current state of the target branch’s changes including previous rebased commits.
Command option | Description |
---|---|
Accept Current Change | Take just the change in the target branches changes. Remember that this will include any rebased commits that are already done |
Accept Incoming Change | Take just the change from the current commit being rebased |
Accept Both Changes | Take both of the above changes. NOTE this will often require additional editing |
You can also use git commands to progress the rebase. Typically you will run the continue command after selecting one of the options above but other commands are listed below. It will then open a vim editor with that commit’s message. If you aren’t changing it just use the vim close command.
Below are commands that can be typed in the git rebase terminal to continue actions.
Command | Description |
---|---|
git rebase --continue | Continue to the next commit of the branch to be rebased. All conflicts must be resolved for this to succeed |
git rebase --skip | Skips the current commit from the branch being rebased |
git rebase --abort | Abort the rebase and return the branch to its pre rebased state |
When not to Rebase
Just because you can do something doesn’t mean that you should. 99% of the time you should NOT rebase a branch that is used by multiple people. The reason for this is that the re-write in the history will make it as though the branches diverged and make the other developers lives more difficult as a result. If you only rebase your own branches then you should never run into issues.
How can it go wrong?
Occasionally you will have to take a change from another branch such as some API updates possibly before they are completed to the target branch. When you eventually go to PR your changes if those changes are already merged before that you will get conflicts. But this can be avoided using the interactive rebase.
Even if you haven’t merged from another branch sometimes someone will happen to alter code in the same area as you.
So you do a rebase and you get conflicts. If you know that you have merged other changes into your branch that have already made their way into your target then you would be better doing an interactive rebase to at least avoid those conflicts. Otherwise you can resolve the conflicts as normal.
References
If you would like to read further on the above topics you can find further info at: