The basics of git rebase.
Hello again! This week the team ran into some git trouble which led to me tumbling down a git rabbit hole. Seems fitting that it would be a R-abbit hole, since the primary commands I needed to sort through were R-eset, R-evert, R-estore, and R-ebase. Today though, we will be focusing primarily on git’s rebase command. Rebasing is exactly what it sounds like you are changing the commit that a particular branch or commit connects to. First, we will take a look at a basic rebase and then we’ll check out how to move a branch back to an earlier commit.
Visualizing the Repo
git log --graph --all
First things first, when starting out with git in general and rebase more specifically, it’s really helpful to be able to checkout visual graph representation of the git repo. Above is a command you can use to get just that. There are a ton of ways to format the log with a graph and if you’re interested in customizing it, you can checkout this article for an overview and the answers to this post if you want to make each commit only take up one line. I definitely recommend taking a look at this explanation of how to create aliases as well that way you can save your fancy customized graph preferences in an easy to remember command.
Basic Rebase Operation
A word of caution, it’s best not to rebase on branches or main that other folks are working on unless you have a specific plan or workflow everyone has agreed upon. This is because a rebase will not only change the base of the commits or branch being moved, but rebasing will change the hash (alpha numeric string associated with the commit) of the commits that are being moved.
Before we begin, just like a merge you can abort a rebase at any time before it’s complete by using the abort flag:
git rebase --abort
If you use the commands:
git checkout topic
git rebase main
Or the command:
git rebase main topic
It will take your repo from this:
topic: E - F
/
main: A - B - C - D
To this:
A - B - C - D - E - F - G
| | |
| | topic branch stops
| topic branch starts
main stops
E, F and G have new hashes
If there are conflicts you will need to manually go into the files and decide what to keep in the files with conflicts (the first resolution will be any conflicts between D and E). If not you’ll, be able to skip ahead to the next steps section.
When you resolve all the conflicts for the first commit, in this case E, you’ll need these two commands:
git add .
git rebase --continue
You’ll have to repeat the resolve conflicting files, add resolved files, and rebase continue process for each commit. In our example, we would repeat it for F and G.
Next Steps
In most situations, you’ll want to do two additional steps after the rebase is complete.
Merge the topic branch into main:
git checkout main
git merge topic
Resulting in:
A - B - C - D - E - F - G
|
main AND topic end
Remove the topic branch:
git branch -d topic
Finally, we arrive here with a single branch on main:
main: A - B - C - D - E - F - G
Rebasing a Branch on a Previous Commit
This word of caution is worth mentioning again. It’s best not to rebase on branches or main that other folks are working on unless you have a specific plan or workflow everyone has agreed upon. This is because a rebase will not only change the base of the commits or branch being moved, but rebasing will change the hash (alpha numeric string associated with the commit) of the commits that are being moved.
Now that we are very clear on that, say we have this situation:
topic: E - F
/
main: A - B - C - D
And we want this to be our end result:
topic: E - F
/
main: A - B - C - D
It is very similar to a basic rebase. You will just need the hash of the commit you want to move the branch to. In this case commit B:
git checkout topic
git rebase --onto hash_of_B main
or
git rebase main topic --onto hash_of_B
If you want to make sure you’re moving the intended commits, you can use the interactive mode by adding an -i flag:
git rebase main -i topic --onto hash_of_B
Like it was described for the basic merge, you will need to cycle through the commits resolving any conflicts and using the commands:
git add .
git rebase --continue
Once all of the conflicts are resolved and the rebase is complete, we will arrive to our destination:
topic: E - F
/
main: A - B - C - D
Root Included Variation
If you wanted to include the root in the rebase option to get this:
topic: D - E - F
/
main: A - B - C
You would use the root flag:
git checkout topic
git rebase --onto hash_of_B --root main
In Conclusion
These are a couple basic rebase commands. Rebase can do quite a few things. I also recommend checking out the squash feature, if you don’t know it already. It is very useful for those times you realize you missed something in your commit and you have to commit again. It allows you to make one commit out of multiple commits.
Until next post, be a goldfish.