[Mono-dev] The new world of Git -- what else can we change :-)

Raja R Harinath harinath at hurrynot.org
Tue Jul 27 15:11:30 EDT 2010


Hi,

I've been trying to think up some more ways to disrupt everyone's
workflow, seeing that we've been so successful with the Git import ;-)

But, these proposals aren't any of those.  I actually have some
ideas that I think are useful.  These are in increasing order of
intrusiveness, but are non-disruptive :-)

I'm hesitant to post this, since it has the potential to turn into a
free-wheeling discussion about git workflows, and random git hints.
But, anyway, here goes.

     * clean up the main repos
     * make the maintenance branches ancestors of the "master" branch
     * make the branches on github.com/mono integration only

---------------------------

* clean up the main repos

The source trees at github.com/mono/ have a lot of junk^W branches left
over from the SVN days.  However, we mostly work on two or three main
branches.  For instance, in the mono/ tree, we work on the unstable
"master", the stable "mono-2-6" and very occassionally on "mono-2-4".
So, looking at the 111 branches in the mono/ tree is annoying.  At first
blush, I guess its pleasing from an code archeology standpoint, and
pleasing in the sense of a job well done with the SVN import.  But, 111
branches are distracting to work with -- they are a cognitive overload,
interfere with command-line completion, and are terrible on the Github
UI.

My proposal is to 

   (a) create a read-only set of fork/clones at github.com/historic-mono
   (b) remove all inactive branches from the repos in github.com/mono

This might also reduce the cost of a fresh clone by a few MB :-)

---------------------------

* make the maintenance branches ancestors of the "master" branch

Right now, "mono-2-4" and "mono-2-6" branched-off of "master" sometime
in history, and the tips of all three branches are divergent.

Git allows a very nice workflow that works well if the tips of the
maintenance branches are ancestors of the tip of development branch.
Now, to enable this workflow, I propose to perform the following
commits -- these are one-time only, and enable the nice workflow.

       git checkout mono-2-6
       git merge -s ours mono-2-4

       git checkout master
       git merge -s ours mono-2-6

The '-s ours' ensures that the contents are not merged, only the branch
ancestry is fixed.

To make it clear, this doesn't affect anything right now.  It only
enables a nicer workflow, but that's my opinion only.  We can debate the
workflow and choose something else instead.  So, here's a description of
why I think the workflow is nice.

The scenario is as follows: say you are fixing bug 555556 which was
present in "mono-2-4", but you want to fix it on all three branches.
What we currently do is work on the fix on "master", and backport the
fix to the other two branches.  This has two drawbacks

  * we can't very well keep track of what fixes have been backported

  * the fix has multiple fairly identical commits associated with it --
    the original one on master, and the cherry-picked backports.  When
    we later find a bug in such particular commit, we'll easily forget
    to notice that there are other commits with identical bugs.

Now, git best-practice[3] suggests that we do the following instead:

  * work on the bug on the earliest maintenence branch that we want the
    fix in

        git branch -b fix-bug-555556 mono-2-4
        <work>
        git commit

  * merge it into the integration branch, and merge the integration
    branch into all newer integration branches

       git checkout mono-2-4
       git merge fix-bug-555556

       git checkout mono-2-6
       git merge mono-2-4

       git checkout master
       git merge mono-2-6

       git push         # pushes all three tips [4]

Note that this maintains the invariant -- the tips of the maintenance
branches are ancestors of the tip of the development branch.

The advantage of this workflow is that each fix has exactly one commit
associated with it in history.  So, if there's a bug with that commit,
we'll be reasonably sure that we don't have duplicate bugs elsewhere in
history.

[3] this is explained in gitworkflows(7), also at

     http://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html

[4] if you followed the suggestion in the GitFAQ to set
    push.default=tracking, you'll need to say

       git push origin mono-2-4 mono-2-6 master

---------------------------

* make the branches on github.com/mono integration only

This is actually a workflow suggestion.  Maybe someone could come up
with some nice pre-commit hooks to enforce the suggestion, but that's
secondary.

Basically, the workflow is to never[1] commit directly on a branch tracking
an origin branch.

  git checkout master
  <start playing around with the code>
  <realize you're actually fixing bug 555555>

  git checkout -b fix-bug-555555  # future commits happen on new branch 'fix-bug-555555'
  <continue working, your working tree is still intact>
  git commit
  <work>
  git commit
  ...

then at a later point clean up the history

  git checkout fix-bug-555555
  git rebase -i --onto master master

and then, once you're ready to push it out

  git checkout master
  git pull    # refresh [2]
  git merge fix-bug-555555
  <sanity checks -- build, and test again -- you checked in unit tests didn't you>
  git push
  git branch -d fix-bug-555555

[1] "never" is too strong, obviously, but you get the idea: avoid if you can

[2] The idea is that you should never[1] have a merge message that reads

        "Merge from git at github.com/mono/mono:master"

    That's useless.  All merges should either be fast-forwards, or look like

        "Merge from fix-bug-555555"

    IOW, eminently readable

---------------------------

Comments, suggestions?

- Hari



More information about the Mono-devel-list mailing list