Automatic Merge

Dear DVCS users, TeamCity 8.1 brings you automatic merging! Please give it a try and let us know what you think!

Now you can merge the sources of a build into a specified branch using the automatic merge build feature. It handles the case when you create a branch to fix some issue and push the branch only once when the work is complete and ready to be merged.

Remote runs

Those of you who use remote-runs from IDE know that the great thing about them is that IDE will submit your changes automatically once the build finishes successfully. However, as it happens with every technology, remote runs have some shortcomings.

When you start a remote run, TeamCity applies your patch on top of the latest revision at the time the build starts. So when you decide to submit your changes, the result of the personal build reflects the final state of your repository more closely, which is great! But if your colleague breaks some tests or, God forbid, a compilation while your remote run is waiting in a queue – your build will fail even though you didn’t break anything.

Another shortcoming is that in order to commit personal changes, TeamCity needs your IDE to be open so that the TeamCity plugin can make a commit on your behalf. Besides, personal builds force you to make all the changes in a single commit which is not always convenient.

Automatic merge

With the automatic merge you get the picture similar to remote runs. When a build finishes successfully in your feature branch, the branch is merged automatically to the default.

As with every merge, the automatic merge works best with short-lived branches. The merge itself doesn’t care about the age of your branch, but the older your branch is, the higher the probability of failure due to conflicts is. Actually, not only files can be moved around, but also semantics can change over time. Things get worse when you, for example, extend some java class while your colleague removed it in the default branch. The merge succeeds but your compiler won’t be happy with the result.

Still, comparing to remote runs, the automatic merge can get you the best of 2 worlds: the isolation of feature branches and the ability to integrate your changes automatically. As a bonus, you can finally turn off your computer when you go home – the merge is performed on the server, so no open IDE is required.

Configuring automatic merge

First, configure feature branches. Then add the Automatic Merge build feature to your build configuration. Specify a pattern for branches to merge, e.g. ‘+:issue-*’; a destination branch, e.g. ‘master’; and a merge commit message to use. By default, the merge is performed only for green builds, but you can also choose to run a merge if no new tests failed. If there are any conflicts during a merge, TeamCity fails the build.

You can specify the merge commit author in VCS root settings:

What if you want to merge only when several conditions are met? For example, do the merge only when tests on Linux, Windows and Mac OS pass. You can achieve that using snapshot dependencies:

  • create a build configuration with a VCS root to merge and configure the auto merge build feature
  • add a snapshot dependency to every build you want to succeed before a merge occurs.

As a result, the merge at the top of the chain will be performed only if all builds in its snapshot dependencies were successful.

Double-distilled merge

To handle semantic conflicts, like the use of a removed class, you can create a separate ‘integration’ branch and use it as a destination for an automatic merge, and then configure another merge from the ‘integration’ to the default branch. The integration branch will sometimes be red due to uncoordinated changes in the parallel branches but the default branch will always be green and safe to deploy*.

Manual merge

The asterisk in the previous sentence means it was a lie . The automatic merge cannot guarantee green builds. If you run your build on multiple platforms or there is a lot of concurrency in your system, some tests may fail even if the previous build on the same revision was green.

So you have a build where some tests failed, but you know that the build is fine and its sources should be merged. To deal with such cases, you can merge the build sources manually. We added the Merge this build sources action on the Changes tab of a build. It allows you to choose a destination branch and do the merge. A manual merge is also useful if the push-only-when-complete workflow isn’t suitable for you, so you can merge the branch when it is ready from the TeamCity UI.

This entry was posted in Features. Bookmark the permalink.

3 Responses to Automatic Merge

  1. Mark says:

    Am I correct in thinking that this only really applies to a DVCS environment like Git or Mercurial, as opposed to Subversion?

  2. Michael Kuzmin says:

    Yes, this is a feature for Git and Mercurial.
    For Subversion, Perforce and others we still have Remote run and Pre-tested commits.

  3. Hao Li says:

    We are using this feature in our CI process and it works as described, which is great!

    I’d like to make a feature request so this would fit our development model even better. Basically we would like to validate every change before it is merged into the shared branch, and we want the merge to always be a fast-forward merge (so what’s been validated pre-merge is exactly the end result of the merge). We are willing to manually deal with the occasional re-basing if fast-forward is not possible.

    One possible way to get us that is to add an additional choice of “Use fast-forward merge only” to “Merge policy”, in addition to the two existing choices of “Always create merge commit”, and “Use fast-forward merge if possible”.

    If we make that choice, and the merge fails, the entire build would fail.

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>