Branch-per-feature workflow using Mercurial - version-control

We have team of 10 developers who works parallel for different features, sometimes these features use common code sometime no.
And now we're changing our process to branch-per-feature and it seems mercurial is more suitable for such development.
I see this process so:
1. make release branch (r-b) from default(trunk)
2. make feature branch (f-b) from default(trunk)
When developer thinks his feature is done he can merge f-b to r-b. When it's time to go to QA we merge all finished f-b to r-b and create release for our QAs.
Questions:
When QA finds a bug developer should modify his f-b and merge it again to r-b. Does it mean that developer just switch to his f-b and start fixing the bug and then makes simple merge f-b to r-b again?
When release is passed QA it goes to PROD - how can we freeze changes? "hg tag" is good choice but someone can update tag if he really wants it.
Thanks

If you're going to merging into specific release branches then your feature branches should be branched from the release branch, not the trunk. It is simpler to merge with the parent branch than a non-parent branch.
1) If you really want to do feature branches then each bug would have its own branch. This will help keep bug fixes separate from new features. After all, it's branch-per-feature not branch-per-developer.
2) Hg tag is what I have used. You are right that someone change move a tag if they really want to, but tags are versioned and you can install hooks on the main hg repo to throw alerts if a tag is moved. I really wouldn't worry about tags being moved unless you can't trust your developers, in which case you are screwed.

The answer to your first question is 'yes'.
The best way to freeze for release is to have a separate release clone that only the release manager can push/pull changesets to. Just because you're using branches doesn't mean multiple-clones don't have a place in your workflow. Have a clone that QA does final pre-flight testing on to which developers can't push changes makes for a great firewall.
Also, consider using bookmarks for your feature branches. Since, as I'm sure you know, Mercurial named branch names never go away the git-like bookmarks work well for sort lived concepts like features and bugs.

Related

Mercurial-like named branches experience in Perforce

I am new to Perforce and find it really hard to follow its workflow..
I have used Mercurial before (not in any advanced ways), but what I lack most in Perforce is the idea of named branches.
Let me explain what I'd like to do:
I get the latest revisions of all files and want to work on a new feature/story/task..
I create a brach, say "Feature 3021"
I code, save changes in this branch (hg commit)
I can save changes to a central server (hg push)
When I'm done coding, I merge the changes from "Feature 3021" with the main branch (default, master, etc.) - after that the main branch has the code I wrote
I can close the named brach ("Feature 3021") so that further commits are not possible.
I don't need this exact behavior in Perforce, but something analogous. I know that Perforce is centralized, so the commit-push step would be probably one, but this is a minor problem here.
All I care is to be able to save my work in version control at any time, even if it's not 100% ready - perhaps to a different branch. I'd also like other users to be able to be able to get my code (from this different branch), but only if they want this - the default branch should stay unafected as long as I don't merge my changes with it.
Is it possible? I am using Server 2012.2
Can you upgrade to Server 2013.1 or later? There's a great feature there, called Task Streams.
Here's some references:
http://www.perforce.com/blog/130627/task-streams-even-if-you-are-classic-perforce-shop
http://www.perforce.com/blog/130206/task-streams
http://www.perforce.com/perforce/doc.current/manuals/p4v/streams_task.html
The analogous flow in Perforce would be:
Maintain a main-line "branch" at some path, say //depot/default
To create a feature branch, integrate from //depot/default to //depot/feature-3021
Work under //depot/feature-3021 and submit
When you are ready to merge back, integrate //depot/feature-3021 to //depot/default
Regarding closing the branch after its use, there are a couple of options that I can think of. You could either change permissions or simply delete it. The delete could always be recovered.
Also note the paths don't need to be at the same hierarchy. A more reasonable branch strategy might use paths like this.
Main-line: //depot/default
Developer branches: //depot/dev/${user}/${feature}

Subversion in Eclipse - Switching branch with uncommitted work in repository

