Branching/merging strategy when one of multiple changes is not signed-off - version-control

I am trying to come up with a good branching merging strategy for a scenario when multiple features are being tested simultanously and at least one of them is not signed-off by stakeholders. I want to get the signed off changes pushed through to production with the least effort in terms of SCM operations and retesting.
I am using CVS (and I can't change this), but the question is SCM technology agnostic to certain extent.
Imagine that at any given time there are multiple features being developed on a common baseline. They're all worked on in isolation in their own branches. At some stage a build is pushed to test envrionment from the trunk that contains all the finished/tested and merged back to trunk changes. Let's say there are 5 branches merged in total and one is not good enough to pass testing or for some reason is not signed-off by the business.
If there was a silver bullet like 'unmerge' operation it would be perfect, but as far as I know there isn't.
My other idea is not to merge all the changes to trunk but to a separate branch forked off trunk and push a build off that branch to test server. If some change is withdrawn for any reason it would require forking a new branch off trunk and merging all but the withdrawn changes. Once all the changes are accepted this temporary branch can be merged to trunk.
I am wondering if this is not an overkill though.
Any other ideas?

While this doesn't really answer your question as asked, you might want to look into the concepts of feature toggles and "branch by abstraction" as discussed in Continuous Delivery. These are a couple of the core concepts that allow iterative mainline/trunk development.

Related

Best practice for applying a change to two Git branches (Release branch and Development)

I work for a small company that currently has only two developers. I'm not an expert with GitHub and I know that our current workflows aren't necessarily standard. I'm not looking to re-design our whole workflow, just a reasonable solution to this specific challenge:
We have two main branches: Development and Master. We use the Master branch for client installs, so it is always behind Development, until we merge the two before a major release.
Due to the nature of our software and target market, it is important for us to be able to periodically apply custom code for specific clients to the Master branch between releases so that it is ready for their use when we install. We also need to apply these changes to the Development branch so that they are included in the next release. This custom code is included in all future client installs/updates, but only accessible to the specific client based on configuration settings.
My current solution is to create the "Custom Feature" branch based on the Master branch. When the custom work is done, we will create a pull request for both the Master branch and the Development branch. Since the Master branch always has the same code as development, just in an earlier state - this seems to me like it should work. But like I said, I'm not an expert with GitHub and I'm sure this could be dangerous for any number of reasons.
I know it's risky to apply these types of periodic changes to a live release branch. However due to the nature of our software, most of our clients expect at least a small level of customization when we install for them.
Edit
I'm aware this is very similar to this question:
Avoid merging master into development branch
But I'm proposing branching from the release branch rather than the development branch, so I think it's a different case (I'll admit some of the concepts from that question go over my head though). I apologize if this is deemed to be a duplicate.
I recommend getting familiar with GitFlow as it might be a solution to your problem. https://datasift.github.io/gitflow/IntroducingGitFlow.html
Basically, you are right, the correct way to do this is to branch off from master, create the change in the branch and then merge to master and develop. Follow the "hotfix" section in the attached link.

Perforce and Feature Branching

At our company we use Perforce for our source control and version management. Currently we implement feature branching with the following "tree"
Hotfix01 - Hotfix branch
Hotfix02 - Hotfix branch
HotfixNN - Hotfix branch
Main (continuous trunk)
RC - Release Candidate branch (next release)
Working01 - Working branch, feature branch.
Working02 - Working branch, feature branch.
Working03 - Working branch, feature branch.
WorkingNN - Working branch, feature branch.
We setup the branches ahead of time. Not that this really matters. Branches off RC are feature branches. Right now we have >50 developers, Analysts and QA team members that are working individually or as a team on various projects, defect fixes, etc. When work comes in you find a free branch (we track that separately), claim that branch (e.g. Working56), do a force merge/sync from RC to that branch (to make sure it's exactly what's in RC at that moment), do your work (code, peer review, QA) while continuously merging any changes from RC to your working branch (at least once per day, perhaps more often as needed) and when you are done you copy the changes up to RC.
This works, but it means we have (at this time) 300 working branches to manage. We would like to implement feature branching in a more sane way where we would use branch mapping and such to create a branch as needed, named after what it's for and then once we merge it back to RC we want it to no longer show up in the depot forever (at least, not for every developer). Basically we want to see only those branches with active development as feature branches, hiding branches we are done with.
What is the best practice? Can this be done with perforce using either branches or streams? Are we missing something with Branch specifications that would allow this? Should we just not worry and allow thousands or tens of thousands of feature branches to pile up in the depot view under RC? Is the way we are doing it now the best we can hope for?
We've been using Perforce for 10 years and this is still a question that haunts us daily.
Task streams are designed for this.
https://www.perforce.com/perforce/doc.current/manuals/p4v/streams_task.html
Create the task stream, do your work in it, merge/copy back to the parent, then unload the task stream.
Common task stream gotchas:
Do not try to reuse or reparent them. One stream per task! If you try to reuse task streams their beneficial features mostly don't work but you still get all of the limitations.
The modified depot files live on after the task stream is unloaded. Adjust your mental model to use the list of streams as the source of truth for which streams are active, not the folders in the depot tree.
If you can handle those, task streams are hugely useful.

Simulate a tfs style changeset in the enterprise version of github

I have three environments; dev, test and staging/prod. In our previous model of using Team Foundation Server, we would have three branches of code that matched up to each of these three environments.
Developers would work locally and when they had their code complete, they'd check it into the dev branch. When checking in, TFS automatically creates something called a changeset. This check-in would kick off a build of the files into code which then gets deployed to the dev environment.
When a developer was happy with their code in dev, they'd merge just their changeset into the test branch. They'd pull up a complete list of all of the available changesets that dhad not been merged into test, they'd select theirs and check those into the test branch. Again, this would kick off a build and the output files would get deployed to test.
Once QA was happy with the changes, the dev would merge this changeset into the prod branch. Kicking off a build and the files would be deployed to the staging area. The developer and QA would them promote these files to prod.
All of would allow multiple developers to work on the same files using this changeset mentality. When a specific changeset (or set of changesets) was merged into another environment, only those changes would get merged.
In my relatively new exposure to git, I cannot seem to find a way to select specific "pull requests" (which I assume is similar to a TFS changeset) from one branch to another branch. When I try to make a pull request from one branch to another branch, it wants to pull in not only my pull request, but every other pull request made in the lower branch by other developers too. What is the magic way to make this happen?
Note: Unfortunately we don't have the notion of a "release". We have five scrum teams working on one website with over 200 pages. Each scrum team has their own sprints and can release multiple scrum stories during their sprint. We have internally only one DEV environment, and one TEST environment and one PROD environment. Not only are our environments used by these five scrum teams, but these DEV/TEST/PROD sites are is also used by various other teams for integration efforts with applications we sell and also for customer account management and purchasing. We cannot change that infrastructure.
Note: this is not for a discussion as to if this "changeset" methodology is correct or proper. This is a question of how to achieve this behavior in github/git.
Note: we are a set of scrum-based agile teams. We work from stories. As many as 60 stories can be actively in development at any one time with our large team of 25+ developers. When one story is ready for prod, we promote it to the prod environment as an atomic unit. So think of a changeset as a story.
I have two thoughts:
Don't do it this way. Instead, you should look to git-flow. http://danielkummer.github.io/git-flow-cheatsheet/ and http://nvie.com/posts/a-successful-git-branching-model/ are good explanations. At it's core, git-flow is a naming convention for branches, so it's really not tied to git at all. In essence, you have feature branches that each developer or dev team works on. Once they complete a feature, they merge into develop. develop is "done features" -- not "done done" but rather "feature complete." When we deem it time to release, we fork to a new release/someversion branch (name to match the release name), and then work with QA to harden the release. Commits on the release/someversion branch are only bug fixes. Once it's good enough to deploy, we fast-forward the master branch up to the release branch as we push it into production. master then represents what's in production. As we deploy, we also merge release/someversion into develop so the bug fixes get into the mainline of development. The project manager / product owner can then think of the develop branch as "the latest," and developers can continue on their feature branches until they're feature complete. (Hint, make features small -- like an hour or a day. Features are not releases.)
So why is this better than the way you were doing it? If the feature is done, ready enough for QA to start banging on it, it's done enough to be part of the next release. Picking and choosing features around each other will lead you into very subtle and unpredictable bugs. Since you're re-merging at each step, you have the possibility that you'll merge incorrectly, creating a bug. You're also now creating unique product with each step, so you could get to production with a completely different set of features than you vetted in dev and test. (Will this do bad things? Ask your pharmacist if these drugs interact when taken together.)
Git-flow works great for cadences where you have well coordinated, infrequent, larger releases. As you get closer to continuous delivery, this ceremony will get in your way. At that point, you may choose to flip to GitHub flow or a similar lighter-weight naming convention.
If you're really, really, really (see the above "you shouldn't do it this way" comment) convinced you should do it this way, first, go convince a rubber duck and hopefully you will have talked yourself out of it. If you're still really, really convinced you need to do this, you'll frequently need to squash your commits together creating one large commit for the entire feature, then cherry pick the changeset between the branches.
There's a few disadvantages to this "squash and cherry-pick" approach. 1. You lose history. Since you're squashing the history together, you have to now keep features in very contained bundles, and frequently edit the bundle as a whole. One of the primary premises of source control is you get an audit history -- both to roll back to if something goes wrong, and to reference when you need to learn why something works this way or who to talk to about it. (See "git blame".) When you squash, you intentionally remove that learning tool. 2. You're playing features into place in different orders. So you're frequently doing merges. What makes git so awesome is merging is easy. What makes git merging easy is you do it in small pieces. This methodology of squashing everything associated with this feature into one huge commit and cherry-picking it between branches means you're doing very large merges ... which means it will be hard.
Yeah, I know you're quite enamored with the way it's always been, and you really don't want someone telling you your baby is ugly. Sorry. Your baby was ugly. On the bright side, it doesn't need to be. Git flow is awesome, and can definitely facilitate the velocity your team needs.
You previous behavior was dysfunctional. Although not unusual: http://nakedalm.com/avoid-pick-n-mix-branching-anti-pattern/
In Git you most likely want to do two things. The first is to follow Git Flow: http://nvie.com/posts/a-successful-git-branching-model/
Once you have this you can look at creating a deployment pipeline for binaries, not for source. You should do a build from MASTER and that build goes through your environments. Happy to discuss here and offline.

Do you feel comfortable merging code?

This morning, I read two opinions on refactoring.
Opinion 1 (Page not present)
Opinion 2 (Page not present)
They recommend branching (and subsequently merging) code to:
Keep the trunk clean.
Allow a developer to walk away from risky changes.
In my experience (particularly with Borland's StarTeam), merging is a non-trival operation. And for that reason, I branch only when I must (i.e. when I want to freeze a release candidate).
In theory, branching makes sense, but the mechanics of merging make it a very risky operation.
My questions:
Do you feel comfortable merging code?
Do you branch code for reasons other than freezing a release
candidate?
Branching might be painful but it shouldn't be.
That's what git-like projects (mercurial, bazar) tells us about CVS and SVN. On git and mercurial, branching is easy. On SVN it's easy but with big projects it can be a bit hardcore to manage (because of time spent on the branching/merging process that can be very long -- compared to some others like git and mercurial -- and difficult if there are non-obvious conflicts). That don't help users that are not used to branch often to have confidence in branching. Lot of users unaware of the powerful uses of branching just keep it away to not add new problems to their projects, letting the fear of the unknown make them far from efficiency.
Branching should be an easy and powerful tool we'd have to use for any reason good enough to branch.
Some good reasons to branchs:
working on a specific feature in parallel with other people (or while working on other features alternatively if you're alone on the project);
having several brand versions of the application;
having parallel versions of the same application -- like concurrent techniques developped in the same time by to part of the team to see what works the better;
having resources of the application being changed on a artist/designers (for example in games) specific branch where the application is "stable" while other branches and trunk are used for features addition and debugging;
[add here useful usages]
Some loose guiding principles:
Branch late and only when you need to
Merge early and often
Get the right person to do the merge, either the person who made the changes or the person who wrote the original version are best
Branching is just another tool, you need to learn how to use it effectively if you want the maximum benefit.
Your attitude to branching should probably differ between distributed open source projects (such as those on Git) and your company's development projects (possibly running on SVN). For distributed projects you'll want to encourage branching to maximize innovation and experimentation, for the latter variety you'll want tighter control and to dictate checkin policies for each code line that dictate when branching should / should not occur, mostly to "protect" the code.
Here is a guide to branching:
http://www.vance.com/steve/perforce/Branching_Strategies.html
Here is a shorter guide with some high level best practices:
https://www.perforce.com/pdf/scm-best-practices.pdf
Branching is trivial. Merging is not. For that reason, we rarely branch anything.
Using SVN, I've found branching to be relatively painless. Especially if you periodically merge the trunk into your branch to keep it from getting too far out of sync.
We use svn. It only takes us about 5 minutes to branch code. It's trivial compared to the amount of pain it saves us from messing up trunk.
Working in a code base of millions of lines of code with hundreds of developers branching is an everyday occurrence. The life of the branch varies depending on the amount of work being done.
For a small fix:
designer makes a sidebranch off the main stream
makes changes
tests
reviews
merges accumulated changes from main stream to sidebranch
iterates through one or more of the previous steps
merges back to main stream
For a multi-person team feature:
team makes a feature sidebranch off the main stream
individual team member operates on feature sidebranch as in "small fix" approach and merges to feature sidebranch.
sidebranch prime periodically merges accumulated changes from main stream to feature sidebranch. Small incremental merges from the mainstream to feature sidebranch are much easier to deal with.
when feature works, do final merge from main stream to feature sidebranch
merge feature sidebranch to main stream
For a customer software release:
make a release branch
deliver fixes as needed to release branch
fixes are propogated to/from the main stream as needed
Customer release streams can be very expensive to support. Requires testing resources - people and equipment. After a year or two, developer knowledge on specific streams starts to get stale as the main stream moves forward.
Can you imagine how much it must cost for Microsoft to support XP, Vista and Windows 7 concurrently? Think about the test beds, the administration, documentation, customer service, and finally the developer teams.
Golden rule: Never break the main stream since you can stall a large number of developers. $$$
The branching problem is why I use a Distributed Version Control system (Git in my case, but there are also Mercurial and Bazaar) where creating a branch is trivial.
I use short lived branches all the time for development. This lets me mess around in my own repository, make mistakes and bad choices, and then rebase the changes to the main branch so only clean changes are kept in history.
I use tags to mark frozen code, and it is easy in these systems to go back and branch off these for bug fixes without having a load of long lived branches in the code base.
I use Subversion and consider branching very simple and easy. So to answer question 1.. Yes.
The reason for branching can vary massively. I branch if I feel I should. Quite hard to put rules and reasons down for all possibilities.
However, as far as the "Allow a developer to walk away from risky changes." comment. I totaly agree with that one. I create a branch whenever I want to really play around with the code and wish I was the only developer working on it.. When you branch, you can do that...
I've been on a project using svn and TFS and branching by itself is a really simple thing.
We used branching for release candidate as well as for long lasting or experimental features and for isolating from other team's interference.
The only painful moment in branching is merging, because an old or intensely developed branch may differ a lot from trunk and might require significant effort to merge back.
Having said the above, I would say that branching is a powerful and useful practice which should be taken into account while developing.
If merging is too much of a pain, consider migrating to a better VCS. That will be a bigger pain, but only once.
We use svn and have adopted a rule to branch breaking changes. Minor changes are done right in the trunk.
We also branch releases.
Branching and merging have worked well for us. Granted there are times we have to sit and think about how things fit together, but typically svn does a great job of merging everything.
I use svn, it takes less than a minute to branch code. I used to use Clearcase, it took less than a minute to branch code. I've also used other, lesser, SCMs and they either didn't support branches or were too painful to use. Starteam sounds like the latter.
So, if you cannot migrate to a more useful one (actually, I've only heard bad things about Starteam) then you might have to try a different approach: manual branching. This involves checking out your code, copying it to a different directory and then adding it as a new directory. When you need to merge, you'd check out both directories and use WinMerge to perform the merge, checking in the results to the original directory. Awkward and potentially difficult if you continue to use the branch, but it works.
the trick with Branching is not to treat it as a completely new product. It is a branch - a relatively short-lived device used to make changes separately and safely to a main product trunk. Anyone who thinks merging is difficult is either refactoring the code files so much (ie they are renaming, copying, creating new, deleting old) that the branch becomes a completely different thing, or they are keeping the branch so long that the accumulated changes bear little resemblance to the original.
You can keep a branch for a long time, you just have to merge your changes back regularly. Do this and branching/merging becomes very easy.
I've only done it a couple times, so I'm not exactly comfortable with it.
I've done it to conduct design experiments that would span over some checkins, so branching is an easy way to wall off yourself a garden to play in. Also, it allowed me to tinker while other people worked on the main branch, so we didn't lose much time.
I've also done it when making wide ranging changes that would render the trunk uncompilable. It became clear in my project that I'd have to remove compile-time type safety for a large portion of the codebase (go from generics to system.object). I knew this would take a while and would require changes all over the codebase which would interfere with other people's work. It would also break the build until I was complete. So I branched and stripped out the generics, working until that branch compiled. I then merged it back into the trunk.
This turned out pretty well. Prevented a lot of toe-stepping, which was great. Hopefully nothing like this will ever come up again. Its kind of a rare thing that a design will change requiring this kind of wide ranging edits that don't result in a lot of code being thrown out...
Branched have to be managed correctly to make merging painless. In my experience (with Perforce) regular integration to the branch from the main line meant that the integration back into the main line went very smoothly.
There were only rare occasions when the merging failed. The constant integration from the main line to the branch may well have involved merges, but they were only of small edits that the automatic tools could handle without human intervention. This meant that the user didn't "see" these happening.
Thus any merges required in the final integration could often be handled automatically too.
Perforces 3-way merge tools were a great help when they were actually needed.
Do you feel comfortable branching code?
It really depends of the tool I'm using. With Starteam, branching is indeed non trivial (TBH, Starteam sucks at branching). With Git, branching is a regular activity and is very easy.
Do you branch code for reasons other than freezing a release candidate?
Well, this really depends of your version control pattern but the short answer is yes. Actually, I suggest to read the following articles:
Version Control for Multiple Agile Teams by Henrik Kniberg
FeatureBranch by Martin Fowler
I really like the pattern described in the first article and it can be applied with any (non Distributed) Version Control System, including Starteam.
I might consider the second approach (actually, a mix of the both strategies) with (and only with) a Distributed Version Control Systems (DVCS) like Git, Mercurial...
We use StarTeam and we only branch when we have a situation that requires it (i.e. hotfix to production during release cycle or some long reaching project that spans multiple release windows). We use View Labels to identify releases and that makes it a simple matter to create branches later as needed. All builds are based on these view labels and we don't build non-labeled code.
Developers should be following a "code - test - commit" model and if they need a view for some testing purpose or "risky" development they create it and manage it. I manage the repository and create branches only when we need them. Those times are (but not limited to):
Production hotfix
Projects with long or overlapping development cycles
Extensive rewriting or experimental development
The merge tool in StarTeam is not the greatest, but I have yet to run into an issue caused by it. Whoever is doing the merge just needs to be VERY certain they know what they're doing.
Creating a "Read Only Reference" view in Star Team and setting it to a floating configuration will allow changes in the trunk to automatically show in the branch. Set items to branch on change. This is good for concurrent development efforts.
Creating a "Read Only Reference" view with a labeled configuration is what you'd use for hot fixes to existing production releases (assuming you've labeled them).
Branching is trivial, as most have answered, but merging, as you say, is not.
The real keys are decoupling and unit tests. Try to decouple before you branch, and keep an eye on the main to be sure that the decoupling and interface are maintained. That way when it comes time to merge, it's like replacing a lego piece: remove the old piece, and the new piece fits perfectly in its place. The unit tests are there to ensure that nothing got broken.
Branching and merging should be fairly straightforward.
I feel very comfortable branching/merging.
Branching is done for different reasons, depending on your development process model/
There's a few different branch models:
Here's a one
Trunk
.
.
.
..
. ....
. ...
. ..Release1
.
.
...
. ....
. ...Release2
.
.
..
. ...
. ..
. ...Release3
.
.
Now here's a curious thing. Suppose Release1 needed some bugfixing. Now you need to branch Release1 to develop 1.1. That is OK, because now you can branch R1, do your work, and then merge back to R1 to form R1.1. Notice how this keeps the diffs clear between releases?
Another branching model is to have all development done on the Trunk, and each release gets tagged, but no further development gets done on that particular release. Branches happen for development.
Trunk
.
.
.
.Release1
.
.
.
.
.Release2
.
.......
. ......
. ...DevVer1
. .
. .
. ...DevVer2
. ....
. ....
...
.Release3
.
There may be one or two other major branch models, I can't recall them off the top of my head.
The bottom line is, your VCS needs to support flexible branching and merging.
Per-file VCS systems present a major pain IMO(RCS, Clearcase, CVS).
SVN is said to be a hassle here as well, not sure why.
Mercurial does a great job here, as does(I think)git.

Do you continue development in a branch or in the trunk? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Suppose you're developing a software product that has periodic releases. What are the best practices with regard to branching and merging? Slicing off periodic release branches to the public (or whomever your customer is) and then continuing development on the trunk, or considering the trunk the stable version, tagging it as a release periodically, and doing your experimental work in branches. What do folks think is the trunk considered "gold" or considered a "sand box"?
I have tried both methods with a large commercial application.
The answer to which method is better is highly dependent on your exact situation, but I will write what my overall experience has shown so far.
The better method overall (in my experience): The trunk should be always stable.
Here are some guidelines and benefits of this method:
Code each task (or related set of tasks) in its own branch, then you will have the flexibility of when you would like to merge these tasks and perform a release.
QA should be done on each branch before it is merged to the trunk.
By doing QA on each individual branch, you will know exactly what caused the bug easier.
This solution scales to any number of developers.
This method works since branching is an almost instant operation in SVN.
Tag each release that you perform.
You can develop features that you don't plan to release for a while and decide exactly when to merge them.
For all work you do, you can have the benefit of committing your code. If you work out of the trunk only, you will probably keep your code uncommitted a lot, and hence unprotected and without automatic history.
If you try to do the opposite and do all your development in the trunk you'll have the following issues:
Constant build problems for daily builds
Productivity loss when a a developer commits a problem for all other people on the project
Longer release cycles, because you need to finally get a stable version
Less stable releases
You simply will not have the flexibility that you need if you try to keep a branch stable and the trunk as the development sandbox. The reason is that you can't pick and chose from the trunk what you want to put in that stable release. It would already be all mixed in together in the trunk.
The one case in particular that I would say to do all development in the trunk, is when you are starting a new project. There may be other cases too depending on your situation.
By the way distributed version control systems provide much more flexibility and I highly recommend switching to either hg or git.
I've worked with both techniques and I would say that developing on the trunk and branching off stable points as releases is the best way to go.
Those people above who object saying that you'll have:
Constant build problems for daily builds
Productivity loss when a a developer commits a problem for all
other people on the project
have probably not used continuous integration techniques.
It's true that if you don't perform several test builds during the day, say once every hour or so, will leave themselves open to these problems which will quickly strangle the pace of development.
Doing several test builds during the day quickly folds in updates to the main code base so that other's can use it and also alerts you during the day if someone has broken the build so that they can fix it before going home.
As pointed out, only finding out about a broken build when the nightly build for running the regression tests fails is sheer folly and will quickly slow things down.
Have a read of Martin Fowler's paper on Continuous Integration. We rolled our own such system for a major project (3,000kSLOC) in about 2,000 lines of Posix sh.
I tend to take the "release branch" approach. The trunk is volatile. Once release time approaches, I'd make a release branch, which I would treat more cautiously. When that's finally done, I'd label/tag the state of the repository so I'd know the "official" released version.
I understand there are other ways to do it - this is just the way I've done it in the past.
Both.
The trunk is used for the majority of development. But it's expected that best efforts will be made to ensure that any check-in to the trunk won't break it. (partially verified by an automated build and test system)
Releases are maintained in their own directory, with only bug fixes being made on them (and then merged into trunk).
Any new feature that is going to leave the trunk in an unstable or non-working state is done in it's own separate branch and then merged into the trunk up on completion.
I like and use the approach described by Henrik Kniberg in Version Control for Multiple Agile Teams. Henrik did a great job at explaining how to handle version control in an agile environment with multiple teams (works for single team in traditional environments too) and there is no point at paraphrasing him so I'll just post the "cheat sheet" (which is self explaining) below:
I like it because:
It is simple: you can get it from the picture.
It works (and scales) well without too much merge and conflict troubles.
You can release "working software" at any time (in the spirit of agile).
And just in case it wasn't explicit enough: development is done in "work branch(es)", the trunk is used for DONE (releasable) code. Check Version Control for Multiple Agile Teams for all the details.
A good reference on a development process that keeps trunk stable and does all work in branches is Divmod's Ultimate Quality Development System. A quick summary:
All work done must have a ticket associated with it
A new branch is created for each ticket where the work for that ticket is done
Changes from that branch are not merged back into the mainline trunk without being reviewed by another project member
They use SVN for this, but this could easily be done with any of the distributed version control systems.
I think your second approach (e.g., tagging releases and doing experimental stuff in branches, considering the trunk stable) is the best approach.
It should be clear that branches inherit all the bugs of a system at the point in time where it is branched: if fixes are applied to a trunk, you will have to go one by one to all branches if you maintain branches as a sort of release cycle terminator. If you have already had 20 releases and you discovered a bug that goes as far back as the first one, you'll have to reapply your fix 20 times.
Branches are supposed to be the real sand boxes, although the trunk will have to play this role as well: tags will indicate whether the code is "gold" at that point in time, suitable for release.
We develop on the trunk unless the changes are too major, destabilizing, or we are nearing a major release of one of our products, in which case we create a temporary branch. We also create a permanent branch for every individual product release. I found Microsoft's document on Branching Guidance quite helpful. Eric Sink's tutorial on branching is also interesting, and points out that what works for Microsoft may be too heavy for some of the rest of us. It was in our case, we actually use the approach Eric says his team does.
It depends on your situations. We use Perforce and have typically have several lines of development. The trunk is considered "gold" and all development happens on branches that get merged back to the mainline when they are stable enough to integrate. This allows rejection of features that don't make the cut and can provide solid incremental capability over time that independent projects/features can pick up.
There is integration cost to the merging and catching up to new features rolled into the trunk, but you're going to suffer this pain anyway. Having everyone develop on the trunk together can lead to a wild west situation, while branching allows you to scale and choose the points at which you'd like to take the bitter integration pills. We're currently scaled to over a hundred developers on a dozen projects, each with multiple releases using the same core components, and it works pretty well.
The beauty of this is that you can do this recursively: a big feature branch can be its own trunk with other branches coming off if it. Also, final releases get a new branch to give you a place to do stable maintenance.
Attempting to manage maintenance of current production code in line with new development is problematic at best. In order to mitigate those problems code should branch into a maintenance line once testing efforts have completed and the code is ready for delivery. Additionally, the mainline should branch to assist in release stabilization, to contain experimental development efforts, or to house any development efforts whose lifecycle extends across multiple releases.
A non-maintenance branch should be created only when there is the likelihood (or certainty) of collisions among the code that would be difficult to manage any other way. If the branch does not solve a logistical problem, it will create one.
Normal release development occurs in the mainline. Developers check into and out of the mainline for normal release work. Development work for patches to current Production code should be in the branch for that release and then merged with the mainline once the patch has passed testing and is deployed. Work in non-maintenance branches should be coordinated on a case-by-case basis.
It depends on the size of your development effort. Multiple teams working in parallel won't be able to work effectively all on the same code (trunk). If you have just a small group of people working and your main concern is cutting a branch so you can continue to work while going back to the branch for making bug-fixes to the current production code that would work. This is a trivial use of branching and not too burdensome.
If you have a lots of parallel development you'll want to have branches for each of the efforts but that'll also require more discipline: Making sure your branches are tested and ready to merge back. Scheduling merges so two groups aren't trying to merge at the same time etc.
Some branches are under development for so long that you have to permit merges from the trunk to the branch in order to reduce the number of surprises when finally merging back to the trunk.
You will have to experiment if you have a large group of developers and get a feel for what works in your situation. Here is a page from Microsoft that may be somewhat useful: http://msdn.microsoft.com/en-us/library/aa730834(VS.80).aspx
We are using the trunk for main development and branch for releases maintenance work. It works nice. But then branches should only be used for bug fixes, no major changes, especially on database side, we have a rule that only a schema change can happen on the main trunk and never in the branch.
If you are gonna be working through a release cycle, big feature, you get marooned to a branch. Otherwise we work in trunk, and branch for every production release at the moment we build.
Previous production builds are moved at that time to old_production_ and current prod release is always just production. All our build server knows about production is how to deploy the production branch, and we kick that build off with a force trigger.
We follow the trunk=current development stream, branch=release(s) approach. On release to the customer we branch the trunk and just keep the trunk rolling forward. You'll need to make a decision on how many releases you're prepared to support. The more you support the more merging you'll be doing on bug fixes. We try and keep our customers on no more than 2 releases behind the trunk. (Eg. Dev = 1.3, supported releases 1.2 and 1.1).
The trunk is generally the main development line.
Releases are branched off and often times experimental or major work is done on branches then merged back to the trunk when it's ready to be integrated with the main development line.
The trunk should generally be your main development source. Otherwise you will spend a lot of time merging in new features. I've seen it done the other way and it usually leads to a lot of last minute integration headaches.
We label our releases so we can quickly respond to production emergencies without distribing active development.
For me, it depends on the software I'm using.
Under CVS, I would just work in "trunk" and never tag/branch, because it was really painful to do otherwise.
In SVN, I would do my "bleeding edge" stuff in trunk, but when it was time to do a server push get tagged appropriately.
I recently switching to git. Now I find that I never work in trunk. Instead I use a named "new-featurename" sandbox branch and then merge into a fixed "current-production" branch. Now that I think about it, I really should be making "release-VERSIONNUMBER" branches before merging back into "current-production" so I can go back to older stable versions...
It really depends on how well your organization/team manages versions and which SCM you use.
If what's next(in the next release) can be easily planned, you are better off with developing in the trunk. Managing branches takes more time and resources. But if next can't be planned easily(happens all the time in bigger organizations), you would probably end up cherry picking commits(hundreds/thousands) rather than branches(severals or tens).
With Git or Mercurial, managing branches is much easier than cvs and subversion. I would go for the stable trunk/topic branches methodlogy. This is what the git.git team using. read:http://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html
With Subversion, I first applied the develop-in-the-trunk methodlogy. There was quite some work when it came to release date because everytime I had to cherry pick commits(my company is no good at planning). Now I am sort of expert in Subversion and know quite well about manaing branches in Subversion, so I am moving towards the stable trunk/topic branches methodlogy. It works much better than before. Now I am trying the way how git.git team works, although we will probably stick with Subversion.
Here is the SVN design that I prefer:
root
development
branches
feature1
feature2
...
trunk
beta
tags
trunk
release
tags
trunk
All work is done from development/trunk, except for major features that require its own branch. After work is tested against development/trunk, we merge tested issues into beta/trunk. If necessary, code is tested against the beta server. When we are ready to roll some changes out, we just merge appropriate revisions into release/trunk and deploy.
Tags can be made in the beta branch or the release branch so we can keep track of specific release for both beta and release.
This design allows for a lot of flexibility. It also makes it easy for us to leave revisions in beta/trunk while merging others to release/trunk if some revisions did not pass tests in beta.
There's no one-size-fits-all answer for the subversion convention question IMHO.
It really depends on the dynamics of the project and company using it. In a very fast-paced environment, when a release might happen as often as every few days, if you try to religiously tag and branch, you'll end up with an unmanageable repository. In such an environment, the branch-when-needed approach would create a much more maintainable environment.
Also - in my experience it is extremely easy, from a pure administrative standpoint, to switch between svn methodologies when you choose to.
The two approaches I've known to work best are the branch-when-needed, and the branch-each-task. These are, of course, sort of the exact opposite of one another. Like I said - it's all about the project dynamics.