hg: commit a changeset as a merge - version-control

Suppose I have two branches A and B. These two branches have been merged together outside of hg (manually I suppose). The merge itself is correct and the files exactly reflect the merge between branch A and B.
Is there a way to commit those files as a merge? I mean to make them appear in hg as if they were merged using hg and make the new commit have both branches as a parent?

One option is to do the merge, but tell hg that you really want that merge to fail. Then reset the files to the version you want and manually mark them as resolved.
hg -y merge --tool=internal:fail otherBranch
hg revert --all --rev thisBranch
hg resolve -a -m
Once you commit and you should be on your way.
See more details here

Related

Addremove after branch merge?

I work in an environment that has a lot of development across different branches. We use mercurial as source control and often merge branches which contain other features. I am wondering if it would ever be necessary to do hg addremove after a branch merge and before committing?
e.g.:
hg checkout foo
hg merge bar
hg addremove ?
hg commit -m "MERGE: bar -> foo"
Is it perhaps necessary when a changeset that was pulled in added or removed a file, or is this automatically handled by mercurial?
hg addremove is usually not needed during merges. Except when you manually add or remove a file during a merge with conflices where the merge is not automatically handled.
However personally I don't recommend to use hg addremove anyway, especially in merge cases, as I consider it wiser to add and remove files from source control explicitly.

Changing what branch a merge is on without redoing the merge?

If somebody has merged branch B into branch A, but meant to merge A into B (so that the commit would be on branch B), is there a method I could use to get that merge (and all of it's descendents) into branch B? Besides redoing the merge, which was a considerable amount of work.
The following approach should solve your issue, but is not really 'clean'.
Update to branch B (just before the merge).
Start a new merge with branch A. To avoid any interactivity, you can use 'hg merge --tool internal:local'. The actual merging doesn't matter, as you'll use the results from your previous merge.
Revert to the previous merge: hg revert --all -r OLD_MERGE_CHANGESET
Commit the merge.
Use 'hg rebase' to move all your later commits on top of the correct branch.
Assuming that you’ve just committed the merge, or if not, that the merge changeset 1. has no children and 2. is the parent of your working directory, then:
hg branch B --force
hg commit --amend

Mercurial: Add branch from master repository

I have a forked project, and now the master repository has added a new branch which I want on my forked project.
Is it best practice to add the branch locally and then merge from the master repository, or is there a more correct way of doing this?
My guess is this, but I don't want to mess things up:
hg branch theNewBranch
hg pull -r theNewBranch ssh://hg#bitbucket.org/master_repository/theproject
hg merge 0011223344ff
hg commit -m "Merged in master repository branch"
There's no need to add it locally. Every commit has the branch it is on burned into it. If they have a commit on theNewBranch you'll get it.
If you want everything they have mirrored locally just do:
hg pull ssh://hg#bitbucket.org/master_repository/theproject
And if you want to merge in into your local branch do:
hg checkout mylocalbranch
hg merge theNewBranch

How to abort a merge in mercurial?

I goofed up a merge. I'd like to revert then try again.
Is there a way to revert a merge before it is committed?
hg revert doesn't do what I'd like, it only reverts the text of the files. Mercurial aborts my second attempt at merging and complains original merge is still uncommitted.
Is there a way to undo a merge after an hg merge command but before it's committed?
hg update -C <one of the two merge changesets>
After you do hg merge, but before hg commit, your working copy has two parents: the first parent is the changeset you had updated to before the merge and the second parent is the changeset you are merging with. Mercurial will not let you do hg merge again as long as your working copy has two parents.
You have two options on how to proceed:
If you want to abort the merge and get back to where you started, then do
hg update -C .
This will update the working copy to match the first parent: the . always denotes the first parent of the working copy.
If you want to re-merge some files then do
hg resolve fileA fileB
This will re-launch the merge tools just as when you did hg merge. The resolve command is good if you find out at hg merge-time that your merge tools are configured badly: fix the configuration and run hg resolve --all. You can run hg resolve as many times as you want until you are satisfied with the merge.
Today there is hg merge --abort. See hg help merge.

Mercurial: Merging one file between branches in one repo

When I have two branches in Hg repo, how to merge only one file with another branch, without having all other files from changeset merged?
Is it possible to merge only certain files, instead of whole changeset?
WARNING: a "dummy merge", as is recommended by #Martin_Geisler, can really mess you up, if later you want to do a true merge of the two branches. The dummy merge will be recorded, and say that you merge into the branch you did the dummy merge to -- you will not see the changes. Or if you merge into the other branch, the changes on that other branch will be undone.
If all you want is to copy an entire file from one branch to another, you can simply do:
hg update -r to-branch
hg revert -r from-branch file
hg ci -m 'copied single file from from-branch to to-branch
If you want to select different parts of that file, then "hg record" is useful.
I just did this on my home directory .hgignore.
If both branches have made changes to a file that you want to keep, a dirty trick would be to create a merge of the two branches using hg merge, possibly/probably on still another branch, check that in, and then copy a single file between the merge and the to-branch:
hg update -r to-branch
branch merge-branch
hg merge -r from-branch
hg ci -m 'temp merge to be discarded"
hg update -r to-branch
hg revert -r merge-branch single-file
hg ci -m 'merged single-file from from-branch to to-branch"
hg strip merge-branch
It is worth mentioning: the way to "copy a single file between branches" (or revisions, or from revision to merge, or....) is "hg revert". I.e.
hg update -r Where-you-want-to-copy-to
hg revert -r Where-you-want-to-copy-from file-you-want-to-copy
...
hg ci
For some reason I, and some of my coworkers, find this VERY confusing. "revert"=="copy" ... makes sense for some usage patterns, but not all.
Nope. Mercurial works on a changeset basis.
But you can do a "dummy merge" where you ignore the incoming changes from one of the branches. Before you commit you could then revert selected files to whatever state you want:
% HGMERGE=internal:local hg merge # keep my files
% hg revert --rev other-branch a.txt # update a.txt to other branch
% hg commit -m 'Dummy merge to pick a.txt from other-branch.'
Maybe that will help you a bit.
One fairly clean way of getting the desired result is to do it in two steps: first use graft, then second use histedit.
Say this is the starting point and you need to select some portions of C and D to "merge" after E:
A---B---C---D
\
-E
Then you would graft C and D on top of E:
A---B---C---D
\
-E--C'--D'
Then use hg histedit to edit C' and D'. During the edit you can make any changes you want, but in this case you would just revert any unwanted files, (or even portions of them).
(Note that histedit edit works by temporarily updating your working folder to match the content of the given changeset as though it were not committed yet. So you can easily revert unwanted files and then hg histedit --continue which will effectively replace the edited changeset.)
So the final result would be:
A---B---C---D
\
-E--C''--D''
Where the '' revisions were modified as required.
I would say this approach is more beneficial when you have large changesets that probably should have been multiple smaller commits in the first place; this approach allows you to "disentangle" only the parts that you need. Using this for just a single file would be fine but could be overkill.
I would just use an external tool like vimdiff to diff the two files that I want to merge and then merge them. The advantage of this is that you can do selective editing on parts of the file. E.g:
hg update -r branch-merging-to
hg extdiff -p vimdiff -r branch-merging-from file-I-am-merging
To do this you need to enable the external tools in your .hgrc, which just means adding these lines:
[extensions]
hgext.extdiff =
If you are using an IDE:
Merge the old branch with new branch
Go inside the the IDE and remove the unwanted changes
Generate the diff file
Update and clean the new branch
Apply the diff in the new branch