Suppose I have the following senario:
Trunk is my main development line where programmers commit to when done.
Branch V1.0 is a branch I created when releasing version 1.0.
The programmer is working on the trunk but needs to switch to the branch in order to fix bugs.
When switching back to the trunk Subversion will give me the latest in the SVN repository which does not include the recent changes.
So, in order to switch he will have to commit what he has because otherwise the changes are "lost". I know they are still kept in the local repository but it would still mean restoring them one by one once he switchesback.
Am I missing something here?
Edit:
Now I am thinking down these lines:
Each programmer would have his own "private" development branch off of the trunch. He could commit to there whenever he wants. When he has finished what he has written he can them merge it into the trunk. He starts again for the next assignment.
If at any point he is required to fix a bug in some other release he can just commit to his own private branch, fetch the odl release and fix it. Then, after committing the changes to the fix, he can easily switch back to his own development branch.
Would that work?
I think that subversion is not thought for switching as you described. A solution would be to have two workspaces, one for the branch and another one the trunk, so you can switch from one to another without problems. I know it is not a nice one.
Consider switching to a version control tool that is better suited for your approach. My own suggestion is Mercurial, coupled with MercurialEclipse. The only drawbacks I'm aware of are that Subversion is better suited to store binary files and that Mercurial's subrepositories don't work so well as Subversion's externals.
In Mercurial your programmers would be able to commit their changes to their private repositories, merge and commit locally again, and then push the resulting changes to an official repository, from which other programmers would pull them into their own private repositories.
The best solution for such purposes is to have two separate working copies. One for working with trunk and one working with the branch.

Managing code in Mercurial: how to revert individual files, "tag" it and be able to maintain it

Update: We ended up using a process very much like this schema (thanks to neuro for the link). We massaged out repository into a state where default is stable (and has the same code as our production environment), we have a dev branch, feature branches for new stuff and use release branches for releases. All seems to be working perfectly.
Backstory
Our team has recently switched from using SVN (using ToroiseSVN Windows client) to Mercurial (using TortoiseHg Windows client) for version control. We have successfully exported our SVN repository and imported it into a Mercurial repository.
We now have a Mercurial repository where we can see the entire history of revisions (changesets in Mercurial).
How we did it in the old days
Life was simpler in the old days; our development process was not really multi-stream like it is now. The trunk was used to hold all code - even changes that were still in-flight (as long as it didn't break the trunk). When it came to managing releases with SVN, we would checkout the trunk (which holds all code), revert the individual changes we didn't want as part of the release, and create a tag for it.
Cherrypicking the code we want with SVN was easy. Bug-fixing previous releases and ensuring it was part of the trunk was simple too.
What we are doing now
In Mercurial, we need to be able to get a snapshot of the "trunk" (default in Mercurial) with individual changes reverted out. We can do this using hg revert.
To snapshot this, we have created a "named branch" - let's call it Build-4.0.1 for now.
Where the challenge arises
Development continues on default as normal when a bug is found in Build-4.0.1. Let's assume the bug is in one of the reverted files. We change the code from the branch for Build-4.0.1, create a new "named branch" (Build-4.0.2) and want to merge it back into default without pushing the reverted code over the top of newer code. How can we accomplish this?
Alternatively, is there a better workflow for managing the releases and our code in Mercurial? I quite like the look of this wonderful SO answer on managing release branches, although I am not sure how we can transition to it from the state we are in now (with in-flight stuff in default).
Note: I have looked at the Transplant extension, but haven't used it yet - could it be part of the solution to this challenge?
Well, to begin with, your use of revert seems strange to me. Usually it is used to revert modifications done to the working copy back to the version of the repository.
The usual way to get the working copy to some point backward is to update :
hg update -r 1234
from there, you can tag, modify, commit, etc.
To merge back you only have to merge your release branch to the default branch. It will work like a charm, unless it is to different/old a release.
Transplant works fine, but do something a bit different from merge : it take your changeset as a "diff" and apply it as a new modification.
To manage your releases, you can look this other answer (by me) :
How to use mercurial for release management?
What we use is a clone / main branch that holds the most stable version, which is released at some points. On this clone : branch, we can fix critical bugs (hotfix). In parallel, we use a dev clone / branch to develop. The hotfixes are merge as soon as completed from stable to dev. When the current development is done, we merge the dev on stable / default.
This schema is pretty good to understand things :)
Good luck !
Going through all the changes and taking out the ones you don't want is not a common way of creating a release, to put it mildly. The Common Branching Patterns section in the SVN book suggest some more popular work flows:
release branches: create release branch from unstable trunk, fix bugs to stabilize it, cherry pick bug fixes between them while the branch is in maintenance mode.
feature branches: keep the trunk stable and ready for release by only merging in the feature branches that you want
The second one is probably the best fit here, because it gives you a place to put experimental or risky changes until you feel confident about them - these are the changes you would have reverted before a release in your old workflow.
Both of these branching patterns should carry over just fine to mercurial. In case you go for the first approach, note that mercurial (since 2.0) now has a graft command, you no longer need the transplant extension.

