Skip to end of metadata
Go to start of metadata

This plugin automates feature/personal branch workflow on Jenkins by providing one-click branching/rebasing/integration or automated rebasing/integration.

Plugin Information

View svnmerge on the plugin site for more information.

For general discussion of feature branches in Subversion, see Online subversion book or articles. Feature branches allow developers to commit their changes without worrying too much about regressions, and this Jenkins plugin assists teams to deploy this more easily.

Features

One-click feature branch setup

You can have Jenkins create a branch in Subversion and create a job for it (by copying from the trunk build job) just by one click of a button.

To do this, first enable the feature branch support in the job that currently builds the trunk by clicking "Accept Integration from Subversion feature branches." This creates an action on the left to manage/create new feature branches. From this page, you can create a branch and the job:

Alternatively, you can manually create a branch, create a job, and enable the feature branch support after the fact by clicking "This project builds a Subversion feature branch" and specifying the trunk job.

Integration status visualization

Jobs that build feature branches get two actions on the left. One shows the status of the integration, meaning what changes in the branch has already been integrated into the trunk, the revision number of the integration commit, what trunk CI job has built it, etc.

The up arrow in the build history indicates builds whose output has been integrated upstream.

One-click rebase

The other action in the project top page allows you to manually initiate the "rebase" action, which is a Subversion merge command to pull in the latest changes from the trunk into your feature branch, thereby synchronizing the branch with the trunk.

In addition to rebasing with the tip of the trunk, this UI allows you to pick arbitrary revision to rebase, in terms of the known build — for example, you can rebase with the revision that was resulted in the last stable trunk build, thereby eliminating any risk that you pick up regressions into your branch.

(This also works with the build promotion plugin and others that can define their own permalinks.)

Automatic rebase

Aside from manually performing rebase, you can also make rebase a part of the build. This can ensure that your feature branch always stay close to the trunk, thereby reducing the pain of the merge down the road.

Specifying the build to rebase to is a good way to control the frequency of the rebase. For example, imagine using the build promotion plugin on the trunk, and promote a build as "rebase point" about once a day (contingent on passing QA jobs.) Since the last "rebase point" build would only change about once a day, the automatic rebase would be no-op most of the time but only once a day.

Automatic integration

In addition to initiate integration manually, you can also make Jenkins do integration automatically. This can be used as a publisher, as seen below:

If you enable this in a project, you'll be automatically integrating with every successful build. This is useful for personal branches, where you'll keep on committing to this branch and let Jenkins verify the change before it gets integrated into the trunk.

This feature gets more interesting in combination with the build promotion. You can keep producing CI builds quickly, then use other jobs to verify its quality, and as a promotion action you can make the integration happen. This matches more closely with the typical integration workflow.

Tips

  • Automatic rebase and integration actions can be configured in the upstream job so they are automatically configured on feature branch jobs when created by the plugin.
  • You can avoid the so-called Subversion "keep-alive-dance" which triggers unnecessary builds of the feature branch by excluding the commit messages matching Rebasing with the integration commit that was just made in rev\.\d+ (see this discussion).

Changelog

Version 2.6 (December 10, 2015)

Version 2.5 (January 10, 2015)

Version 2.4 (December 20, 2014)

  • Add support for build parameters in Subversion URLs. (issue 24735).
  • Fix wrong revision used for upstream integration (issue 25739).
  • Add permissions for Rebase and Integrate actions (issue 25942).
  • Fix integration of promoted builds (issue 14725).

Breaking changes

New permissions for Rebase and Integration will have to be granted manually on system using matrix-based authorization.

Version 2.3 (July 15, 2014)

Version 2.2 (May 28, 2014)

  • Improved repository layout detection and customization on "New Branch" action (issue 15830, issue 22284).
  • Added option on "Automatic Rebase" action to fail the build when merge conflicts are found (issue 6851, issue 22850).

Version 2.1 (Mar 13, 2014)

  • Fix reintegration issue with HTTP protocol (issue 12495).

Version 2.0.4 (Feb 28, 2014)

