Git Rebase Illustrated With Time Travel

Published on 2022-01-28 16:43:00+01:00

Back in the office days, colleagues and I would have weekly discussions about git which usually ended with comparing merge to rebase or with me preaching about the dangers of rewriting the history. Let's go back to these times but with a slight twist. There's already plenty of other in-depth git tutorials and git-rebase(1) is great and you should read it. There is no point in creating yet another resource, so instead let's make it a fun and chill weekend read.

Let's say two different people are working on two completely disconnected task in parallel in a known period. These tasks can be divided into a sequence of sub-tasks, where each sub-tasks enables next sub-task to be performed and there is no room for parallelization (for now). This situation can be illustrated like this:

original timeline

In the graph A and B lanes represent the progress of a task with significant points in sub-tasks. All sub-tasks can be projected into the time line and their order remains the same.

Let's expand the example by adding two common spots in time for both tasks: first being someone ordering to perform both tasks, and second being the merge of both lanes into one.

timeline with common tasks

This should look somehow similar to you, because (if not for the missing middle part) this graph represents a regular workflow that uses git-merge(1). C is a common origin and goal for both task lanes and serves the same purpose as master branch.

In order to reduce the number of lanes we can let one of the tasks claim the main lane for their own. This happens when you branch off an active branch that gets some additional work done before you merge back into it:

branch off and back

This image was probably recognized by you right away.

Now, it just happened, but turns out that by the end of the A task the person responsible for it built a time machine and proposed to the project management to use it in order to perform both tasks sequentially but in parallel time. They were as confused as you are but gave green light just to see what happens.

Developer took the results of B with them and went back in time to the spot where A and B diverged. They started to work on A using the souvenir from the future as the base. People that were working on task B in the meantime were confused.

When the moment for merge came, the traveller from future just presented their work and said that it's already merged, so there's no need to do anything. And they spoke truthfully, because in linear time the work looked like this:

rebase in linear timeline

But from the perspective of the traveller the whole timeline got distorted and didn't look linear at all:

rebase in non-linear timeline

From this point of view the sequence is one-lane and completely undisturbed. On the other time the timeline gets shifted and some parts of it fade away as they never were or are no longer observed by the time traveller. This is the perspective that one assumes when explaining rebase "in a normal way": reapplying the changes to a different base code (with same dates, meaning time travel, yay).

All of this happens every time you rebase your branches. Really.

Don't get me to talk started about interactive rebase features and cherry-picking! Or maybe do. That could be fun.