Branching and Merging Strategies

I have been tasked with coming up with a strategy for branching, merging and releasing over the next 6 months.
The complication comes from the fact the we will be running multiple projects all with different code changes and different release dates but approximately the same development start dates.
At present we are using VSS for code management, but are aware that it will probably cause some issues and will be migrating to TFS before new development starts.
What strategies should I be employing and what things should I be considering before setting a plan down?
Sorry if this is vague, feel free to ask questions and I will update with more information if required.
This is the single best source control pattern that I have come across. It emphasizes the importance of leaving the trunk free of any junk (no junk in the trunk). Development should be done in development branches, and regular merges (after the code has been tested) should be made back into the trunk (Pic 1), but the model also allows for source to be patched while still under development (Pic 2). I definitely recommend reading the post in its entirety, to completely understand.
Pic 1
Pic 2
Edit: The pictures are definitely confusing without words. I could explain, but I would basically be copying the original author. Having said that, I probably should have selected a better picture to describe the merge process, so hopefully this helps. I'd still recommend reading the post, however:
The simplest and most usual way I've seen branching work is off two premises. Trunk and Release. I think this is known as the "Unstable trunk, stable branch" philosophy.
Trunk is your main source. This contains the "latest and the greatest" code and is forward looking. It generally isn't always stable.
Release is a one-to-many association with trunk. There is one trunk but many releases that derive from the trunk. Releases generally start with a branch of the trunk once a particular functionality milestone has been hit so the "only" things left to go in for a particular deployment should just be bug fixes. You then branch the trunk, give it a label (e.g. 1.6 Release is our current latest Release), build and send the release to QA. We also push the version number (usually the minor number) of the trunk up at this point to ensure we don't have two releases with the same number.
Then you begin the testing cycle on your release branch. When sufficient testing has been perfomed you apply bug fixes to the release branch, merge these back to the trunk (to ensure bug fixes are carried forward!) and then re-release a build of the branch. This cycle with QA continues until you are both happy and the release is finally given to the customer(s). Any bug reports from the customer(s) that are accurate (i.e. they are a bug!) start another QA cycle with the branch in question.
As you create future releases it is a good idea to also try to move older customers onto newer branches to reduce the potential number of branches you might have to back-patch a bug fix into.
Using this technique you can deploy solutions using your technology to a variety of customers that require different levels of service (starting with least first), you can isolate your existing deployments from "dangerous" new code in the trunk and the worst merge scenario is one branch.
My first recommendation would be to read Eric Sink's Source Control HOWTO - specifically the branches and branch merge chapters.
We have 3 containers - DEV, MAIN, and RELEASE for our work. MAIN contains all our "ready-to-release" code and we tend to think of it as "basically stable." DEV/Iteration (or DEV/Feature, or DEV/RiskyFeatureThatMightBreakSomeoneElse) are branches from MAIN and are merged up when the Iteration/Feature is ready to promote up past the DEV environment. We also have TFS builds set up from the DEV/Iteration branch and the MAIN branch.
Our RELEASE container contains numbered releases (similar to the "tags" container used in many Subversion repositories). We simply take a branch from MAIN each time - I like to say we're "cutting" a RELEASE branch to signify this shouldn't have a lot of activity going on once the merge is finished.
As for VSS->TFS - Microsoft supports an upgrade path which should keep your version history, but if you don't need it the history, I would just get the latest version from VSS, check it into TFS and archive the VSS repository.
One final tip - get your team members familiar with source control. They must understand branching and merging or you will be stuck doing a lot of cleanup work :).
Good luck!
The subversion book describes some common branching patterns. Maybe you can also apply these to TFS.

