I went to see X-Men: Days of Future Past last weekend. While having a heated discussion about the logic behind the time travel in the movie with fellow Rocketeer Lucas Galego, we realized that Git provides a great analogy for time travel. So here you have it, the new X-Men movie explained in Git.
If you haven't seen the movie yet then you probably shouldn't read this post. There are definitely spoilers here. If you have seen it then read on...
In The Beginning
Fade in. The X-Men are on the main timeline (the master branch), but something has gone terribly wrong. Super-powerful shape-shifting sentinels (bugs) have emerged and are killing all the X-Men (the working features). Luckily, Kitty Pryde, aka Shadowcat, has the ability to send people's consciousnesses back in time (she's a Git master).
Finding The Problem
The group of remaining X-Men think back in their memories (Git history) to determine at which point in time (which commit) the problems started. In Git, you can use git bisect to quickly determine which commit introduced a problem.
$ git bisect start $ git bisect good some-time-far-in-the-past $ git bisect bad time-when-sentinels-are-coming-to-murder-us
Git bisect uses binary search to pick which commit to show you each time. You then tell Git which commits are good and which are bad...
$ git bisect good $ git bisect bad
And through a quick process of elimination Git will pinpoint which commit started all the trouble:
Author: Mystique <firstname.lastname@example.org> Date: 1973 Kill Trask, get my DNA stolen.
Ah yes, that's the one. Mystique just had to go getting her DNA stolen. Good job Mystique. It's okay though, we can fix this.
Going Back in Time
Now that we know where the problem started we can go back in time and change history (write new code).
The X-Men choose to send back Wolverine (a programmer), because the trip will be a rough one for his mind and he is the only one with instant healing power (you have that too, right?).
Kitty Pryde places her hands next to Wolverine's head, concentrates really hard and... boom! Wolverine from the future wakes up in his 1973 body. That's just like git checkout:
$ git checkout wolverine-wakes-up-in-random-bed-1973 You are in 'detached HEAD' state....
We are in a
detached HEAD state. That sounds morbid, but it really means that we are detached from the main timeline (master branch), and we have the capability to start a new timeline (a new branch) if we choose.
Wolverine wakes up and quickly dispatches some nameless henchmen (squashes minor bugs). They should know better than to mess with Hugh Jackman.
Wolverine wants to be on a new timeline, which is like checking out a new branch:
$ git checkout -b prevent-sentinels
Now the movie goes on and Wolverine stops Mystique from killing Trask, twice. The sentinel program is stopped and the dystopian future is prevented.
$ git commit -m 'Pull Charles out of depressed state' $ git commit -m 'Free Eric from super-max prison' $ git commit -m 'Stop Mystique from killing Trask at the summit' $ git commit -m 'Stop Mystique from killing Trask at the press conference' $ git commit -m 'Get rebar-ed by Magneto'
Wolverine now is lying unconscious at the bottom of a river with rebar laced throughout his body. Mystique, disguised as Stryker, revives Wolverine. At this time he doesn't have the memories from the dystopian future, he's just his original 1973 self. Let's stash the changes to Wolverine's memories so we can get them later:
$ git add app/characters/wolverine/memories.yml $ git stash
The New Timeline Becomes the Main Timeline
We've got totally new events on this timeline, and we want it to become the official timeline (the master branch).
To do this we need to remove all commits from master that occur after the timelines diverge, then pull in all the new commits from our new branch. We can do this with git reset --hard and git rebase:
$ git checkout master $ git reset --hard wolverine-wakes-up-in-random-bed-1973 $ git rebase prevent-sentinels
Now master is the exact same as the prevent-sentinels branch, so we can add code directly to master. We don't need the prevent-sentinels branch anymore so we can delete it:
$ git branch -D prevent-sentinels
Wolverine's Memories Return
At the end of the movie Wolverine's memories from the dystopian future return:
$ git stash pop $ git add . $ git commit -m 'Wolverine's memories return'