Mercurial - merging same changeset to a repository twice? - mercurial

We have these Mercurial repositories:
Trunk
|
|
|---------myapp_1_0_23 (created off release 1.0.23)
|
|---------myapp-newstuff (created off rel 2.0.4)
Release schedule (nothing yet released):
v1.0 from myapp_1.0.23, any add'l changes in this repo will get merged to the trunk
v2.0 from the trunk
v3.0 or v4.0 released based on a merge of myapp-newstuff and the trunk. At the time of the merge the trunk may have v2.0 code or some new features that we'll release from the trunk as v3.0
After making changes in myapp_1.0.23, we merge them to the trunk, but let's say we also need them in myapp-newstuff so we also merge them there. What then happens when we eventually merge myapp-newstuff code to the trunk?
The trunk already has changes made in myapp_1.0.23 so what happens when we merge those same changesets from myapp-newstuff back to the trunk? Will Mercurial be smart enough to know those changesets are already in the trunk?

Mercurial will handle this situation just great -- because you're using 'merge'. When you're using export/import (or transplant), cherry picking as it's called, and you have the same changesets in there multiple times with different node ids (due to different parents) then Mercurial can't know "Oh, this one's already here". However, so long as you're merging Mercurial will do a great job of saying "oh, this repo already has that changeset so I don't need to re-apply it".
The general rule of thumb is: "Make every change with as early a parent as you can and then merge down". If I have a bug that's in version one, two, and three, I fix it in one and then merge into two and then merge into three. If instead you fix it first in three, then you have to try to get it into two without bringing all the other changes in version three with it -- which is hard and often requires the very cherry picking we're trying to avoid.

Related

Is this a proper Mercurial merge?

2 main branches:
stable - used for release and for hotfixes.
default - used for all other development and all features
Please see revisions 8 and 9 specifically. I added a 2 separate features in revisions 3 and 4, worked on them separately, merged them into default in revisions 7 and 8. They are not complete at this time.
My question is, did I do this correctly considering that I am not done with the features and did not close the feature branches? The connected blue and pink lines at revision 8, along with the blue extension at revision 9 are confusing me.
I'm pretty new to source control, so any explanations are appreciated.
You just have two heads on your tree, which are at revisions 8 and 9 specifically now. You could run "hg heads" on the command line in that directory to see some textual information about them both. At this point, you could update to either head, make changes and commit, then update to the other head, make changes and commit, etc. Also, you could merge your feature branch into the default and then just have one head. It depends on how long you want to keep your feature branch separate.
More interestingly, are you planning to keep using the "stable" branch? If so, I guess that you could "hg update" to r1, and then merge things from your other branches to there.
Side note: You may be interested in reading about "hg flow", and its branching model. See for example:
https://andy.mehalick.com/2011/12/24/an-introduction-to-hgflow
http://www.carl-berg.se/post/hgflow-git-flow-for-hg

Mercurial: devs work on separate folders, why do they have to merge all the time