Version 1.3 (Feb 21, 2014)

  • Handle feature branches in subfolder (isse 21781).
  • Added possibility to enter a commit message when creating a feature branch (issue 11012).
  • Copy "Local module directory" from upstream project when creating a feature branch (issue 11379).

Version 1.2 (Apr 14, 2012)

Version 1.1 (Oct 1, 2011)

Version 1.0 (Sep 1, 2011)

  • Initial release

31 Comments

  1. J S

    Rebase changes from upstream throws error: java.lang.NullPointerException
    at jenkins.plugins.svnmerge.FeatureBranchProperty.rebase(FeatureBranchProperty.java:148)
    at jenkins.plugins.svnmerge.RebaseAction.perform(RebaseAction.java:105)
    at jenkins.plugins.svnmerge.RebaseAction.perform(RebaseAction.java:25)
    at jenkins.plugins.svnmerge.AbstractSvnmergeTaskAction$WorkerThread.perform(AbstractSvnmergeTaskAction.java:105)
    at hudson.model.TaskThread.run(TaskThread.java:127)
    at jenkins.plugins.svnmerge.AbstractSvnmergeTaskAction$TaskImpl$1.run(AbstractSvnmergeTaskAction.java:161)
    at hudson.model.ResourceController.execute(ResourceController.java:88)
    at hudson.model.Executor.run(Executor.java:230)

    Clicking on "Integration status" throws "status code 500"

  2. kohsuke

    Please provide a box to input a comment, and add it to the rebase comment

  3. How does this plugin resolve merge conflicts ?

  4. Hi,

    we are using the svn merge plugin and the promoted builds plugin just as you proposed in the 'Automatic Integration' section. The promotion is configured to "Promote builds..." "only when manually approved" and "Integrate to upstream upon succesful build" is configured as action. If we now approve the promotion manually, the following error appears:

    Legacy code started this job. No cause information is available
    Building in workspace /var/opt/int/hudson/server/hudsontest02/data/jobs/buildtest-feat001/workspace
    Promoting buildtest-feat001 #10
    Upstream Subversion URL is not specified. Configuration problem?
    failed build jenkins.plugins.svnmerge.IntegrationPublisher@4cb3b97f SUCCESS
    Finished: FAILURE

    "This project builds a Subversion feature branch" is checked and the upstream project name is set. Do you have any idea how to solve this?

    1. I wanted to create a feature branch for "current stable" purpose, to help automatic deployment.

      For this you have to remove "accept automatic integration" (since no commit will come from the feature branch)

      and removed the "automatic integration" (that i've added, but that is again for different purpose, if your feature branch run successfully can commit to the trunk),

      and added a trigger to run the created job for the feature branch.

      And set up automatic rebase for the feature branch.

      Now my feature branch will allways be based on the latest stable. And the trunk can be used as normal.

      (As I understand this plugin proposing the other way when you work with branches and this plugin integrates them to the trunk)

  5. How does one store or add SVN credential needed for creating a feature branch?  Are they added elsewhere and merely used by the plugin?  Using this plugin "out of the box" seems to work fairly well, but I am getting permission error when trying to create a new feature branch:

    Error

    svn: E200015: MKACTIVITY /svn/MyProject/!svn/act/32399071-3b01-0010-a4d7-275040667f37 failed

  6. We are thinking of going to personal branches for our CI model.

    user commits to their branch, drives build, if successful commit to the integration branch, not trunk.

    this commits to 'upstream', but I can't figure out how to limit to the integration branch.

    In the base svn plugin we specify both the integration branch (1st)  and the user branach (second)

    they are checked out in order correctly.. and effectively have the merged results in the working copy on the build server.

    did I miss a configuration option?

    1. If I understand correctly, the integration branch is the 'upstream' of the personal branches. If you enable "Accept Integration from Subversion feature branches." on the job that builds the integration branch and create the personal branch jobs as feature branches of this job, it should do what you want. (Note: If you create a job on an existing branch, the plugin will ask to attach the job to the branch).

  7. Hi Hugues,

    I ran into an issue with this plug-in. It's not a stopper or deal-breaker for me, and it's probably a very rare edge case.

    The scenario is I wanted to be able to trigger older builds by passing the specific revision, so I added SVN_REVISION as a parameter, defaulting to HEAD.

    1. Set up a job
    2. Feature branch it
    3. Modify the main job to allow SVN_REVISION to be passed in as a parameter,
    4. and default it to HEAD (may not matter)
    5. and change your svn url to http://path/to/project/trunk@$SVN_REVISION
    6. then rebasing a feature will fail, complaining about the path.

    Also, if you set up the job initially with the @SVN_REVISION, the plug-in won't be able to find the repo when you go to feature branch it.

    The work-around for me is easy enough; rather than specifying the @SVN_REVISION in the URL, I just:

    1. manually cut a branch from the specific revision I want,
    2. tell the plug-in to add the feature branch (with the same name)
    3. Click OK to add the project when it warns me the branch already exists.

    Given that it's most likely just a bizarre edge case of mine, I don't know that I would do anything with it, I just wanted to give you a heads up.

    1. It is an interresting case. I create issue JENKINS-24735 to that effect.

      One easy fix would be to remove the @XXX suffix from the URL. I don't think it makes any sense to rebase/integrate to a specific revision, does it?

      1. That's true. The @NNN suffix was just to go back in time to create the branch, but it's so rare of a case, it doesn't matter, it was just as I was migrating to Jenkins. I would probably just mark the issue as "won't fix."

  8. I've just hit another interesting one. It's not a bug in your plug-in, but rather something that we need to correct in our workflow.

    Using C#, we have our projects set up to use a shared AssemblyInfo.cs file, that exists at the root of the solution.

    Ideally, this would be a template, but without that file locally, the build will fail, and we were trying to avoid adding a pre-build event.

    During the build, we update this file to have the correct version information, including the svn revision. So, because this isn't a template, it shows up as an scm change.

    How this ties in with your plug-in is, that if I try to rebase from the upstream, it shows that there are local modifications and it will sometimes fail, or sometimes succeed (and commits these changes). So it would be nice if I could tell the SVNMerge plugin to do a revert first, that way there are no local changes.

    But again, this is a sign that our workflow needs improvement, so I'm going to correct our situation by converting that file to a template, svn ignoring the actual version of the file, and adding a pre-build event to copy the template to the full version.

    1. Would it be possible to use an external definition for AssemblyInfo.cs ?

  9. How are conflicts handled?

    1. A conflict during a rebase is ignored unless "Stop the build if the merge fails" option is checked.
      A conflict during a reintegration fails the build.

  10. I am having a hard time trying to come up with a way to let all feature branches trigger after a successful upstream/trunk build, for automatic rebase.

    All plugins that trigger downstream jobs expect a full job name, no wildcards. If developers all create a personal branch for themselves, how can I make sure that the feature/personal branch job is triggered when there are successful builds of the trunk?

    Right now, after developers create their personal branches through the plugin, which copies the trunk job, I have to manually go to the trunk job and add a new downstream job.

    1. I agree, it would be very convenient to be able to use wildcard in job name. But, for some reason, it is not supported, yet.

      One solution would be to use the Jenkins Script Console.

      On the other hand, the Subversion Merge Plugin could be able to help. Upon feature branch creation, the plugin could add a build trigger on the feature branch. However, that kind of trigger only work when project tracks Fingerprint.

  11. Under "Rebase with upstream subversion revision", there is an option "Last Integrated build".

    Can you elaborate what that is? When doing manual rebase, there is no such option. I've had jobs setup using that option, and it was working fine for several weeks, but now it fails because "No build that matches Last Integrated build".

    What makes a build "integrated", is it marked in anyways? We are talking about the trunk/upstream build here, right? Do I need to keep log history of all builds in Jenkins for this to work?

  12. Ran into this today and was wondering if this is "normal".

    - Developer1 committed code to Integration branch yesterday
    - Developer1 never promoted that code into Stable branch
    - Developer2 committed code to Integration branch today
    - Developer2 used Jenkins to then promote code up to Stable
      (here's where the "huh" happens.)
    - Rather than promoting Developer2's commit to Stable, Jenkins instead promoted Developer1's commit to Stable.

    Is this how the plugin is supposed to work?

    1. Hugues -

      Did you happen to get a chance to view the above post?

      Just wondering if the plugin is designed to "queue" commits made to Feature branches?

      1. Normally, the plugin merges everything up to the revision associated to the build (it is reintegrating).

        If you have the following situation.

        • Developer 1 commits to feature branch rev. R.
        • Jenkins builds feature branch, build #X.
        • Developer 2 commits to feature branch rev R'.
        • Jenkins builds feature branch, build #X'.

        At that point, you can reintegrate build #X, which contains rev. R only or you can reintegrate build #x', which contains revs R and R'.

        Is it possible that the promotion action reintegrate the wrong build ? You can look at the Integration Status. If Jenkins states that build x' was reintegrated but commit rev. R' is not in the stable branch, it is clearly a wrong behaviour.

  13. Witnessing another behavior that I'm unsure about.

    - I commit code to my Feature branch

    - Jenkins detects the change and triggers a build for my Feature branch

    - The build passes and I click the "Integrate to Upstream" button

    - The merge to upstream occurs and then Upstream is immediately merging back into my Feature branch (I never setup any Post-Build action to do that)

    - Jenkins detects the change in my Upstream and triggers a build for my Upstream branch

    - Jenkins ALSO detects the change (that mysterious merger back down to Feature branch) in my Feature branch and triggers ANOTHER build for my Feature branch

    So my Feature branch job ends up getting triggered 2 times in a relatively short window.

    Is this the appropriate behavior?

    1. I wouldn't say it is appropriate but I observe the same behaviour when using a subversion post-commit hook to trigger Jenkins builds. Do you use post-commit hook ?

      1. Hugues -

          No, I never setup a post-commit hook.

        1. This is called the Subversion "keep-alive-dance". It's a "record-only" merge. This is what allows the feature branch to remain open after it has been reintegrated to Trunk.

          This "keep-alive-dance" is not required as of Subversion 1.8, but needed for all versions below that.

          You can configure trigger criteria on your Feature branch not to rebuild when a certain commit message is encountered, such as "Rebasing with the integration commit that was just made"

          1. Slav -

            Thank you so much for the quick response!

            In my Feature branch Jenkins job, in the Build Triggers section of the configuration page, I see an option for "Ignore Post-Commit Hooks".  Is that what I would want to enable to prevent this secondary build from occurring?

            1. No no, this has nothing to do with "Post-commit". This is an action of the plugin itself: the plugin performs the record-only merge and commits to SVN. That is it. Your SCM polling or Post-commit hooks are required to trigger regular builds, but they also detect this change. You can make an exception for this commit.

              It commits with a fixed commit message.
              It reads: "[REBASE] Rebasing with the integration commit that was just made in rev" (followed by revision number)

              In the feature branch job configuration, under "Source Code Management" section, click the "Advanced..." button in the Subversion configuration. It will open (among others) a field called "Excluded Commit Messages". Give a regular expression for commit messages that you want to exclude, in this case:

              (?i)Rebasing with the integration commit that was just made

              1. Ah, ok.  So something like this should work then.

                /Rebasing with the integration commit that was just made in rev.\d+/

                -EDIT-


                Actually, the above snippet still didn't work.  Posted a question on StackOverflow.  I had to get rid of the REGEX delimiters.  Also, just in case, I escaped that period after "rev".  Works great now!

                Rebasing with the integration commit that was just made in rev\.\d+
                  1. Slav -

                      You are awesome!  Thanks for your help! :)

  14. I wanted to use different user for the creation of Branch on the SVN to keep track of who created the branch and use generic user for job to run automatically and my existing job also use generic user for the automated builds.

    Also it looks like anyone have access to Jenkins have capability to create the feature branch and initiate the rebasing etc. I was wondering how can use matrix based authentication in LDAP access system so that others users don't see this option only admin can.

    Any suggestion would be helpful.

    Thank you for this beautiful plugin :)