Understanding the Mercurial merge changeset - mercurial

If I have two heads in my repo - C and D which have the common parent of B - and I do an hg merge then a hg commit, what exactly is in that merge changeset? I am trying to understand what I see what I do hg diff -c xyz where xyz is the id of the merged changeset.
Will the changeset show the diffs of all files modified in C and D vs. the state of those files as they existed in the common parent repository B?

A merge commit has two parents, so when running a diff it is important to understand which parent you are diffing against.
hg diff -c <changeset> shows the diff of the changeset relative to the first parent.
From hg help diff:
diff may generate unexpected results
for merges, as it will default to
comparing against the working
directory's first parent changeset if
no revisions are specified.
To diff against a specific parent, it is best to provide the explicit revision of both the merge changeset and corrent parent (e.g. hg diff -r <parent> -r <merge changeset>

Mercurial implements a directed acyclic graph so in your merge changeset depends on where you're coming from. When you type "hg merge" it assumes "tip" (much in the same way hg pull assumes the root repository from which you cloned your head) If you type "hg heads" you can see which one is the tip. When you do this merge, assuming C as the tip, you are merging in the changes from D.

Related

Revert pushed bad merge in hg

I stated working by creating a new branch (say) new-feature and done all the changes ( a lot of files has been changed).
And I wrongly merged it with a branch say 'my-client' branch where every one works and pushed the code to the repository. I want to remove the merge I've done.
No other developers currently working on branch 'my-client'.
I have tried
hg backout <REV> // rev of the bad merge
abort: cannot backout a merge changeset.
Is there any way to fix it?

mercurial hg up -C created a branch with the same name as current, how to remove it or merge it

I had a change in my branch and after unseccessfull merge, I tried to revert that unsuccessefull merge with hg up -c but it created a new branch instead. I can merge it into current or discard it or what to do with it?
EDIT:
actually I did the following, I had a branch and committed changes there there. then I wanted to push my changes to server, so I pulled changes, and tried to merge with them, but there were a conflict I couldn't resolve myself and I thought: I'll revert all changes back and merge again - so used hg up -C which I thought, will revert everything I changed during my unfinished merge. But what actually happened, another branch with the same name was created, containing only that changes I committed previously and with the same name as a branch I was working in and I was switched to the branch where I was working, which didn't have my changes. So two questions here: what actually happened and why another branch with the same name was created?
Having multiple heads on the same branch, which I think is what you're saying with "a branch with the same name as current" is a normal situation and, yes, you can use hg merge to consolidate them into one head. Use the hg heads command to find the hashes of the two heads of branch X. Then:
hg update REVISION_ID_OF_ONE_HEAD # changes your working directory to match one of the heads
hg merge REVISION_ID_OF_THE_OTHER_HEAD # merges that head's changes in
hg commit # create a new changeset that is the child of both those heads thus reducing the head count by one
Also #ringding is correct that hg update never creates branches. You either already had them and didn't know or received another head when you pulled.

merge in mercurial with automatic comment listing changeset ids/guids for the two heads

I stopped using hg fetch to pull and merge in another head for a Mercurial repository because I like to make the commit message say what is merging with what. Furthermore, I am moving from "merge repo1 -> repo2" to a more specific "merge head1guid -> head2guid" format.
How can I automate this so I don't have to list the heads with hg heads then copy and paste the guids for the two changesets into my commit message?
As others have pointed out in comments the one or two parents of a changeset are already stored in a changeset and shown in hg log and other command line views -- You're probably better off not re-storing them.
If you really wanted to you could do something like:
hg commit -m "merging $(hg log -r . --template '{parents}')"
but I always try to put something actually useful in the message like "Merging Jim's work on foo into Alice's work on bar"; there's no new information in re-storing the nodeids of the parents.
Note that command only works when you're committing a merge -- it'll be empty otherise.

How to compare sets of changesets between 2 Mercurial branches?

I've got a (remote) Hg repository with a couple branches. I want to verify that branch A has every changeset that branch B has (it may have more, and that's OK).
Is there an easy way to do this with just hg?
I can write a little shell script to do it, but it seems like the sort of thing that might come up a lot, so maybe there's an easy built-in way.
This will show any ancestors of changeset b which are not an ancestor of changeset a:
hg log -r "ancestors(b) and not ancestors(a)"
This should show you which changes still need to be merged from B to A if you give the head of branch B for b, and the head of branch A for a.

Mercurial remove changeset, history with merges

I want to remove a changeset from history but hg export does not work for merge changesets (see https://www.mercurial-scm.org/wiki/Export). Is there a way to use hg pull for a range of revisions? For example, say I want to remove revision 999 I want to be able to say:
hg init NewRepo
hg pull ../OldRepo -r 0:1000
hg pull ../OldRepo -r 1000:tip
Any ideas?
Pull can't pull a range of revisions because every mercurial revision that exists in a repository must have all of its ancestor changesets in that revision too. So if you do:
hg pull ../oldRepo -r 1000
you get all of revision 1000's ancestor revisions too.
In general, mercurial is about building an immutable history -- if you regret a changeset you don't remove it you create a new one that undoes the work of the changeset you no longer like. If you can't abide having full history in your repo you need to use something like the strip or convert extension. Both work as advertised, but provide plenty of opportunities to shoot yourself in the foot. If you can stand it, just undo the onerous changeset in a subsequent changeset and move on.