Merging two different directory trees - Mercurial - mercurial

I am here to ask a sort of theoretical question since I am working on a merging proof of concept for two Mercurial repositories. Currently, I have two repositories with entirely different tree structure. Let's call them Repo A and Repo B.
The directories looks as following:
Repo A Repo B
| |
Dir A -- Dir A1 -- File A Dir A --- Dir A1 -- Dir A2 -- File A2
| | File A File A1
Dir B -- Dir B1 -- File B1 |
File B |-- Dir B -- File B
So, in Repo A , the dir B is present in the same level as dir A but in Repo B, dir B exist inside of dir A. Both of them are active repositories so they have their own code changes histories but Repo B has the latest changes for dir B.
What I would like to achieve is to merge Repo B onto Repo A tree structure and maintain the change set history and tags of both repo A and repo B for dir A and dir B without losing anything.
I've read an article http://hgtip.com/tips/advanced/2009-11-17-combining-repositories/ but I'm not sure if its applicable in what I am trying to do. If there is a similar question before mine, please help point the link out. Or any useful articles will help too.
Otherwise, guidance from all of you will be great. XDD
Thanks.

Indeed, you basically linked one version of the answer already yourself - that's exactly what you want to do:
prepare one repo (or both) such that the internal directory structure matches eachother, so that no naming conflicts occur for stuff which needs to stay separate and those things which are the same are named identically
pull one repository into the other. You will be warned that you are pulling from an unrelated repository. That's fine, that's what you want to do. You will end up with a repository with two independent branches.
merge the two branches and resolve the conflicts in the manner you need
You see one such thing in this one example repo where we merged two closely related tools into one code base.

Related

How to work with Mercurial fork parent repository?

For example exists hg rep A - project setup environment. It contains following files:
//project A
.some_config_file
script_1
After project B forked from A, some changes was made.
// project B
M .some_config
M script_1
Parallel in project A there has been improved some features or bug fixed in script_1.
// project A
M script_1
When I try to pull new features (hg pul -u 'repA') to B from A, it brings old .some_config back to repository and overwrites actual one.
And there is my questions:
How do I resolve this conflicts?
How to pull partially changes from fork parent?
And what the best practice to work with fork parent?
Pulling from forked rep, pollutes local one.
You seem to be unfamiliar with the distinction of your 'working copy' and the repository as a tree of individual changesets.
The solution likely is: update your working copy to your fork B. Then merge the original project, fork A, into your currently checked-out version, into fork B. Take care to only accept those changes during the merge which you want to be merged - and discard any changes made to .some_config
Besides that, it's often a bad idea to have config files in a repo. Only have example config files there (and name them such) and keep the actual config file outside, untracked.

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.

Mercurial: Move a collection of files to an unrelated repository

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

Does a mercurial subrepository have to be a subdirectory of the main repository?

My project is made up of code in the following locations
C:\Dev\ProjectA
C:\Lib\LibraryB
C:\Lib\LibraryC
Presently each of these folders is a completely independent Mercurial repository. Project A changes all the time, Library B and Library C change rarely.
I currently tag each version of Project A as it is released and (when I remember) put a corresponding tag in the Library B and C repositories.
Can I improve upon this by using subrepositories? Would that require me to make Library B and C a subdirectory of Project A?
If Library B and C must be subdirectories of Project A what do I do if I want to start a Project D that uses Library B but isn't otherwise affiliated with Project A at all?
If Library B and C must be
subdirectories of Project A what do I
do if I want to start a Project D that
uses Library B but isn't otherwise
affiliated with Project A at all?
Any project can exist both independently and as subrepository of another project at the same time. I'll explain by suggesting a workflow.
First of all, each of your projects (A, B, C) should have a blessed repository that is published somewhere:
You could run hgwebdir on your own server, or make use of a Mercurial hosting service like Bitbucket or Kiln. This way developers have a central authorative point to pull/push changes from, and you have something to make backups of.
Now you can make clones of these repositories to work on in two different ways:
directly clone your project. For example:
hg clone http://bitbucket.org/LachlanG/LibraryB C:\Lib\LibraryB
and/or create subrepository definitions by putting a .hgsub file in the root of ProjectA with the following content:
libraries/libraryB = http://bitbucket.org/LachlanG/LibraryB
libraries/libraryC = http://bitbucket.org/LachlanG/LibraryC
These subrepository definitions tell Mercurial that whenever Project A is cloned, it also has to put clones of Library B and Library C in the libraries folder.
If you are working in Project A and commit, then your changes in libraries/LibraryB and libraries/LibraryC will be committed as well. Mercurial will record which version of the libraries is being used by Project A in the .hgsubstate file. The result is that if you hg update to an old version of the project to see how things worked last week, you also get the corresponding version of your libraries. You don't even need to make tags :-)
When you hg push the Project A changes to the blessed repository, Mercurial will also make sure to push the subrepository changes first to their own origin. That way you never accidentally publish project changes which depend on unpublished library changes.
If you prefer to keep everything local, you can still use this workflow by using relative paths instead of URLs in the subrepository definitions.
You can indeed declare B and C subrepos of project A (they will appear as subdirectory, as described in Mercurial Subrepository).
That would improve your release mechanism as it would allow you to:
get all repos in one place (A and under)
reference an exact tag of B and C under A
tag each sub-repo s first if they had any modification
tag A with the information about B and C tags in it (any clone of A will be able to get the exact tags of B and C used by A)
You can also declare B as a subrepo of D, independently of A. What you make in A (regarding B) will have no consequences for B used in D.

Sync files in Two Different Repos using HG

I've got a problem when I try to sync files in two different repos. What I want to do is:
I've got 2 repos A and B, and they share some common files, suppose they lie in A/docs/common/ and B/docs/common. So when I write some new docs in A and I want to update it to B or vice versa. How can I do?
I try this: I write a .hgignore in A to ignore the files I don't want to sync to B, and then try to hg push B's repo url. It doesn't work.
So how can I do this?
Thanks.
If I'm reading it correctly and your repository roots are above the docs directory (test: hg root says /file/path not /file/path/A) Your current soln, ignoring the files outside of docs in both repos, won't work because mercurial tracks full file paths back to root, to A/ and B/ are part of your file paths so they're different in different the two repos making them separate repos.
One thing you could do is use Mercurial's sub-repository support to make docs a sub-repo that's "included" within both A and B. Then you can push/pull docs around and the separate, different parent repos will keep track of what point on docs they've been updated to.
If I misread your original situation and A and B are just separate clones and docs is a top level directory with the same path in both repos (test: hg root is /file/path/A and file/path/B), then you've got a totally normal mercurial situation that should be working. Just make sure you're commiting, pushing (or pulling), and updating and you should see changes migrate across.