Tuesday, May 15, 2012

Basic Change Process Using Git

Very early on, I explained the basic change process in a diagram that's agnostic to the version control system. Git does have an interesting particularity that merits mention: the fast forward.

The motivation for this discussion came out of some questions around the promotion model, and what a "promotion" actually looks like in practice. As a reminder, a basic premise of the promotion model is that we use a stabilization branch to deploy from, and use master to aggregate all the new stuff.

One concern was that by merging master into the stabilization branch, we would create merge conflicts, and generally not be guaranteed to get the same code. If you first merge from the stabilization branch into master, then merge back, you shouldn't get that in any version control system.

With git though, you get a bonus:

We start with a series of checkins on the main branch. In git, a branch is a linked list of revisions, the root of which is stored in the "head" of the branch, here in dark color.
When you create a new branch, you essentially create a new head, and point it to the branch point revision. The following command creates the branch and "places" you at the head of it.
git checkout -b branch

Now if you check in a commit, you create a new revision. This revision will have a back pointer to the parent revision owned by the branch, and head will point to your new revision:
    vi somefile ...
    git commit \
      -a -m 'made change A'

Meanwhile, ongoing work hasn't stopped:
git checkout master
vi somefile ...
git commit -a -m 'made change B'

Now assume you wish to "promote" master into the branch. You start by merging branch into master:
 git merge \
    --no-commit branch
 # resolve conflicts
 git commit \
    -a -m 'Merged branch'

Now comes the git magic:
git checkout branch
git merge master
Nothing happens except that the head of branch is fast forwarded to the head of master. So we actually promoted the exact same revision we initially merged from the branch. Most other version control systems will create a new revision with a copy of the same content.

If you want, you can emulate that behavior in git:
 git checkout branch
 git merge \
    --no-ff master
This will create the copy and emulate the behavior of lesser version control systems - but why would you want to?

The bottom line is that fast forwarding makes the two models I described in my promotion post topologically equivalent. The only thing that changes between the two models is whether you reuse the same branch name or create new branch names. Topologically, a new branch will get extruded every time you do the merge down / merge back combination, no matter what model you choose:

No comments:

Post a Comment