I have four devs working in four separate source folders in a mercurial repo. Why do they have to merge all the time and pollute the repo with merge changesets? It annoys them and it annoys me.
Is there a better way to do this?
Assuming the changes really don't conflict, you can use the rebase extension in lieu of merging.
First, put this in your .hgrc file:
[extensions]
rebase =
Now, instead of merging, just do hg rebase. It will "detach" your local changesets and move them to be descendants of the public tip. You can also pass various arguments to modify what gets rebased.
Again, this is not a good idea if your developers are going to encounter physical merge conflicts, or logical conflicts (e.g. Alice changed a feature in file A at the same time as Bob altered related functionality in file B). In those cases, you should probably use a real merge in order to properly represent the relevant history. hg rebase can be easily aborted if physical conflicts are encountered, but it's a good idea to check for logical conflicts by hand, since the extension cannot detect those automatically.
Your development team are committing little and often; this is just what you want so you don't want to change that habit for the sake of a clean line of commits.
#Kevin has described using the rebase extension and I agree that can work fine. However, you'll also see all the work sequence of each developer squished together in a single line of commits. If you're working on a stable code base and just submitting quick single-commit fixes then that may be fine - if you have ongoing lines of development then you might not won't want to lose the continuity of a developer's commits.
Another option is to split your repository into smaller self-contained repositories.
If your developers are always working in 4 separate folders, perhaps the contents of these folders can be modularised and stored as separate Mercurial repositories. You could then have a separate master repository that brought all these smaller repositories together within the sub-repository framework.
Mercurial is distributed, it means that if you have a central repository, every developer also has a private repository on his/her workstation, and also a working copy of course.
So now let's suppose that they make a change and commit it, i.e., to their private repository. When they want to hg push two things can happen:
either they are the first one to push a new changeset on the central server, then no merge will be required, or
either somebody else, starting from the same version, has committed and pushed before them. We can see that there is a fork here: from the same starting point Mercurial has two different directions, thus a merge is required, even if there is no conflict, because we do not want four different divergent contexts on the central server (which by the way is possible with Mercurial, they are called heads and you can force the push without merge, but you still have the divergence, no magic, and this is probably not what you want because you want to be able to checkout the sum of all the contributions..).
Now how to avoid performing merges is quite simple: you need to tell your developers to integrate others changes before committing their own changes:
$ hg pull
$ hg update
$ hg commit -m"..."
$ hg push
When the commit is made against the latest central version, no merge should be required.
If they where working on the same code, after pull and update some running of tests would be required as well to ensure that what was working in isolation still works when other developers work have been integrated. Taking others contributions frequently and pushing our own changes also frequently is called continuous integration and ensures that integration issues are discovered quickly.
Hope it'll help.

How to commit only certain revisions to a cloned repository

We have recently moved from Perforce to Mercurial, and we are struggeling a bit to find out how to merge only certain changes to our stable releases.
We have a central repository that all developers clone from.
In Perforce, we have been using branches to maintain releases, and then merging only bug fixes per change lists from branches into trunk, or the other way around into branches that needed that fix.
In Mercurial, we have implemented this by cloning, where each stable release is a cloned repository of trunk.
Our structure looks a bit like this:
Trunk
|- Release 1
|- Release 2
|- Release 3
My question is, how can we merge only specific change sets from trunk into a branch? I hope there is an easy way to do it, preferably using TortoiseHg, since we have a lot of developers with different experience level that will be doing this.
I might not understand fully what you want to do.. but yes you can take changes from one branch into another branch (e.g., from the trunk, called default in Mercurial, to a release branch). In modern Mercurials, this can be done using the graft command (or before the transplant extension). To use it on a branch type: hg graft REVISION (see hg help graft for more details).
Now what I don't understand is that it seems that you do not have several branches but only one (default) and several clones (?), in which case everything becomes a bit more complicated.. You could pull only one changeset but then you need to pull also its ancestors and it is difficult to know what you actually get into your clones working directories! So I would really advice to create the release branches!
Hope it'll help.

In Mercurial, can I merge just some files between two branches? [duplicate]

