Joshua Goldberg
Joshua Goldberg

Reputation: 5353

Finding mercurial merges that modify a file

In Mercurial, how can I find merge changesets that modify a particular file?

The help for log and diff point out the quirks in dealing with merge changesets.

Is there a way to work around these quirks and find the changes?

Here's an example task: If I'm working on a tricky merge with conflicts, I may want to find all of the changesets on default that touched a file since my branch started, in order to verify and understand the content of the merge. I'd like to be able to say

hg log -pr 'ancestor(mybranch,default)::default' path/to/myfile

and have it show me all of the relevant changes I'm merging in (since the common ancestor). Because of those quirks, however, this misses anything coming in to default by a merge from another branch.

Upvotes: 1

Views: 261

Answers (2)

Aaron Jensen
Aaron Jensen

Reputation: 26809

It seems like you're trying to figure out how a changeset made it into a branch (or what changesets will come into a branch). A common question because merges in Mercurial are not the same as merges in non-distributed version control systems. In traditional VCS, like Subversion, a merge creates a new revision with all the changes from that incoming branch. Thus it is easy to find the merge where a file changed because it changed in the merge.

With Mercurial, however, merges don't behave this way: a merge is more like a labeling operation. Mercurial marks all the changes on the incoming branch as now belonging to the new branch.

Thus, when trying to figure out how a change to a file got into your branch, you have to ask two questions: what changeset introducted the change you're interested in and what merge brought that into your branch. You can use the file() revset query to answer the first question. Once you have that changeset, then you can use this revset query to find out what merge brought it into your branch: 'descendants(<the_rev>) and branch(<the branch>).

To find all the changesets that will be merged in and that modified a particular file:

 hg log -r "(::<incoming_branch> - ::<destination_branch>) and file('path/to/the/file')"
  • ::<incoming_branch> gets all the ancestors of the incoming branch
  • ::<destination_branch> gets all the ancestors of the destination branch
  • - removes all the common changesets, leaving only those that haven't been merged
  • file('path/to/the/file') filters the results to changesets that modifed that file

Upvotes: 1

Lazy Badger
Lazy Badger

Reputation: 97365

all of the changesets on default that touched a file

Excuse me, but isn't it just

hg log -r "branch(default) & file('path/to/myfile')"

or, if you want to have -M also

hg log -r "branch(default) & file('path/to/myfile') & !merge()"

Upvotes: 0

Related Questions