What Git branching models work for you?

HiQ CJ picture HiQ CJ · Apr 12, 2010 · Viewed 68.3k times · Source

Our company is currently using a simple trunk/release/hotfixes branching model and would like advice on what branching models work best for your company or development process.

  1. Workflows / branching models

    Below are the three main descriptions of this I have seen, but they are partially contradicting each other or don't go far enough to sort out the subsequent issues we've run into (as described below). Thus our team so far defaults to not so great solutions. Are you doing something better?

  2. Merging vs rebasing (tangled vs sequential history)

    Should one pull --rebase or wait with merging back to the mainline until your task is finished? Personally I lean towards merging since this preserves a visual illustration of on which base a task was started and finished, and I even prefer merge --no-ff for this purpose. It has other drawbacks however. Also many haven't realized the useful property of merging - that it isn't commutative (merging a topic branch into master does not mean merging master into the topic branch).

  3. I am looking for a natural workflow

    Sometimes mistakes happen because our procedures don't capture a specific situation with simple rules. For example a fix needed for earlier releases should of course be based sufficiently downstream to be possible to merge upstream into all branches necessary (is the usage of these terms clear enough?). However it happens that a fix makes it into the master before the developer realizes it should have been placed further downstream, and if that is already pushed (even worse, merged or something based on it) then the option remaining is cherry-picking, with its associated perils. What simple rules like such do you use? Also in this is included the awkwardness of one topic branch necessarily excluding other topic branches (assuming they are branched from a common baseline). Developers don't want to finish a feature to start another one feeling like the code they just wrote is not there anymore

  4. How to avoid creating merge conflicts (due to cherry-pick)?

    What seems like a sure way to create a merge conflict is to cherry-pick between branches, they can never be merged again? Would applying the same commit in revert (how to do this?) in either branch possibly solve this situation? This is one reason I do not dare to push for a largely merge-based workflow.

  5. How to decompose into topical branches?

    We realize that it would be awesome to assemble a finished integration from topic branches, but often work by our developers is not clearly defined (sometimes as simple as "poking around") and if some code has already gone into a "misc" topic, it can not be taken out of there again, according to the question above? How do you work with defining/approving/graduating/releasing your topic branches?

  6. Proper procedures like code review and graduating would of course be lovely.

    But we simply cannot keep things untangled enough to manage this - any suggestions? integration branches, illustrations?

Below is a list of related questions:

Also check out what Plastic SCM writes on task driven development, and if Plastic is not your choice, study nvie's branching model and his supporting scripts.

Answer

VonC picture VonC · Apr 12, 2010

The most troubling feature new developers to DVCS need to realize is about the publication process:

  • you can import (fetch/pull) whatever remote repo you need
  • you can publish (push) to any (bare) repo you want

From that, you can respect a few rules to make your questions easier:

Now:

Workflows / branching models:

each workflow is there to support a release management process, and that is tailored for each project.
What I can add to the workflow you mention is: each developer should not create a feature branch, only a "current dev" branch, because the truth is: the developer often doesn't know what exactly his/her branch will produce: one feature, several (because it ended up being too complex a feature), none (because not ready in time for release), another feature (because the original one had "morphed"),...

Only an "integrator" should established official feature branches on a "central" repo, which can then be fetched by developers to rebase/merge the part of their work that fits that feature.

Merging vs rebasing (tangled vs sequential history):

I like my answer you mention ("Workflow description for git usage for in-house development")

I am looking for a natural workflow:

for fixes, it can help associating each fix with a ticket from a bug tracking, which helps the developer remember where (i.e. on which branch, i.e. a dedicated branch "for fixes") he/she should commit such modifications.
Then hooks can help protect a central repo against pushes from non-validated bug-fixes or from branches from which one shouldn't push. (no specific solution here, all this need to be adapted to your environment)

How to avoid creating merge conflicts (due to cherry-pick)?

As stated by Jakub Narębski in his answer, cherry-picking should be reserved for rare situations where it is required.
If your setup involves a lot of cherry-picking (i.e. "it is not rare"), then something is off.

Would applying the same commit in revert (how to do this?)

git revert should take care of that, but that is not ideal.

How to decompose into topical branches?

As long as a branch as not yet been pushed everywhere, a developer should reorganize its history of commits (once he/she finally see the development takes a more definitive and stable shape) into:

  • several branches if needed (one by clear identified feature)
  • a coherent set of commits within one branch (see Trimming Git Checkins)

Proper procedures like code review and graduating ?

Integration branches (in a dedicated integration) repo can help the developer to:

  • rebase his/her development on top of that remote integration branch (pull --rebase)
  • solve locally
  • push the development to that repo
  • check with the integrator that doesn't result in a mess ;)