Wednesday, November 25, 2015

A Git workflow

In my current project, we are introducing branches both at the server level and at the local level.  We have server level branches when our master is being released and we want to add functionality while the release process is going on.  I personally want a local branch for each story I am working on so that I can quickly switch back to the previous state to check things out.  This has led to some confusion and pain:  Essentially, we constantly forget which git command to use when.

Git is not intuitive when it comes to this workflow (or any workflow, if you ask the skeptics), especially as the team prefers to do rebase over merge.  Here is one of the many possible solutions.  I describe the case with the local work in progress branch, but you can leave that part out as described below

Workflow with a local work-in-progress branch

Step 1:  Create a work in progress branch and commit to it.  I still have not settled on always calling this branch 'wip', as it is ephemeral anyway, or giving it a decent name.   For short and simple stories, I definitely recommend wip.
git checkout -b wip
git commit -am 'done'

Step 2: You can squash or otherwise modify your commits with a
git rebase -i <REVISION>.  You can use various short cuts to refer to the revision where you branched off, I personally like to actually use the revision id (sha) there.  
We use 'git lola' a lot, which is an alias for
git log --graph --decorate --oneline --all

I realized I often only want to see the last few commits, so here is a bash alias (it does not show the coloring as git lola does, which is a shame)
alias lola='git log --graph --decorate --oneline --all | head'

Step 3: Update master to receive any new work your colleagues may have done.
git checkout master
git pull -r 
The -r option on the rebase is not required as we should not have any updates to master, but my teammates are in the good habit of always typing pull -r.

Step 4: Rebase the wip branch on the updated master, solving any merge conflicts as you go.
git checkout wip
git rebase master

If there are any merge errors, fire up your merge tool and use 'git rebase --continue'.  The commit should now be good to go and pass all your tests.

Step 5: Merge the wip branch into master.
git checkout master
git merge wip
Although this team does not like merges, this merge is actually a fast-forward so it is acceptable to them.  I guess it leaves the wip branch as a parent in the merge comment, but as we will be shortly deleting that branch this is harmless.

Step 6: Rewrite the commit and do a duet-commit / pair-commit:  To clearly distinguish our temporary commits (early, often) from the real deal, I only do a duet-commit when I am actually ready to ship this code.
git reset HEAD^
git duet-commit 

This assumes your work was all contained in one commit.  You will have to do some extra git magic if you have more than one commit to convert to a duet-commit.

Step 6: Ship the code and delete the branch
<magic-shipping-command>
git branch -d wip



Step 7: Enjoy your fresh commit

As one of my current team mates says: "I hate branches, they really blow. Stop reading this."  Sounds a lot like this guy to me :-)


No comments:

Post a Comment