问题
Having two branches, how can I find the latest revision(s) where the two branches were merged? Is there a standard Mercurial command to do that?
This is the same as question How to find the common ancestor of two branches in SVN?, but for Mercurial instead of subversion.
I didn't understand why Lazy Badger's answer was the right one, so I had to make a little drawing, and now I get it:
When two branches are merged, they are not really "merged", but the changes from one branch are integrated into a second branch. This means that the merge commit only belongs to the originating branch, and not to the merged branch. This is why the merge revision is one of the two children of the ancestor revision.
This is probably best seen with a picture:
default o----o----a---b---o---o
\ \
other `-o---o---m---o
ancestor(default,other) == a
children(ancestor(default,other)) == (b,m)
children(ancestor(default,other)) and merge() == m
回答1:
hg log -r "children(ancestor(default, Cleanup)) and merge()" --template "{rev}\n"
is latest merge for default and Cleanup branches (polished version of Tim Henigan's answer).
回答2:
In recent versions of Mercurial (>1.7), you can do this with revsets:
hg log -r "max(ancestor(<branch1>, <branch2>))"
The same revset filter also works in the Filter toolbar of TortoiseHg.
回答3:
You can rewrite this query to:
- The closest single changeset that is an ancestor changeset of the tip of both branches
Let's assume you have two branches, identified by R1
and R2
, be it the name of the branches or the revision number or hash of a changeset in each, or whatnot.
Then you can find the changeset you're looking for as:
hg log --rev "ancestor(R1,R2)"
回答4:
If you have more than two branches then you have to add an additional filter to Lazy Badger's answer, because children() might give you also children that are not in your branches.
hg log -r "children(ancestor(default, Cleanup)) and merge() and branch(default|Cleanup)" --template "{rev}\n"
other o---o-----m1---o
/
default o---o---a---b---o
\
another o---o-----m2---o
ancestor(default, other) == a
children(ancestor(default, other)) == (m1,b,m2)
children(ancestor(default, other)) and merge() == (m1,m2)
children(ancestor(default, other)) and merge() and branch(default, other) == m1
回答5:
Just for the posterity this is not right in the case the left branch has not been merged with the right branch, but the left branch has lately been merged into right.
The correct solution is:
last(parents((ancestors('{left_branch}') and branch('{left_branch}') and merge())) and branch({right_branch}))
回答6:
You can find all the merges from a source branch into a destination branch with this revset query:
children(p2(::DESTINATION and merge()) and branch(SOURCE)) and branch(DESTINATION)
::DESTINATION and merge()
gets all merges in the destination branch.p2(set)
returns the second parent of each merge, which is always the changeset on the source branch which was merged into the destination branchand branch(SOURCE)
filters all those merges into just those that came from the source branch.children(set)
returns all the children ofp2()
, one of which is the merge we're looking forand branch(DESTINATION)
filters the children ofp2()
to just show changesets on the destination branch, which, it just so happens, are the merges we're looking for.
So, to get the last merge from source into destination, wrap the above query with the max(set)
query. So the final command would be:
max(children(p2(::DESTINATION and merge()) and branch(SOURCE)) and branch(DESTINATION))
回答7:
hg log -r "last(ancestors(target) & branch(source))"
This gives you the least common ancestor of target and source branch ON source branch.
source o---a---o---m2---o
\ /
intermediate o--o--m1---b---o
\
target o---o------------m3---o
The least common ancestor of source and target branch in this example would be b, but b is not on the source branch, we therefore want to get a back.
To get b back you can use the solution of Lasse:
hg log -r "ancestor(source, target)"
I often want to know the latest "default" revision in some task branch and I don't care if my task branch was directly merged with default or via some intermediate path.
来源:https://stackoverflow.com/questions/8067084/find-the-latest-merge-point-of-two-branches