Is it correct to do a merge of named branch with the default Mercurial branch? - mercurial

I have hit following issue regarding Mercurial usage. I have two branches: default branch and let's say A branch. After establishing the A branch (point 1 in my diagram below) there were done some modifications on the default branch (point 2 in my diagram below) so the situation is following
1 2
----default-----o-------------o
\
\
-----A------
My goal is to have the changes from the default branch (from point 2) on the A branch. My idea was to use the hg merge default command for this. I have searched this forum and I have found similar question. Based on that it seems to me that my intention is at least doable but I am not sure whether it is correct approach because I have thought that the merges including the default branch should be done only in direction: named branch->default branch. My question is whether the approach I have suggested above i.e. do a merge with default branch is correct?

This isn't really a matter of "right or wrong". Technically Mercurial supports what you propose. You can merge from any branch into any other branch.
The question is what is the best thing for your workflow. If the problem is that changes were made on default that should have been made on A, then a merge from default to A seems appropriate. But there also could be alternative ways of making such a correction (if indeed that is what is required). The question doesn't have enough information to really elaborate on this, however.
If the intention is to do new feature development on branches, and then only merge the completed results of that work onto default, that seems reasonable, and I think is a common approach.
Regardless, if you haven't already you should carefully define what work is expected to be done on what branch, just to avoid confusion & mistakes.

Related

Mercurial: Pulling in others merges + branching

I'm still very new to Mercurial so please let me know what I'm doing wrong.
We have an hg repo for each of our developers. I'm working on a new feature in branch x. Since then, others have made critical changes to the project, which I have pulled into my repo. However, when I'm working on branch x my working copy still has the old stuff, which causes it to not play well w/ our shared MySQL database.
Q: How do I update my branch to have the other developers new stuff while keeping my own code in the x branch; I'm not ready for them to have it yet and I definitely don't want to merge x into default... I'm not sure what to do here...
Or am I going about this the entirely wrong way? If so, what should I be doing instead?
[edit]
Also, I'm using TortoiseHG, so if you have any instructions specific for that it would be appreciated.
[/edit]
You are doing everything right. In order to "keep up" with the work of the other developers, you have to merge the default branch into your x branch. Not the other way around.
When you are in your x branch, it is as easy as doing hg merge default.
Edit : I deleted my statement about hg merge being equivalent to hg merge default, which is false. I misread the documentation.

Get a bugfix from default to a feature branch in Mercurial

How do I get a bugfix I made on the default branch into a named branch in mercurial?
I recently started work on a new feature so thought I'd do this work in a branch (which I've not really done before) so I could keep the changes out of the main default branch until I've finished working on them and the feature is ready to deploy. The idea being that I could update to the default branch and apply any bugfixes as needed.
Now I want to get the bugfix into my named branch. The tip (rev 739) has the change I want to incorporate into the BoardSummary branch. I know I could merge but I don't want to bring my BoardSummary changes into the default branch.
I looked at the mercurial: apply a bugfix change from stable named branch to dev branch answer but it didn't make sense to me.
Edit: I'm with it up to "Then you discover that changeset 2 introduced a bug", in my case I went back to 732 fixed the bug and committed (onto the default). The idea being that the fix is in place before I branched. But now how do I get that fix into 738 without merging the 2 branches together? It looks like the bug is actually fixed in 739 - so isn't in the BoardSummary branch yet. This seems to be what the 2nd tree shows in the answer but the 3rd diagram is explained with "you would instead do this" - I don't understand that bit
Evidently, your default branch contains only one changeset not present in the BoardSummary branch. You should merge default into BoardSummary, and not the other way round. This way, BoardSummary will have the fix, and none of the BoardSummary will be in default.
To summarize:
$ hg up BoardSummary
$ hg merge default
$ hg commit -m "Merge the fix for #247"
An explanation
There are a number of kinds of branches which can be employed. The most common are:
stable (production) branches for maintaining the released versions,
default (master, trunk) branch, which contains more or less stable development activity,
feature branches, which are not mature enough to be merged into trunk.
The main idea here is that it is always safe to merge from stable to default, and from default to feature. This means that in terms of changesets, any stable branch is a subset of default, and default is a subset of feature branches.
For instance, you're reworking your data access level in a feature branch new-dal (major feature). At the same time, you've added a couple of new reports in default (minor features), and found and fixed a bug in a 1.0-stable. Well, just merge the branches going from the oldest to the newest (1.0-stable -> default -> new-dal), and that's all.
This is explained very well on the Mercurial wiki: Standard Branching: Release branches.
Your case
In your case, BoardSummary is clearly a feature branch, so you can merge default into it without any hesitation. The opposite should only be done if you're ready to integrate the new feature into default.
At first you should rollback/remove the commit 739 (which is your fix) from the history. Then you commit the fix on r732. This will create a new head and should be the new r739. Your history should look like this:
r329
|
--r232-----default branch
\
\
feature branch
Now you merge your new head (r329) into the default and the feature branch. Now the history should look like the last tree in the linked answer.

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

