Git – A Developer’s Workflow

A few weeks ago I attended a nice little presentation about GIT at our local Chippewa Valley Developers Group meeting. After the show, and discussing the presentation over a couple of brews with a configuration manager and a low level C++ engineer — we thought that a lot of things weren’t clear like release strategy.

I remember when Subversion came out, I was really keen on it because it had a very loose workflow, easily adaptable to many technical processes. In fact if you’ve ever kan-banned, the board *really* starts to look like a release process especially if there are different server environments for say Java web apps. Won’t get into just how bad those environment columns can get – I’ve even seen a board with at least 20 columns of tasks taking up an entire 10X20 ft. wall! A wee bit too much. Git is also loose in this manner, and in my use of Git — I have more experience in Hg and Darcs — and talking with a lot of different points of view I think a pattern emereged that is a great practice for developers.

Festus says — “Why don’t you just go on an Git?”

Here are the two revelations about Git I’ve arrived at:

  1. A merge is not a merge is not a merge. That means, merging master and origin (possibly the remote repo, from where you cloned) is NOT the same as merging master and branch. Not at all.
  2.  A Developer should ALWAYS develop from a branch. Always.

The first revelation led to the second revelation. But for some reason, in the merge/rebase wars — it was forgotten that a loca branch/master merge was quite differnt than a master/origin merge.

The question that led me to this was, I thought you applied a typical master/origin workflow to a branch. That is, that the realtionship between branch and master was the same as master and origin, such that in branch you would pull –rebase to sync up with master. Not so. There is no pull activity, unless you wish the branch to pull from origin.

The second question was, discussing with the config manager — how to bundle features in such a way that it’s useful to them. It’s a matter of “repository scope.” So this came out of that discussion:

  1. Developers should check in early and often with atomic commits.
  2. Atomic commits are almost useless to a release manager, they want a feature release. SO they need bigger units of commit because they may want to revert that entire feature, and a set of commits won’t do.

Hence, the branch/master merge creates that package whilst retaining those atomic commits.

For the my developers my workflow is now this when I am assigned work, for a branch named topic:

git checkout -b topic

do a bunch of work . . . .

git commit -m "topic commit 1"

git commit -m "topic commit 2"

now update master from origin . . . .

git checkout master
git pull --rebase

sync my branch to master. . .

git checkout topic
git rebase master

merge into master . . .

git checkout master
git merge topic

and (after checking for changes) push . . .

git push

Onto solving the second part, making commit’s for a config manager.

Note that Git implicitely does a “fast forward” merge for master/branch that plays my commits on top of the master, but there’s never a record of the merge. IN a lot of cases this might be OK, but in many cases we may want a *real* feature branch to retain its unit of checkin. For instance, say the branch was a whole new package, in which case for the config manager we want to do a non-fast forward merge that will remember the commits, but also retain the branch information.

git merge --no-ff topic

Some utilities like “squash” seem like a bad choice for this because they toss the history out — bad for the developer. But this no fast forward merge can do the trick; retain history in all scopes.

alt text

(From nvie.com, Vincent Driessen, post “A successful Git branching model“)

The impact of doing development like this is far reaching. For the last years I have been on Subversion checking directly into trunk; and Hg managed a lot of merge and commit history with less work than Git. But the Git community has brought it to my attention — ALWAYS CREATE A BRANCH before you develop.

I wonder how this will impact code writing. Making a feature being aware that it should be able to be reverted when you check it in is WAY different than checking in non-accessible work-in-progress or hard coding out features.

My personal feeling is that to some extent this is a pipe dream. Many projects have some developers changing underlaying libraries while the rest build on top of them — the unit of a “feature” does not sit at the checkin level. So more hands on and use cases are needed to improve what we do, no doubt.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>