Mercurial: Move a collection of files to an unrelated repository - mercurial

I have a bunch of files, its actually a c# project and the files related to it, the whole hg repository is a solution with many projects.
I need to move those (with history) to another existing repository .
What is the best way to do this?

Say, you have A and B repositories. Your goal is to extract an 'a' folder in A and merge it with B to make B_with_a, while preserving histories.
1) Extract 'a' in A and make Aa. You can do this with hg convert:
~$ hg convert A Aa --filemap list.txt
where list.txt is
include a
2) Pull Aa to B - to make B_with_a_yet_merged. You have to use -f since they are not related.
~/B$ hg pull ./../Aa -f
3) Merge two branches in B_with_a_yet_merged to make B_with_a
~/B$ hg merge (with the last rev in Aa)
PS.
Don't forget to backup A and B beforehand! When I first did this, I messed up repositories three times.

After a poke around hg commands I found bundle, seemed to have made the trick. More details soon
Update: tried this and didnt work. It brought the files when I unbundled it, and I was able to merge, but for some reason the graph was off.
I just thought I d post for completeness

Related

Synchronizing changes from a child mercurial repository created with hg convert back to its parent mercurial repository

I have a parent repository A.
I've created a small child repository B of the parent repository containing a cherry-picked small list of sub-folders for access by another team using hg-convert
hg convert A B --filemap filemap.txt
where filemap.txt doesn't do any renaming. It only includes or excludes folders. Such as:
exclude *
include folder1
include folder2/subfolder1
include folder2/subfolder2
include folder2/subfolder3
exclude folder3_that_was_pulled_in_for_some_reason
Converting from A to B works fine. I can also re-run the hg convert command to "push" subsequent changes on A to B (I'm using the term push loosely here...)
But what about when I want to "push" changes from B back to A? Running hg convert B A without the filemap recreates all the commits in B back in A so I have loads of duplicated commits in A.
Is there a reasonable way to keep A and B in sync in future? Is it likely to be impossible if changes are applied to A and B in different orders?
There's no good way to do this, which is why convert shouldn't be part of a bi-directional workflow. It is possible to use convert incrementally, so you can go A to B many times, but you can't go B to A. You could try to hg export patches from B and hg import them into A, and it would probably work, but when you then hg convert A into B again they'll double up and the merge will probably be hard.
Consider splitting the repo into two separate repos with
the public stuff as a sub repository of the whole repo.
/projectname
stuff.txt
/folder1
/folder3_that_was_pulled_in_for_some_reason
/projectname-public
/folder2/subfolder1
/folder2/subfolder2
When projectname-public is a sub-repository, then it can be cloned separately, released separately, and you can take pull requests and patched and merge them in easily.
Subrepos aren't for beginners, but they're easier than round-tripping on convert.

How to diff two revisions of a file that got renamed in between and Mercurial doesn't know about the renaming?

I accidentally renamed a file outside of Mercurial. When I committed the change, Mercurial treated the change as two unrelated files (ie. a remove and a add). I need to go back to diff the two revisions but I don't know how to do so when Mercurial sees them as two respective files across different revisions. What can I do to diff the files?
You didn't say what operating system you were using. The following will work with bash on Linux:
diff <(hg cat -r rev1 file1) <(hg cat -r rev2 file2)
You can replace diff with another program like vimdiff if you want a visual diff.
If you want to actually fix the history so that Mercurial is aware of the rename (and can use that information in future merges if needed), there's a way to do so documented on the Tips and Tricks page on the Mercurial wiki.
Current contents copied here for ease of use (and in case the link gets broken later):
Steps:
Update your working directory to before you did the rename
Do an actual "hg rename" which will create a new head
Merge that new head into the revision where you did the "manual" rename (not the head revision!)
Then finally merge the head revision into this merge result.
Advice:
Make a clone first and work on that, just in case!
After finishing the steps, use a file compare tool to check that the original and the clone are identical
Check the file history of any moved file to make sure it is now restored
That being said, if all you want to do is compare the contents at the point in time, you can definitely accomplish that without making Mercurial aware of the rename (as mentioned in Stephen Rasku's answer). In fact, you can use a combination of "hg cat" and an external comparison tool to compare any files, not just ones that Mercurial knows about.
Fix history:
Update to first changeset with new-filename, save file outside WC
Update to parent of bad replacement changeset, replace file correctly (with rename tracking), commit, got second head
Rebase all changesets from old anonymous branch on top of fresh good changeset
--close-branch on bad-replacement changeset or delete this unwanted changeset or leave inactive head intact

Excluding a file while merging in Mercurial

I use Mercurial with TortoiseHg. I have two branches (A and B) with two files (toto.cs and titi.cs).
Is there a way, when I want to merge B with A, to exclude titi.cs from merging, and only merge toto.cs? If it's possible, how can I do that?
Sure. Not merging titi.cs is really just using titi.cs exactly as it exists in A or in B (your choice). You could do that manually like this:
hg update A
hg merge B
hg revert --rev A titi.cs
(swap A and B to go the other direction).
Or you could do that automatically in your Merge Tool Confguration with something like this in your .hgrc.
[merge-patterns]
titi.cs = internal:local
Which tells Mercurial to always use "this one not that one" for files matching that pattern.
If you're talking about a certain file which you want to be exempt from merging, then see #Ry4chan's answer. This is perfectly valid: some files, like build-relating configs, can be autogenerated, and conflict resolution for them is useless. Or, you might actually want to drop changes made in a source file.
If, on the other hand, you are trying to mimic file- or directory-limited merges of SVN-like systems, be careful. The revert trick does not mean you merged some files and didn't merge other: you merged everything, the revert was just a kind of merge.
If you want to move some changes from one branch to another (say, backport a fix in a certain subsystem to an old stable branch), you don't merge the files with the fix; instead, you merge the changesets containing the fix; hg graft will help you do so.

Using Mercurial (hg), is there a way to diff rev 4873 and 4821 but only for my changes?

I want to know what changes I made, without looking at the 30 other files that other team members modified.
So when I hg out, it said the first changeset to push was 4821, so since then I have pulled, merged, and pushed a couple times. Now I want to make sure all the debugging code is removed. Is there a way to diff the current revision (4873) against revision 4821 but only for my changes?
If your changes are in different files than those of your coworkers, which is how it sounds, you can use something like this:
hg diff -r 4821 -r 4863 -I path/to/file1 -I path/to/file2
If they're mixed in the same files as other people's changes then you would have needed to keep your changes in a separate branch (which doesn't require the branch command, anonymous branching is commonly used for this sort of thing).
The following command should do the trick:
hg diff -r "4821:4873 and user(your_username)"
I don't know if you can upgrade to the recently release Mercurial 1.6 or not, but this functional query language feature they just put in is what you might be looking for.
Try this approach:
First clone your local repo to another folder
In the new clone, rebase your last changeset so that it immediately follows your the other changeset (this should create a new head from it)
Do the diff

How can I do a changeset based merge instead of file-by-file based merge with Mercurial?

When performing a merge with Mercurial, it wants to merge conflicting files one at a time which just isn't a productive workflow on large merge sets. Instead, what I would like to do is merge the entire changesets of both heads (like using kdiff3 to diff 2 heads). To me that sounds straightforward but I can't figure out how to achieve it.
So far, the closest I can get is to go through the merge the usual way, leave all the conflicts unresolved (a file at a time...), and then hg vdiff -rHead1 -rHead2 - but vdiff (using kdiff3) doesn't seem to have options for passing the tool an output dir (the current working dir) and instead launches with the output dir as a tempdir (possibly -o is the answer?).
Let me put it another way - I want to use kdiff to merge two heads into my working directory. I want the results in my working dir to be my merge that I can commit.
I must be missing something obvious, I can't be the only one who wants to do this.
I came up with a solution that achieves what I want but I still feel like it's a kludge.
Start with an empty working dir with 2 heads: Mine and Theirs.
Update working dir to Mine:
hg update [My head's rev here]
Perform a merge, but fail all files that Merc can't handle automatically without launching a merge tool and keep "My" files when in conflict:
hg --config "ui.merge=internal:fail" merge
See https://www.mercurial-scm.org/wiki/TipsAndTricks#head-9f405488b6d3b3d092a09aafa28db515ba44c742 for how-to merge/fail details.
Now I've got a working dir with as much as auto could figure out, but any outstanding files still untouched from Mine. (Use hg resolve -l to see the Mercurial's resolution status of current files)
Now I can vdiff my working dir against the Theirs head which gives me the high level, changeset-to-changeset merge that I was looking for.
hg vdiff -r [Theirs head's rev here]
Note: If you're using WinMerge for your vdiffs , then make sure it has an /r switch as an option which will do a subdirectory compare and - if WinMerge config is set to use Tree-View - will give a great tree comparison. From Mercurial.ini:
[extdiff]
cmd.vdiff = C:\Program Files\WinMerge\WinMergeU.exe
opts.vdiff = /e /ub /r /dl other /dr local
Now I can work the entire directory which includes the unresolved files and make project wide changes as necessary (ie. maybe resolving one file requires additional changes in another).
When done use resolve to mark all files resolved for Merc and then commit.
hg resolve -m
Whew! Here's hoping this helps someone else!
I relayed the question to #mercurial on irc.freenode.net a couple of days ago. mpm (the author of Mercurial) gave sort of an answer (it was only half an answer, so I didn't immediately pass it on here). He said that one might be able to do something where you let Mercurial merge the files automatically (and insert the <<<< and >>>> merge markers where there are conflicts).
Then use a merge tool that knows about these markers: this will let you resolve them all at once instead of doing it on a file by file basis. A starting point would be the page on merge tool configuration. It explains that
[ui]
merge = internal:merge
will make Mercurial inserte the merge markers. Here I tested it by making two files x.txt and y.txt which I then modified with conflicting changes in two clones. The merge simply gave:
% hg merge
merging x.txt
warning: conflicts during merge.
merging x.txt failed!
merging y.txt
warning: conflicts during merge.
merging y.txt failed!
0 files updated, 0 files merged, 0 files removed, 2 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon
All files were processed in one go, I did not have to confirm anything per file like you describe.
The files now contain merge markers like this:
% cat x.txt
foo
<<<<<<< local
hehe
=======
foobar
>>>>>>> other
The next step is to find a tool that can take a directory tree with such files and let you resolve them. I looked at kdiff3, but did not figure out how to use it to operate on a single file alone, it seems very focused on comparing pairs of files/directories.
I'm not sure how much this half answer helps you -- maybe you also got stuck at this point? But I hope it can help others who want to have the merge markers inserted into all files and then resolve the conflicts by hand.
I think this answers your question.
sounds like you want the extdiff command:
i have these in my ~/.hgrc (I prefer meld, but you can change it to kdiff3, etc)
[extensions]
hgext.extdiff =
[extdiff]
# add new command called meld, runs meld (no need to name twice)
cmd.meld =
With extdiff your merges occur in your working directory, and moreover you can pass any extra parameters to your diff program with -o:
$ hg help extdiff
hg extdiff [OPT]... [FILE]...
use external program to diff
repository (or selected files)
Show differences between revisions for the specified files, using
an external program. The default program used is diff, with
default options "-Npru".
To select a different program, use the -p option. The program
will be passed the names of two directories to compare. To pass
additional options to the program, use the -o option. These will
be passed before the names of the directories to compare.
When two revision arguments are given, then changes are
shown between those revisions. If only one revision is
specified then that revision is compared to the working
directory, and, when no revisions are specified, the
working directory files are compared to its parent.
options:
-p --program comparison program to run
-o --option pass option to comparison program
-r --rev revision
-I --include include names matching the given patterns
-X --exclude exclude names matching the given patterns
Try setting ui.merge. See this page for more details.