Sunday, August 15, 2010

Git Saved my @$$: Episode I–The Phantom Branch

I have been enjoying Git for a while now.  Since switching to Git on my current project, we have been quietly succeeding.  However, whether through disinterest, or laziness, I avoided really understanding how it worked.  That is, until it saved my ass.

So here’s the deal.  I was on a tear.  I just finished coding and testing a feature.  As I am now wont to do, I was working on a local feature branch (PO-updates).  It was time to merge back to our development branch.  Actually, it was time to rebase, but I merged out of ignorance.  There were merge conflicts in the project (*.proj) file, but I was on fire.  Not time to pay attention to the output.  I ran all my unit tests, and [blam] green bar!  Ok, merge complete (or so I thought).  Time to delete the feature branch.

Screenshot of me not noticing the warning "error: the branch 'PO-updates' is not fully merged. If you are sure you want to delete it, run 'git branch -D PO-updates", and me (of course) running "git branch -D PO-updates"

Oh crap!  After the initial freaking out was over, I took a deep breath and reviewed what I knew about Git (which was very little).  Well, as it so happens, I was working in the same session where I did the final commit for that branch.  The command “ci” is just a shell script that adds new files then commits changes.

A screenshot of my last commit (with comment "finished").  It shows that the ID for the branch "PO-updates" is 1c5680b.

Hm, I wonder what I can do with this information.  The ID of the branch PO-updates is 1c5680b.  Maybe lets see if I can see the log just for this branch.

"git log 1c5680b" yields the id of the commit "finished"

Holy $#!+ that worked!!  Now I have this big long @$$ commit ID (c15680b2647bfcb02d7ed6723a30d9fe2cd62e7 for anyone who cares).  After pondering what I could do with that for a while, I formulated this hypothesis.  Git seems to let you do just about anything.  I wondered if it would let me merge that merge the last commit in to a new branch.

Creating a new branch.  "git co -b PO-changes-deux" then merging changes from the big honking ID for the last commit.

Double holy $#!+ b@man! I think it just did something amazing.  Did it really just merge a commit from a deleted branch into a new branch?  Is it possible that it would be cool enough to not immediately purge the deleted files from history?  I nervously opened up my project.  In truth, Git had me at “git init,” but that was the very moment where I became a sincere Git fanboy.  I don’t enter into fandom lightly, since I tend to think of fanboys as mindless zombies, but this was too much.  I LOVE GIT!

All that I had left to do was to rename the branch to the proper name.

git branch -m PO-changes-deux PO-changes

Now I no longer delete feature branches when I’m done with them.  I created a shell script called “archive” that surrounds the branch name in parentheses.  “archive PO-changes” would have changed the branches name to “(PO-changes)”.  I also created a shell script called “shelve” which surrounds the branch name in curly braces.  This allows me to organize the branches and visually differentiate active and inactive branches.  Shelved branches show up at the bottom of a branch list, and archived branches show up at the top.

image