This question already has answers here:
Mercurial: Merging one file between branches in one repo
(5 answers)
Closed 2 years ago.
Reading up on Mercurial, it seems to always branch and merge the complete repositories.
Is it possible to just merge some files from one branch to another? (For example I may only wish to merge in the files that fix a given bug.)
Likewise can I cherry pick some change sets, but still have a correct merge record, so if a complete merge is done later it is correct?
I am coming from a perforce “mindset” so may be thinking about this the wrong way.
Yes, Mercurial always branches and merges the whole tree. You don't have the "flexibility" that something like perforce gives you to select individual files for a merge. This is a good thing (trust me). Changesets are atomic (you can't split them) and immutable (you can't change them). Hence this needs a little bit of a mindset change.
Changesets should be targetted at one task, and one task only. If you're fixing a bug, nothing else goes in the changeset apart from the bug fix. You've then got a changeset which documents that bug fix, and you haven't got the problem of wanting to split it. It wouldn't make sense to want to. Half a bug fix is often worse than no bug fix.
When it comes to merging that there's a couple of options:
One school of thought says you should go back to where the bug was introduced. Fix it. Commit (making a small anonymous branch), and merge that forward onto whatever head you want it on (dev, stable, release, whatever). This isn't always practical though.
Another method is fixing the bug in the release branch, and then merging to the development branch. This normally works well.
Alternatively you could fix it at the head of your development branch, but then if you merge it onto your release branch you'll bring over all your development changes. This is where graft (new in 2.0) and the older transplant extension come into play. They allow you to "cherry-pick" a single or range of changesets from another branch and place them on another branch.
Reading up on Mercurial, it seems to always branch and merge the
complete repositories.
Yes
Is it possible to just merge some files from one branch to another? (For example I may only wish to merge in the files that fix a given bug.)
Just touch only "some files" in needed changeset and merge branch with this changeset in head with another branch or transplant in any time
Likewise can I cherry pick some change sets, but still have a correct merge record, so if I complete merge is done later it is correct?
Yes, you can transplant| any changesets to another branch, applied state will be remembered and changes will not be duplicated on final merge

mercurial team repository / picking and choosing

I have a small team and I would like to do the following:
I have my trunk, I'll just call it TRUNK
Now, TRUNK is a project that's already in production and running. Now, the inevitable defects come in, but into bugzilla and are assigned to users.
Each user clones TRUNK to their local repositories and makes changes and pushes them to a directory TRUNK/projects (projects is not a clone of TRUNK, just a regular directory)
Now, the day comes where I want to create a new build called RELEASE and I want to merge some of the bug fixes (not all, just some) into RELEASE.
Notice, I am not committed to the idea of having TRUNK/projects/[bugfixes list], but that's what I currently have now and am more than open to any / all suggestions.
What are some ideas? Is there something I can do / should do differently? Again, I am open to any / all suggestions, including completely changing the above procedure (except for using Mercurial as that's what the company makes us use)
There are two ways to do this and they diverge not at release time, but when you do the bug fixes depending on what parent you give the bugfix changesets. The "good" way uses only push, pull, and merge. The less good way (it's not entirely bad, but it's certainly sub-optimal) is called cherry picking and it has drawbacks. The tricky part is that whether or not you're going to be able to move bugfixes into RELEASE via merge without moving everything from TRUNK into RELEASE is something you have to decide before you make that change.
Here's a really complete answer for a similar question that explains what's going on: Some help with merging legacy branch in Mercurial
The key concept though, is that you can merge a changeset into any branch you want but it brings with it all of its ancestor changesets. So you want your bug fixed to have minimal ancestry. That means fixing a bug not in a new changeset in TRUNK that happens to be the latest feature you added, but instead, first, hg updateing to a changeset that already exists in both your TRUNK and your RELEASE, and there are two great candidates for that. Either:
the changeset where RELEASE and TRUNK diverged
or
the changeset where the bug was introduced
My preference is for the later. If a bug was introduced in changeset 666 then every clone, branch, and build that has changeset 666 will want your fix. So when fixing it just do:
hg update 666
.. fix the bug ..
hg commit -m "fixed bug 55" # creats changeset 999 which a new head
Then you can do this:
hg update TRUNK
hg merge 999
and you'll know you're only pulling in a single changeset. Later when you're ready to release you can do:
hg update RELEASE
hg merge 999
and you're again only getting the single changeset you want.
The advantage of this mode of working over cherrypicking (using export/import or transplant) is that your fix exists only once in your repo. If you have 99 different vendor branches for various finicky customers and you want to see if they have the fix for bug 55 you can just do:
hg log -r 'descendants(999) and heads(FUSSYCUSTOMERBRANCHNAME)'
and if there are no results then that customer doesn't have 999 and thus doesn't have the fix for bug 55 in changeset 666. When you re-do the same work with multiple changesets (which is the result of export/import and transplant) that's harder to verify.
Common practice is to create topic branches.
Each new issue/ticket/enhancement is commited into separate branch.
Anytime maintainer wants to make new release he can merge all (or only some) that branches into "default" or even new branch called e.g. "release_1_x".
To be more precise. Developer working on code can still clone repository, then create local branch and finally, after one or more commits to that branch, pushes local changes to one centralized clone (from which every other developer in team can pull/clone again).