18

I think this article, A Successful Git Branching Model, is very well known among experienced DVCS users.

I use hg mostly, but I would argue this discussion is fine for any DVCS.

Our current workflow is each developer clones the master repo. We write code on our own local repo, runs tests, and if all goes well pushes to the master.

So we want to setup CI servers like Jenkins and improve our workflow with the future provisioning system (chef, puppet, ansible, etc).

Real part

Well, the model presents above works nice but branches can break CI. The feature branch should sync with the origin (according to the article, it would be development branch) to make CI and merging smooth, right?

Say Alice and Bob are working on two features. But Alice is done the next day. Bob's feature takes a week. By the time Bob is done, his changes are out of dated (maybe Alice refactored/rename some classes).

One solution is each morning developers must pull master/origin to check if there's any changes. If Alice commited, Bob should pull and merge into his workspace so his feature branch is up-to-date.

  1. Is this a good way?
  2. Should these branches exist in the master repo (not local clone?) Meaning should every developer has commit privilege to the master repo on GitHub/Bitbucket so they can create a new branch? Or this is done locally?
  3. Lastly, the model presents by the article should break CI if branches are not sync with the origin/master. Since we want to do nightly build, should developers pull and merge before they leave work, and have CI runs on each feature branch as well?

3 Answers 3

12

First of all, the use of feature branches (to isolate the work done on a feature) and CI (to find integration problems as soon as they are committed) are slightly at odds.

In my opinion, running CI on feature branches is a waste of time. As feature branches come and go frequently, the CI tooling would have to be reconfigured over and over again. And that for a branch that most likely only gets updates from one or two sources that coordinate their check-ins to avoid the problems a CI system is meant to detect.
Thus, there is also no point in having the feature branches on the master repository server.

As for questions 1 and 3: It is the developer's responsibility to ensure the build on the main development branch does not break when they merge their feature-branch into it. How they do that is their problem, but two possible ways are:

  • Pull changes made to the main development branch into the feature branch on a regular basis (e.g. daily)
  • When the feature is done, merge the main development branch into the feature branch and push the merge result onto the main development branch.

In either case, the obvious integration issues (e.g. renamed classes/files) are found and fixed first on the feature branch. The more subtle issues are most likely only found when the nightly build runs and should be fixed there and then.

3
  • I do agree that the use of feature branches is (slightly) at odds with the CI concept. However, it is possible to create a CI system that does not require reconfiguration to run on feature branches. (I have done this in the past with some simple python scripts), and it can be useful when your "feature" branches are actually being used as release stabilization branches, where CI is absolutely required. Sep 18, 2015 at 13:51
  • 1
    Actually, I think that we need two "central" branches -- one as a "throwaway_integration" branch that exists purely as a quick merge-and-test check for features actively under development, and another "master" or "stable" branch that contains features after they have reached a certain level of stability/maturity. Developers pull stable code to work on from the second "stable" / "master" branch, and merge & push changes frequently to the first "unstable" / "throwaway_integration" branch. CI tests should run on both branches, of course. Sep 18, 2015 at 13:57
  • @WilliamPayne: I believe that such a "unstable" branch is often called "develop" Sep 18, 2015 at 18:17
5

In response to 1)

Any way that works is a good way. However: the whole premise of Continuous Integration is to integrate continuously. The idea is to catch integration bugs not only as early as possible, but within the development feedback cycle - i.e. while all the details for the code under test are within the short-term memory of the developer making the changes. This means that, under normal, everyday circumstances, work must be integrated across feature branches on every commit - maybe once every 15 minutes or so. To reiterate: The main purpose of continuous integration is to expose integration bugs while all the details are in the short-term memory of the developer(s) making the changes.

2)

Mostly, branches are created in Mercurial by cloning repositories, so you do not need to give every developer commit privileges to the master repo. You probably, however, want to give developers the ability to create cloned repos on the continuous integration server, as it is not always feasible to run tests locally. (I once had a CI system where the unit tests took 8 hours to run on a 128 core cluster) - Needless to say, developers did not, could not run tests locally.

3)

If you have the computational resources for it, yes, developers should be fully up to date with the main line of development at all times, particularly before they leave work, and you should run overnight tests on all lines of development (Although most CI systems do not make this easy).

2
  • 1
    "Mostly, branches are created in Mercurial by cloning repositories" - this may have been true in 2013, but these days, Mercurial bookmarks are functionally equivalent to Git branches in all but name.
    – Kevin
    Aug 21, 2015 at 15:42
  • @Kevin: You are most likely right. I've been using git (almost) exclusively since Feb '13 -- about a month after I wrote the above response ... so I am not particularly up-to-date on what changes have happened to Mercurial since then. Sep 18, 2015 at 13:47
1

Here is how you can do it: feature branching.

  1. For any new task (bugfix, feature, etc) start a new branch (e.g. bugfix-ticket123-the_thingie_breaks)
  2. While you work, continuously update and merge default (or master in git) into your feature branch. This helps you have your branch updated without having to work in the default branch
  3. When your feature is ready and your unit tests pass, then pull and merge default into your branch once more, close your branch and push it without merging, your integrator will notice the new head and that it is a closed branch, so he/she will take care of integrating it. If you have no integrator, switch to default and merge your feature branch into default.

The important thing here is that you will have 0 conflicts in the default branch when you merge your feature branch into it, and all your tests do pass.

With this simple workflow you will always have a pristine and stable default branch, now do the same for release branches, but integrating from default. If you need to integrate hotfixes directly into the release branches you can still do this by skipping the default branch, but again, only picking branches that just updated from the target branch and have no conflicts and their unit tests pass.

2
  • You mix and substitute rather orthogonal things. 0 merge conflict != 0 faulty unit-test, successful merge != successful code Jan 7, 2013 at 17:45
  • Added some clarification, forgot to mention that unit tests should pass as well :) Jan 8, 2013 at 11:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.