Reputation: 1390
I use Mercurial named branches regularly for job and for hobbies, and I thought I understood them reasonably well. I also thought that I understood the differences between named and unnamed/anonymous branches. But a group at work has run into a problem that I admit has me a little stumped, and now I'm questioning my own understanding and all of my life decisions.
A coder was working on their default/unnamed line of development:
A -> B -> C
Then they did a few small commits for a side task, with the intention of later updating back to an ancestor and resuming normal checkins there. That is, first doing:
A -> B -> C -> D -> E -> F
and then committing more to C:
/-> D -> E -> F (unnamed branch for later)
/
A -> B -> C ---> G (new tip)
Their plan is to come back to F at some future date. So they did all that; work continued at G, and that part of the graph has been a surprisingly straight line from G to say M.
Now they want to sync their repo, and the target repository stops at say B. (Both pushing or pulling are viable, so they'll use whichever approach supports whatever options are needed.) Except that only the main path through the graph
A -> B -> C -> G -> ... -> M
should be pushed/pulled. The D->E->F
branch is topologically unrelated, and shouldn't (to my understanding) count as ancestors of G onward. But trying things on the target repo like
hg incoming -r M /path/to/above/repo
hg incoming -r M -b default /path/to/above/repo
is correctly finding B as the most recent common ancestor, but then it decides that all changes "more recent" than B need to go across, instead of the ones along the branch from M back to B.
Gotta admit, I'm not sure how to exclude the little unnamed offshoot branches. Personally, I typically clone the repo at C and then commit D through F off in the clone, but that's why I've never run into this situation and can't answer their question. I've found lots of "guides to branching" that explain how to merge F back into M, and how to make sure the D->E->F
branch is pushed remotely (--new-branch
), and several writeups on how to make the offshoot go away (variations on --close-branch
and no-op merging), but I know and use all of those already; I'm drawing a blank on how to simply leave it behind across a pull.
After we played around for a while and couldn't find the options to do this, their eventual solution was to clone the repo containing the offshoot, then strip the offshoot changesets before finally synchronizing. Which everyone agreed was kind of kludgy, but at least let their team make progress again. I'd like to find something better for next time.
Upvotes: 0
Views: 32
Reputation: 489045
The easy way to do it is to mark these commits secret so that they just don't get exported at all. That's not quite what you asked, but that's what I'd do. Ignoring that option, though, I think the short answer is that you can't, at least not directly. But that might be wrong; maybe you can, using the Convert extension.
Mercurial documentation likes to call these anonymous branches, but I think that this phrase is ill-advised. I would just call them daglets, made up of a selected (usually linear) chain of commits leading up to each head. A branch in Mercurial is a named entity. Every commit exists on exactly one branch. When you have a situation in which the default
branch has commits:
D--E--F
/
A--B--C--G
what you really have is one branch, named default
, with seven commits and two heads. The fact that one head is named tip
at the moment is not really relevant since we could easily create a new branch X
with commit H
:
default: D--E--F
default: /
default: A--B--C--G
\
X: H
and now tip
means commit H
, not commit G
. Branch default
continues to exist with its seven branches and two heads. When you hook two hg repositories together, they'll transfer commits according to the (named) branches.
The convert extension does let you skip and/or re-map parts of the graph. It's possible that you could use this to keep D-E-F
from coming in, and/or to splice them into a different branch. It seems like making this work would take a lot of human-time (and effort) and hence not really be particularly viable, though.
Upvotes: 3