Ignore one parent when pulling a merge commit - version-control

I want to pull a set of changesets from a certain branch in a remote repository. One of the changesets is a merge from another branch, which I don't want to pull. However, it will be pulled even if I specify the branch name:
hg pull -r REV -b mybranch REMOTE_REPO
Is there a way to pull this commit as a regular changeset, ignoring its other ancestors?

No, this is impossible. All changesets (whether they are regular or merge changesets) depend on their ancestors and cannot be pulled in isolation. This is a fundamental design decision in Mercurial.
Merging prematurely results in the annoying situation you describe — each branch is no longer clean and cannot be pulled without also pulling in other stuff. The best way to avoid this is to use rebase (if the development is local-only and thus elegible for rebasing) or to simply ask people to stop mixing unrelated things together until you can make a firm decision about what needs to be merged.

Related

How to do a difficult rebase in O(n) rather than O(n^2)?

There's this difficult rebase that keeps stumbling on conflicts every other commit. In order to be able to resolve some confusing conflicts, I must sometimes --abort and check out the master branch to see what exactly is there (unconfounded by conflict markup, stuff rebased so far, or git's "ours" vs. "theirs" hell). Whenever I do this, I must subsequently re-resolve all conflicts up to that point. This makes the rebase effectively O(n^2).
Is there a better way?
(Note: it absolutely must be a rebase, this requirement is a given. Merging is out of the question).
First, the new (Git 2.30) new merge strategy: ORT ("Ostensibly Recursive's Twin") will be slightly faster.
But the all process would still be not O(n).
Second, do use the git worktree command in order to checkout master in a separate folder (without making a separate clone).
That way, you don't have to abort the merge in progress, and can compare with a copy of your working tree, on master branch.

Using mercurial why would I ever want to merge without committing?