Cross-Branch merging in TFS?

Is it possible to merge to a branch that is not a direct parent or child in TFS? I suspect that the answer is no as this is what I've experienced while using it. However, it seems that at certain times it would be really useful when there are different features being worked on that may have different approval cycles (ie. feature one might be approved before feature two). This becomes exceedingly difficult when we have production branches where we have to merge some feature into a previous branch so we can release before the next full version.
Our current branching strategy is to develop in the trunk (or mainline as we call it), and create a branch to stabilize and release to production. This branch can then be used to create hotfixes and other things while mainline can diverge for upcoming features.
What techniques can be used otherwise to mitigate a scenario such as the one(s) described above?
I agree with Harpreet that you may want to revisit how you you have setup you branching structure. However you if you really want to perform this type of merge you can through something called a baseless merge. It runs from the tfs command prompt,
Tf merge /baseless <<source path>> <<target path>> /recursive
Additional info about baseless merges can be found here
Also I found this document to be invaluable when constructing our tfs branching structure
Microsoft Team Foundation Server Branching Guidance
tf.exe merge /recursive /baseless $/TeamProject/SourceBranch $/TeamProject/TargetBranch
MSDN: How To: Perform a Baseless Merge in Visual Studio Team Foundation Server
You may want to revisit your branching strategy. How do you get production branches? Are you merging all code from development branches, regression testing and then creating a production branch for fixes? Or are you developing on the trunk and then creating production branches to stabilize and release from? The second way creates problems of the type you're describing. If you are using the first approach -- the trunk is supposed to be only for things that have been built on branches tested and then merged you will run into this much less often. Under that approach if you're still having this problem it may be because your development effort is very large and you may need a relatively complex branching strategy with layers of branching and promotion.
AFAIK you can do this as long as the branches were created off of the same original folder.
trunk/
branches/
-/feature1 (branched from trunk)
-/feature2 (branched from trunk)
If you do this then you should be able to merge between feature1 and feature2 as well.
Though my branching/merging experience with TFS leaves me wanting more. I wish we just had SVN.
Yes, you can do a baseless merge, but only from the command line (tf.exe).
TFS will allow you to merge with a branch that is not a parent/child - these are called baseless merges. See these links:
From MSDN
From the TFS Team via CodePlex
We typically do major or destabilizing changes on a development branch. If close to a major release of one of our products nearly all changes will be done on a branch.
I am far from a TFS expert, but I think you can merge siblings, and I think it is not a baseless merge.
We branched off our main branch (branch name "main") for a feature (branch name "feature"), then I needed some of the work in a branch that was also branched off the main branch (branch name "dev"). I would consider feature and dev branches to be siblings as they both came from the same parent. I merged feature to dev and all files (14000) were marked as merge, some were marked as merge,edit. I could not cancel (visual studio would just hang), so I accepted the merge. Then I merged dev to main, then I pulled main to feature, and again 14000 files were marked for merge. I was really upset, and afraid this would continue.
At this point we did a test project. We set up main, then branched dev and feature from main. We repeated the above steps with the same results. Once we completed the merge from main to feature, all future merges only showed the edited files.
After our little test I completed the merge from main to feature. And just like the test our merges now only show the edited files. We can go dev to feature, feature to main, main to dev, etc.
I did notice when branching all file dates were modified. Maybe this is an issue?