A mercurial merge chose the wrong changes, what is the correct way to fix this?

Changes were made to our .vcproj to fix an issue on the build machine (changeset 1700). Later, a developer merged his changes (changes 1710 through 1715) into the trunk, but the mercurial auto-merge overwrote the changes from 1700. I assume this happened because he chose the wrong branch as the "parent" of the merge (see part 2 of the question).
1) What is the "correct" mercurial way to fix this issue, considering out of all the merged files, only one file was merged incorrectly, and
2) what should the developer have done differently in order to make sure this didn't occur? Are there ways we can enforce the "correct" way?
Edit: I probably wasn't clear enough on what happened. Developer A modified a line in our .vcproj file that removed an option for the compiler. His check-in became changeset 1700. Developer B, working from a previous parent (let's say changeset 1690), made some changes to completely different parts of the project, but he did touch the .vcproj file (just not anywhere near the changes made by Developer A). When Developer B merged his changes (becoming changes 1710 through 1715), the merge process overwrote the changes from 1700.
To fix this, I just re-modified the .vcproj file to include the change again, and checked it in. I just wanted to know why Mercurial thought that it shouldn't keep the changes in 1700, and whether or not there was an "official" way to fix this.
Edit the second: Developer B swears up and down that Mercurial merged the .vcproj file without prompting him for conflict resolution, but it is of course possible that he's just misremembering, in which case this whole exercise is academic.
I will address the 2nd part of you question first...
If there is a conflict, the automated merge tools should force the programmer to decide how the merge happens. But the general assumption is that a conflict will involve two edits to the same set of lines. If somehow a conflict arises because of edits to lines that are not close to each other the automated merge will blithely choose both of the edits and a bug will appear.
The general case of a merge tool always merging properly is very hard to solve, and really can't be with current technology. Here is an example of what I mean from C:
int i; // Someone replaces this with 'short i' in one changeset stating
// that a short is more efficient.
// ... lots of code;
// Someone else replaces all the 65000s with 100000s in another changeset,
// saying that more precision is needed.
for (i = 0; i < 65000; ++i) {
integral_approximation_piece(start + i/65000.0, end + (i + 1) / 65000.0);
}
No merge tool is going to catch this kind of conflict. The tool would have to actually compile the code to see that those two parts of the code have anything to do with eachother, and while that would likely be enough in this case, I can construct an example that would require the code to be run and the results examined to catch the conflict.
This means that what you really ought to do is rigorously test your code after a merge, just like you should after any other change. The vast majority of merges will result in obvious conflicts that a developer will have to resolve (even though that resolution is often fairly obvious), or will merge cleanly. But the very few merges that don't fit either category can't easily be handled in an automated fashion.
This can also be fixed by development practices that encourage locality. For example a coding standard that states "Variables should be declared near where they're used.".
I'm guessing that .vcproj files are particularly prone to this problem since they are not well understood by developers and so if conflicts do appear they will not be sure what to do with them. My guess is that this happened and your developer simply did a revert back to the revision (s)he checked in.
As for part 1...
What to do in this case depends a lot on your development process. You can either strip the merge changeset out and redo it, though that won't work very well if lots of people have already pulled it, and it will work especially poorly if there are lots of changesets that have already been checked in that are based on the merge changeset.
You can also check in a new change that fixes the problem with the merge.
Those are basically your two options.
The tone of your post seems to me to indicate that you may have some politics surrounding this issue in your organization, and people are blaming this error on the frequent merges of Mercurial. So I will point out that any change control system can have this problem. In the case of Subversion, for example, every time a developer does an update while they have outstanding changes in their working directory, they are doing a merge, and this kind of problem can arise with any merge.
In mercurial a merge doesn't have a single parent, it by definition has two and only two parents. When someone is merging they're making two choices:
What two changesets will constitute the two changes
Which of those changesets will be the left-parent and which will be the right-parent
Of those two questions the first is very important, and the second barely matters at all, though it took me a while to come to understand that.
You select the left-parent by using hg update X. That changes the output of hg parents (or in newer versions hg summary) and essentially determines what's in your working directory before the merge.
You select the right-parent by using hg merge Y. That says merge X (the working directory's parent) with changeset Y. As a special case, if there are only two heads in your repository and your parent is already one of them then Y will default to the the other.
I'd have to see your resulting graph to know just what the developer did, but it's possible he didn't update to one head or another before invoking merge, which would have him merging one head with some point back in history.
If your developer picked the right parents for the merge then the left vs. right doesn't much matter -- the only real difference is that when one uses hg diff or hg log -p or some other command that shows the patch for a merge changeset, it's displayed relative to the left-parent. That's, however, mostly a factor in display only. Functionally they're pretty much identical.
Assuming your developer picked the right changesets then what he should have done was test the result of the merge before committing it. Merging is software development, not an annoying VCS side effect, and not testing before committing is the error.
Fixing
To fix this, just re-do the merge correctly. Use hg update to set one parent, use hg merge to pick the other. Make sure your current working directory is correct and then commit. You can get rid of his bad merge using something like hg strip or better, just close down his branch with hg commit --close-branch after updating to it.
Avoiding
You say "mercurial auto-merge", but mercurial doesn't really auto-merge. It does a premerge which is an extremely cautious combination of obvious changes, but it's so careful it won't even merge for you if each merge parent adds code in the same region because it can't know which block of code you'd rather have first.
You can disable this premerge entirely or on a file-by-file basis using the merge tool configuration options:
https://www.mercurial-scm.org/wiki/MergeToolConfiguration?highlight=premerge

best practices in mercurial: branch vs. clone, and partial merges?

...so I've gotten used to the simple stuff with Mercurial (add, commit, diff) and found out about the .hgignore file (yay!) and have gotten the hang of creating and switching between branches (branch, update -C).
I have two major questions though:
If I'm in branch "Branch1" and I want to pull in some but not all of the changes from branch "Branch2", how would I do that? Particularly if all the changes are in one subdirectory. (I guess I could just clone the whole repository, then use a directory-merge tool like Beyond Compare to pick&choose my edits. Seems like there ought to be a way to just isolate the changes in one file or one directory, though.)
Switching between branches with update -C seems so easy, I'm wondering why I would bother using clone. I can only think of a few reasons (see below) -- are there some other reasons I'm missing?
a. if I need to act on two versions/branches at once (e.g. do a performance-metric diff)
b. for a backup (clone the repository to a network drive in a physically different location)
c. to do the pick&choose merge like I've mentioned above.
I use clone for:
Short-lived local branches
Cloning to different development machines and servers
The former use is pretty rare for me - mainly when I'm trying an idea I might want to totally abandon. If I want to merge, I'll want to merge ALL the changes. This sort of branching is mainly for tracking different developers' branches so they don't disturb each other. Just to clarify this last point:
I keep working on my changes and pull my fellow devs changes and they pull mine.
When it's convenient for me I'll merge ALL of the changes from one (or all) of these branches into mine.
For feature branches, or longer lived branches, I use named branches which are more comfortably shared between repositories without merging. It also "feels" better when you want to selectively merge.
Basically I look at it this way:
Named branches are for developing different branches or versions of the app
Clones are for managing different contributions to the same version of the app.
That's my take, though really it's a matter of policy.
For question 1, you need to be a little clearer about what you mean by "changes". Which of these do you mean:
"I want to pull some, but not all, of the changesets in a different branch into this one."
"I want to pull the latest version of some, but not all, of the files in a different branch into this one."
If you mean item 1, you should look into the Transplant extension, specifically the idea of cherrypicking a couple of changesets.
If you mean item 2, you would do the following:
Update to the branch you want to pull the changes into.
Use hg revert -r <branch you want to merge> --include <files to update> to change the contents of those files to the way they are on the other branch.
Use hg commit to commit those changes to the branch as a new changeset.
As for question 2, I never use repository clones for branching myself, so I don't know. I use named branches or anonymous branches (sometimes with bookmarks).
I have another option for you to look into: mercurial queues.
The idea is, to have a stack of patches (no commits, "real" patches) ontop of your current working directory. Then, you can add or remove the applied patches, add one, remove it, add another other one, etc. One single patch or a subset of them ends up to be a new "feature" as you probably want to do with branches. After that, you can apply the patch as usual (since it is a change). Branches are probably more useful if you work with somebody else... ?