Git Ready to Rebase

Graphic of git branches

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.

Sources

Print Friendly, PDF & Email