Perhaps I'm biased from years of svn but why would I ever want to merge with a different branch then make some changes before committing. The hg output itself suggests otherwise:
(branch merge, don't forget to commit)
Dear hg, then why didn't you just do it for me?
Because a merge operation is not guaranteed to produce correct output (automatic merges can use bad heuristics for how to deal with conflicts, manual merges can suffer from human error). Usually, what you will do is the following:
Merge.
Build.
Test.
If the test failed, fix the issue, go back to 2.
Commit.
Mercurial does not suggests otherwise, it 's just reminder: "All merge-related changes stored only on Working Dir, commit results into repository for permanent storing" and doesn't prohibit you to make some additional changes in code before commit.
But separation of tasks (merge and not-related to merge changes - i.e changes not initiated by merge-conflicts) into separate changesets is good idea anyway

Less frequent/verbose notifications for hg push

My project uses hgext.notify. Currently incoming.notify = separate messages on every changeset. Considering changegroup notify, but even that contains info about every changeset, just all in one big email.
Here's the problem:
My work style is "check in early and often". I make many small checkins, usually on branches. Task branches. Eventually integrated.
My teammates do not like seeing messages for all of my checkins on my task branches.
We are considering using a history editing extension like collapse or histedit to reduce the verbosity - but I dislike losing history. I just want not to bother them with every individual changeset.
Q: is there a way, some configuration for an existing hook, or some alternate hg extension, that can be set up to do notifies as folllws;
a single message per changegroup (that's okay)
a single user provided message per changegroup - not just concatenation of all the branch changeset messages
filter out only the changest messages for, say, the trunk (the default branch in hg parlance). I.e. leave the branch changeset messages in, but don't send email.
(Note: my pushes typically involve several changesets on a branch, and then a merge onto default. So it is not enough to just filter the entire changegroup in or out according to what branches are affected.)
diffstats not between the tip and every changest on the branch, but just between "important" changesets on the trunk (default branch) - which may be evety changest on the trunk.
I'm afraid no such extension exists. The notify extension is just a basic way to send off emails with a little room for customization.
It sounds like you have a particular idea about what you want. I suggest you see if you can formulate it as a revision set and then simply use hg log in a changegroup hook. Pipe the output to mail and you've got yourself a very simple notify extension that you can customize to your hearts content!
What I'm saying is that the notify extension is not that complex and in many cases it can be replaced by a suitable invocation of hg log. You can even use a custom template for hg log if you want to change the output more than what hg log -v or hg log --patch does.
The tricky part (and the part that's not entirely clear from your question) is to filter out exactly the right changesets. You mention "important" changesets in point 4 above, but I'm not entirely sure what makes a changeset "important". If it is important when it's a merge from a feature branch into default, then something like this might be a start:
hg log -r "$HG_NODE:tip and children(not branch(default)) and branch(default)"
By taking the child changesets of the non-default changesets and intersecting with changesets on the default, we get exactly the merge points where feature branches were integrated.
I'm sorry the answer is so generic, but I think you're best off with writing a small custom shell script for what you want.

Easiest way to perform incremental merge in mercurial

I have a project, that have branched sometime. Both branches have had a lot of commits since the split, and I want to merge them into one. Simply merging the two heads is not enough because it has too many conflicts, and the merged branch is also unstable, and non-functional.
Therefore I want to incrementally merge the two branches. By incremental I mean I take the tip of one of the branches and apply the changes from the other one one at a time. Testing each merge, and continuing if everything goes well.
What is the easiest way to do this using mercurial?
You've pretty much outlined a strategy yourself. Assume you have two heads, named headA and headB. hg up -r headB to one of the two heads, then use hg merge -r X repeatedly, where X is a revision along the other line of development.
You can use hg log -r 'ancestor(headA,headB)::headA' to get a list of good candidates for these merges (depending on overall topology).
You can use hg transplant to pull specific changesets into a branch.

What am I doing wrong with SVN merging?

When SVN with merge tracking works, it's really nice, I love it. But it keeps getting twisted up. We are using TortoiseSVN. We continuously get the following message:
Error: Reintegrate can only be used if revisions 1234 through 2345 were previously merged from /Trunk to the reintegrate source, but this is not the case
For reference, this is the method we are using:
Create a Branch
Develop in the branch
Occasionally Merge a range of revisions from the Trunk to the Branch
When branch is stable, Reintegrate a branch from the branch to the trunk
Delete the branch
I Merge a range of revisions from the trunk to the branch (leaving the range blank, so it should be all revisions) just prior to the reintegrate operation, so the branch should be properly synced with the trunk.
Right now, the Trunk has multiple SVN merge tracking properties associated with it. Should it? Or should a Reintegrate not add any merge tracking info?
Is there something wrong with our process? This is making SVN unusable - 1 out of every 3 reintegrates forces me to dive in and hack at the merge tracking info.
This problem sometimes happens when a parial merge has been done from trunk to branch in the past. A partial merge is when you perform a merge on the whole tree but only commit part of it. This will give you files in your tree that have mergeinfo data that is out of sync with the rest of the tree.
The --reintegrate error message above should list the files that svn is having a problem with (at least it does in svn 1.6).
You can either:
Merge the problem files manually from trunk to branch, using the range from the error message. Note: you must subtract 1 from the start of the range, so the command you'd run would be:
cd <directory of problem file in branch working copy>
svn merge -r1233:2345 <url of file in trunk>
svn commit
or
If you're certain that the contents of the files in your branch are correct and you just want to mark the files as merged, you could use the --record-only flag to svn merge:
cd <directory of problem file in branch working copy>
svn merge --record-only -r1233:2345 <url of file in trunk>
svn commit
(I think you can use --record-only on the entire tree, but I haven't tried it and you'd have to be absolutely sure that there are no real merges that need to come from trunk)
Bunny hopping might be the solution.
Basically, instead of continuously merging trunk changes into a single branch (branches/foo, let's call it), when you want to pull those changes from trunk:
Copy trunk to a new branch (branches/foo2).
Merge in the changes from the old branch (merge branches/foo into branches/foo2).
Delete the old branch (delete branches/foo).
Your problem is that you're trying to use Reintegrate merge on a branch that has been 'corrupted' by having a 'half merge' already done on it. My advice is to ignore reintegrate and stick to plain on revision merging if this is your workflow.
However, the big reason you get errors is because SVN is performing some checks for you. In this case, if the merge has extra mergeinfo from individual files in there, then svn will throw a wobbly and prevent you from merging - mainly because this case can product errors that you might not notice. This is called a subtree merge in svn reintegrate terminology (read the Reintegrate to the Rescue section, particularly the controversial reintegrate check at the end).
You can stop recording mergeinfo when you perform your intermediary merges, or just leave the branch alone until its ready - then the merge will pick up changes made to trunk. I think you can also byass this check by only ever merging the entire trunk to branch, not individual files thus keeping mergeinfo safe for the final reintegrate at the end.
EDIT:
#randomusername: I think (never looked too closely) at moving is that it falls into the 'partial merge' trap. One cool feature of SVN is that you can do a sparse checkout - only get a partial copy of a tree. When you merge a partial tree in, SVN cannot say that the entire thing was merged as it obviously wasn't, so it records the mergeinfo slightly differently. This doesn't help with reintegrate as the reintegrate has to merge everything back to the trunk, and now it finds that some bits were modified without being merged, so it complains. A move appears kind of the same thing - a piece of the branched tree now appears differently in the mergeinfo than it expects. I would not bother with reintegrate, and stick with the normal revision range merge. Its a nice idea, but it trying to be too many things to too many users in too many different circumstances.
The full story for mergeinfo is here.
I suspect you're not following the merge instructions correctly:
"Now, use svn merge with the --reintegrate option to replicate your branch changes back into the trunk. You'll need a working copy of /trunk. You can get one by doing an svn checkout, dredging up an old trunk working copy from somewhere on your disk, or using svn switch (see the section called “Traversing Branches”). Your trunk working copy cannot have any local edits or contain a mixture of revisions (see the section called “Mixed-revision working copies”). While these are typically best practices for merging anyway, they are required when using the --reintegrate option.
Once you have a clean working copy of the trunk, you're ready to merge your branch back into it:"
I have few problems with merging.