Mercurial merge changeset between branches brings all ancestors with it - merge

I have a problem with merging changes between branches.
I have default branch default.
When I'm starting working under new issue I make new branch like #565 from default and working with it. After working I'm merging code changes from #565 into default - it work great.
Also I have branch anotherbranch - this is like production branch, we can merge something there if it was tested on default.
Sometime I need to merge code changes from #565 into anotherbranch. When I trying to do this, Mercurial offer me to merge ALL code changes between #565 AND anotherbranch (because #565 is child of default).
How I can merge ONLY code changes of #565?

Someone suggested the graft command, and that's probably what you'll end up using, but let me take a step back and suggest that this problem will go away if you improve your process a bit.
In general if you fix bugs in new branches branched from anotherbranch and add new features in branches from default you'll have the best of both worlds. Fix bugs off of your "production" branch and then merge that production branch, called anotherbranch, back into default immediately.
That's the usual process and that makes sure that the bug fixes are everywhere but that new features don't hit production until they've gotten good testing.

I think what you need is the graft command ("copy changes from other branches onto the current branch").

The best way to fix this is, as Ry4an suggests, to modify your workflow. You may also want to consider using the mq extension to create patches. Patches are a great way to apply only certain changes to a repository, particularly if you're not ready for a full-on merge.

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}

Gerrit: working with multiple branches & propagating changes

I'm trying to identify the proper way of working with multiple branches on Gerrit that would match our workflow.
The way we work with branches right now is: we have master & feature branch. Master is the branch we want to polish and make it ready for release, while feature is obviously a field of intensive work. Now, in our particular case whenever somebody works on a bug fix, they:
create a change targeted for master branch
cherry pick it to the feature branch targeted change
once gerrit code review completes, submit both changes.
now the way i understand cherry-pick, it selects individual commit and merges it to the current change. if that is the case, i would expect to have no merge conflicts in the end, and indeed this workflow works perfectly with just GIT. Gerrit, however, most likely due to its nature (branches are not merged remotely the way these are locally and get a different sha tag) lists a tremendous number of conflicting files in the end.
Now, I resolved all these issues by applying merge strategy (ours on feature, theirs on master), but it does not feel right: if anything was not propagated, it just got discarded.
My question is: is there a safe workflow, similar to the above one, that would in the end produce a clean merge with gerrit?
I would say that it's better, in this case, to merge than to cherry pick.
A cherry pick adds the same changes but not the same commit. So while the source is the same on a cherry pick and merge the git tree is different. When the tree is different and you later do a merge git will think that the commit you previously cherry picked is missing and try to merge that change as well, even if the actual code is already there. That's probably why you get a lot of conflicts.
I would propose another way of working.
When you do normal work you develop on feature and push to Gerrit as normal.
When you do a patch (ie bug fix) on the stable production environment you do that directly on master (or local branches if you like but not on feature)
When the patch as been approved in Gerrit it get's merged into the real master and you can make a pull request to get that change to your local copy. Your version of master is now the same as Gerrits master
Now you would merge all new changes on master into feature. Make sure you do a rebase so that the patch ends up before anything you've already done on feature
Once it's time to deploy all new features you can merge feature into master, push to Gerrit (if you have permissions you can by pass gerrit by pushing directly to master instead of refs/for/master as these changes are already reviewed)
Once all changes are on Gerrits master you do a pull on your master and a merge into feature with rebase making feature a clean branch to work on. It's of course totally valid to have a new feature each release. Both work fine.
I'm a little confused, as this flow should work just fine. If other users submit changes before your bug fix is reviewed/verified/submitted, that could result in merge conflicts, but that should be rare.
If you:
Fix a bug on master
Push to review (creating change A in gerrit)
cherry-pick change A on top of the feature branch (resolving any conflicts from master to feature)
Push the cherry-picked change to review (creating change B)
Review/verify/submit changes A & B
Everything will work fine. The only way for merge conflicts to occur is if other users upload and submit changes between steps 1 and 5. Are you seeing different behavior? Can you provide more details?

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.

Branch-per-feature workflow using Mercurial

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.

How does merging a branch actually work (under the hood)?

this may be a naive question, but, as asked in the object, what is the actual way used by versioning softwares to merge a branch back into the main trunk without generating broken code?
Here's a quick example: I make a branch out of the main trunk for the program "Hello World Power edition". I add support for Klingon. This is a radical change that changes the way the function printHelloWorld() works.
Meanwhile, because of bug #749 that cause "Hello World" to be written "Helo World", the function printHelloWorld() in the main trunk has been changed.
Now, the problem that I see here is: when i merge by branch back to the main trunk i experiment a clash in the function printHelloWorld() within the file sayHello.py
How does a VCS program know how to add the Klingon support from my branch and keep the bug fix in the main trunk? What are the human-driven or software-driven strategies to avoid this?
Thanks in advance.
How does a VCS program know how to add
the Klingon support from my branch and
keep the bug fix in the main trunk?
VCS knows nothing about semantic of your source code it sees it as a bunch of text/binary files. VCS system uses diff / merge algorithms to detect conflicts between yours and current file version. It is your responsibility to resolve such conflicts because only you know semantic of these changes. Some VCSs like SVN would require you to update your working copy with latest changes from trunk before allowing you to commit changes to make sure that nothing is lost.
To make sure that you didn't break anything and all previous bug fixes were not broken you should use code reviews, unit tests and other practices. Continuous integration is a good way to keep software healthy.
In such a case the version control system can't merge automatically, you have to do the merge by hand. Good unit tests will help you to ensure that no functionality is lost.
Before you can merge your branch back to trunk, the version control system will update your working copy with the changes in trunk since you branched out. It will just not allow you to merge without this update. This ensures you get all the bug fixes in the trunk in your next commit.
A good strategy for working on a branch is to port changes in trunk into you branch on very regular basis. This ensures that you don't drift too apart from trunk, leading you to have problems when you eventually merge back into trunk.