Yesterday I saw a project by github user vbarbaresi called MetroGit, where he uses git branches and commits to represent the Paris metro system. My first thought was “wow, what a cool idea!” My second thought was “wow this transit system is complex.” My third thought was “wow the TTC is boring I bet I could do this in 5 minutes.”
AND THEN IT TOOK LIKE 6 HOURS
I decided I would build it in the same way vbarbaresi did, using empty commits where the commit message was the name of the subway stop, and each branch named after the corresponding subway lines. Git doesn’t like empty commits, so to do this, you need to add the flag —allow-empty to the end of your commit message.
For some reason I was worried that someone would notice while I was building the repo and watch me make mistakes, so I started with a test repo. Here I tried different types of merges to see what they’d look like in the network view, which was my main focus. I tried an octopus merge which was new to me and looked like this:
This is done by merging 2 branches into another branch at the same time, with the following syntax:
git merge branch-1 branch-2
I wanted to make the subway lines run along side each other, like this:
instead of in bunches, like this:
Each clump represents a push, so I learned quickly that when I wanted the lines to run along side each other, I’d need to push after every commit. I’d checkout a branch, write the commit, push it, switch branches, write the next commit, push it, switch branches again, and so on.
On the TTC (here’s a map) there’s a scenario where two lines meet and then go through two stations together, Spadina and St.George:
I couldn’t for the life of me figure out a way to do this - if you can think of one, let me know! I made a couple attempts of merging branch-1 into branch-2, and then merging branch-2 into branch-1 (and similar ideas), but because there were no changes, nothing would stick. I settled on deciding that the lines would only be merged on the St.George commit, as technically the lines don’t actually meet at Spadina (you have to walk a hundred metres or so from one line to the other). Just let me have that one for now.
When I felt happy with the way my branches had turned out, I decided to update the README. Shoot. This would pollute my lovely little network visualization, catching my master branch up to the others. Guess who learned a whole bunch about rebasing? Surprise, it was me. Guess who learned even more about trying to rebase empty commits. You guessed it.
I managed to squash master down to a single initial commit. This took a little trickery because rebase will usually not allow you to squash the first two commits for some reason. Git will rudely spit out ’Cannot ‘squash’ without a previous commit’ or somesuch, leaving you with your heart in your hands and a pair of sad commits that just want to be together. UNTIL:
git rebase -i –root
From the docs:
–root: Rebase all commits reachable from , instead of limiting them with an . This allows you to rebase the root commit(s) on a branch.
Huzzah. Now we have master as a single point, instead of a long line polluting the visual.
And this is where I’m at today. My friend Chris suggested retroactively turning the branches into orphan branches.
From the docs:
–orphan : Create a new orphan branch, named , started from and switch to it. The first commit made on this new branch will have no parents and it will be the root of a new history totally disconnected from all the other branches and commits.
To do this I’d have to delete the initial commits using git rebase -i. Instead of marking a commit “pick” or “squash”, simply deleting the line would “cause the commit to be lost”. The problem is, you can’t only have empty commits leftover from the rebase, as far as I can tell.
I haven’t figured out where I’ll go from here, but I might end up starting over with all the good stuff I’ve learned. For now, lonely lil’ master dot will have to hang out with this subway stop buddies.
You can see the result so far here.