Reputation: 5353
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.
modifies()
in the revset or passing the filename as another argument)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
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 mergedfile('path/to/the/file')
filters the results to changesets that modifed that fileUpvotes: 1
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