Is it possible to use the git-flow model with Subversion?

11,401

Solution 1

We use what is called the unstable trunk development method. This was the development methodology that the creators of Subversion had in mind when they created Subversion. It's simple and easy to implement.

  • You do all of your development on trunk. Thus called the unstable trunk.
  • When you get close to a release, you make a branch for that release. The idea is to make the branch late enough to keep parallel development as short as possible, but not so later that some developers can't do their jobs because they no longer need to work on the current release, but need to start working on the next release. In Agile, this is usually done right before the firming sprint. It's usually done when the release is feature complete, and now you're just fixing bugs.
  • The release takes place off of the branch. You tag off the branch. If there are patches that are needed, they're done off of the branch.

Here's an idea how it works:

  • Imagine you're working on Release 1.2. You are working on the trunk. Now, you're getting close to the time when Release 1.2 is about to be released, and there's not enough work on Release 1.2 to keep your developers busy. You create a 1.2 branch for your release.
  • Now, the people still working on Release 1.2 switch over to the Release 1.2 branch. Meanwhile, developers working on 1.3 stay on trunk.
  • You are now ready to Release 1.2. You tag Release 1.2 right on the branch. The branch is not merged back into trunk. The trunk is for Release 1.3.
  • Bugs are reported, and you want to fix them in Release 1.2.1. You continue working off the 1.2 branch. No new branch needed for 1.2.1. (You can lock branches between releases to keep them pure.
  • When you are about to do Release 1.3, you repeat the process -- branch 1.3 and work for 1.4 continues on the trunk.

There will be some merging. It's mainly merging defects fixed on the release branch back to trunk. There are three options of doing this:

  • Once you do a release, you merge enmass all changes on the branch back to trunk. There's very little tracking. You're just assuming that all the bug fixes on the branch also apply to the trunk.
  • You use a tracking systems that understands issues may live on more than one release. In this case, you simply mark a bug discovered on the branch to trunk too. You can cherry pick changes that apply to trunk thanks to your issue tracking system.
  • Some sites simply don't merge. They also track via the defect tracking system changes that need to be applied to the trunk that were applied on the branch, and simply re-implement them. They might copy changes from the branch to trunk, but they never do a formal merge. However, once you do this, you can't ever merge (unless you merge with the --record-only flag).

You, of course, realize that this method takes something called planning. You must prioritize your work, so the developers do the work for the upcoming release before work on the future release. You only branch once you no longer have enough work on the upcoming release to keep all of your developers busy.

You can implement the standard Git workflow which is using development separate development branches for each developer or issue, and then delivering those changes onto trunk. This would require a lot of branches, one for each developer/feature.

You first merge from the trunk to the branch to rebase your code. Once you've done the rebase, you merge from the branch back to the trunk using the --reintegrate switch. Pre-1.6, you were suppose to delete the branch and recreate it since --reintegrate sort of messed up merge tracking. However, this has been fixed in Release 1.6.x and up.

Solution 2

That's a big question. I only have ideas how to solve some of the problems:

  1. I don't think this can easily be solved without using branches a lot. Not sure if this can be easily solved by using GIT either. Feature branches go a long way in solving this problem, but in general you should probably try to concentrate on features for the next release only.
  2. trunk - I consider it the master branch.
  3. I'd say the development branch is the code for the next release
  4. Seems difficult without using a lot of branches, no idea how to properly solve this.
  5. You could use branches or note the revision number being in TEST and ACC. PROD should be put into a tag I guess.
  6. I'd say using automated regression tests and continuous integration. Also using peer reviews can help here, at best you use some sort of tool to mark a file as reviewed. That way you can ensure that you only merge files that have been reviewed. It could also be interesting to tie your commit messages to your bugtracker, to automatically figure out which files have been touched in relation to which issues, and then make sure all issues are actually closed for the files you want to merge. This is a non trivial task, especially if you are thinking about merging only parts of branches. Thereby, sort of, doing a feature merge.
  7. Use a tag for the release. You can check it out just like a branch and add patches if necessary
  8. List all svn commits for the entire repository on one page (e.g. trac/redmine/jira overview)
  9. Use a local copy I'm afraid/or a branch again. Or make the R&D use git svn locally for research.

Some of these problems can, at least partly, be solved by using git svn. By using it you can for example to experiments locally using gits branch features, without storing those in the global repository. Of course this is not interesting if you are exploring a new feature with many members on a team, unless they are all comfortable with using git and pulling from each other over the network. By using git svn you can also use git cherrypick to hand pick single commits to apply from one branch to another (e.g. development onto released-x.x-tag).

That's all I could come up with for now, hope it helps.

Solution 3

In my activities I use SVN with the following approach.

  1. Trunk is the "master" branch. You should never commit anything directly in the trunk. Trunk always need to match exactly the latest released version in production. So, trunk always represent a stable branch. Trunk is updated only with reintegration of branches.

  2. You need branches for your work. Every new branch has to be created from the trunk, so every new branch match exactly with the production version at creation time. Changes and fixes are committed in the branches.

  3. You should have at least 2 main branches:

    • develop: intended for future developments that are not already planned for release.
    • hotfix: used to commit all bugfix and only fixes. For frequent use, It need to be updated with trunk version when the trunk is updated.
  4. Create a branch for every main stream of work: a project, a subproject, a change request. You can work with parallel developments.

  5. Create "integration" branches to join branches that you have to release. You need to merge into the integration branch every branch candidated to the release. So, integration branch can join both hotfix and a project, for example.

  6. Build your artifacts from integration branches or from the branches self.

  7. When you have released a branch, create the tag for that release, so you can have a copy of the released version and you can still work the branch. In tags you should have only released version. Don't commit changes in the tag!

  8. After a branch is released, you need to update the trunk. So reintegrate the branch in the trunk. You can reintegrate an integration branch, or the branch directly (if you didn't pass from the integration).

  9. When the trunk is again matched with production version, report it in all your active branches.

This method is not really a replica of the git-flow concept, but It follows some of its requirements.

With this approach you can have the following advantages:

  • trunk is stable. You always know what trunk represents at that moment.

  • Every branch contains only its own changes.

  • With integration branches you can manage parallel branches in a single release

  • With tags you always have a copy of a released version

The disadvantages are:

  • Many branches to manage.

  • You need to merge and switch very often, expecially to report changes into integration branches

  • Many conflicts to solve every time

By the way, this is the best approach I ever worked with because It allows you to keep the control of versions.

Share:
11,401
Ryan Taylor
Author by

Ryan Taylor

Updated on June 05, 2022

Comments

  • Ryan Taylor
    Ryan Taylor almost 2 years

    We use Subversion and aside from a few individuals such as myself there is little to no experience with branching and merging in Subversion. My Subversion experience is limited to simple feature branches where merge and tree-conflicts, while not exactly rare, are not exceedingly difficult to resolve.

    Given that, I am helping to manage a project where our current commit to trunk method is simply unsustainable for our needs. I introduced feature branching and merging to my localized team and we had some success. However simple feature branching was still not able to answer all our questions such as:

    1. How do we develop code in parallel for this release and subsequent releases?
    2. What code is considered stable?
    3. What (in development) code is going into the next release?
    4. What (in development) code is going into a subsequent release?
    5. What version of code is our Test, Acceptance, or Production environments?
    6. How do we integrate concurrent development activities with a known stable release to reduce introducing bugs and incomplete work?
    7. How do we provide hot-fixes to released code?
    8. How do we know, from our source control, what development activity is currently ongoing?
    9. How do we experiment or R&D without disrupting the current code base while leveraging?

    It seems that git-flow as defined here would go a long way to answer a lot of these questions. I experimented with this method in Mercurial and it seems like that it is possible to implement this method there as well. Sadly, migrating to a DVCS is off the table at this point.

    However, my brief attempt to mimic this method in Subversion failed with many merge and tree conflicts. The merge options and edge cases are numerous and baffling.

    Can Subversion be used to implement git-flow and if so what is the pain level?

  • Ryan Taylor
    Ryan Taylor over 11 years
    Thanks for the info. This is very helpful and is definitely the direction we seemed to be headed with our internal discussions. However, you mention not merging your releases back into trunk; 'You tag Release 1.2 right on the branch. The branch is not merged back into trunk.' but later you state there will be 'some merging'. In particular 'Once you do a release, you merge enmass all changes on the branch back to trunk.'. Why would you not merge your release back into your trunk? Wouldn't this be necessary to port any bug fixes into the next release?
  • David W.
    David W. over 11 years
    @RyanTaylor What I meant was that the branch isn't merged back to the trunk and the release is done from the trunk. There are places that insist that releases must be done from the trunk. Therefore, the branch is not only merged to the trunk, but the trunk is made to match exactly what's on the branch just so a release can be done off the trunk. You don't do that. There will be changes on the branch that also apply to the trunk. These can be brought back down to the trunk by either merging or by simply applying them without doing an actual merge. Either way will work.
  • lud
    lud about 10 years
    My coworkers doesn't seem to understand the word "planning" when we're talking about VCS
  • Alessandro C
    Alessandro C almost 6 years
    I don't think this is the better approach even if it's marked as the right answer. Trunk has to be used like the master branch in git. Developers need branches in order to work on all possible parallel streams, and "integration" branches are needed to join the branches during the time. When a branch is released, it has to be reintegrated in the trunk. So, trunk always matches with the production environment. Tags have to be intended to create copies of every release. The unstable trunk doesn't allow to manage this kind of behaviour.