how can I split a mercurial repository? - mercurial

The format of the hg mv command is hg rename [OPTION]... SOURCE... DEST
. Path names are relative to the current directory. Thus, when you are at a command prompt at the root directory and specify hg mv -n -I * A\B Z, mercurial will create the directory Z under the root directory, and move A\B\readme.txt to Z\readme.txt.
How can you specify, under Windows, that Z is the repository root directory? I tried using '.' as destination, i.e. hg mv -n -I * A\B . but got a message that A\B\readme.txt will be copied to B\readme.txt, not to readme.txt at the root. I tried using '~' as the destination, but hg mv -n -I * A\B ~ got me a new directory named "~" below the root, obviously not what I wanted.
So my question is: How do I specify the repository root directory as the destination to the mercurial move command?
edit: I'll try to clarify the issue.
I have an OldDev repository containing two products: Product-A and Product-B. Using the '~' symbol to denote OldDev's root folder, OldDev contains two folders: ~/Product-A and ~/Product-B (in addition, of course, to ~/.hg where its metadata is stored).
Each product is composed of a few projects, and each such project is assigned a folder under the product's folder. Thus Product-A has the Project-A, Project-B and Project-C, stored in ~/Product-A/Project-A, ~/Product-A/Project-B and ~/Product-A/Project-C, correspondingly. ~/Product-A/Project-A/xxx.cs is one of (Product-A's) Project-A's files.
Now I want to extract Project-A to its own NewDev repository. As it's the single project in NewDev, it makes no sense to retain the product/project hierarchy, so I want it to be at the root of NewDev: it xxx.cs file, for example, will be #/xxx.cs, where # is the root folder of NewDev (the one contianing NewDev's .hg directory where NewDev's metadata is stored).
To extract Project-A to NewDev I used the the convert extension, as documented in "split a repository in two". I used a mapfile containing the one mapping include Product-A/Project-A.
So far, NewDev is an exact subtree of OldDev. It does not contain ~/Product-B, it does not contain ~/Product-A/Project-B nor ~/Product-A/Project-C. It only contains ~/Product-A/Project-A. The files that remained are located at exactly the same paths as before, but only those files that belong to Product-A's Project-A were retained.
So, I've achieved half of my goals: I split OldDev, with its many products and projects, and created NewDev with only one project (Project-A). However, the files of Project-A are not at # but at their old (OldDev) location #/Product-A/Project-A. I need to move them up two steps so xxx.cs, will be at #/xxx.cs and not at #/Product-A/Project-A/xxx.cs
To move the files I tried to use the hg mv command, but I can't figure how to specify the root (#) as the destination.
Solution: What worked for me, based on Marc Anton Dahmen's answer, is as follows:
convert1.txt: hg convert -s hg -d hg --filemap mapfile1.txt olddev temprepo
mapfile1.txt: include Product-A/Project-A
convert2.txt: hg convert -s hg -d hg --filemap mapfile2.txt temprepo newrepo
mapfile2.txt: rename Product-A/Project-A .
Where the text of convrert1.txt and convert2.txt, of course, shell commands.

You must use the rename directive in your filemap instead of include like so:
rename Project-A .

Moving every file in a repository and the repository data is not an hg mv operation because that cannot change where the repository meta-data is stored.
The wording of your question is still really ambiguous, but I have a decent guess as to what you want to do.
Suppose you have a repo called /some/dir/avi-repo and you really want it to be in /avi-repo. Use clone:
cd /
hg clone /some /avi-repo
Now you have two identical copies of the repo, one in /some/dir/avi-repo and one in /avi-repo. You can delete all of /some/dir/avi-repo now.
Your desire seems a little more complicated than that with a tree like:
/some
---- /.hg # the repository meta-data
---- /dir # no files in here just the sub-dir
-------- /avi-repo
------------/file.c
------------/file.dat
------------/important-file.txt
And you want to move avi-repo to /some/avi-repo. You should be able to do that with the right sequence of mercurial commands, but it is far easier to:
mkdir /temp
cd /temp
hg clone /some /temp/avi-clone
rm -r /some
mkdir /some
hg clone /temp/avi-clone /some
Or some variant of that. The point is that repatriating an entire repository is not a job for hg mv.

Related

TortoiseHG forget files in all sub folders of specific name

I have a pretty large folder (with many sub folders) on a mercurial repository. I was a bit too fast with my first commit so I added a lot of files that i now realize shouldn't be on version control. I've updated my .hgignore file accordingly but all the old files are still version controlled. Is there a command that I can write in the root directory that forgets all files that are in a folder of a specific name. These folder names exist in a lot of places and i want them all forgotten with one command since it would take a long time to go through them all manually and forget the folders/files
I guess it would maybe look something like this:
hg ignore ../folderName/
Yes... use a pattern to match them like
hg forget FOLDERNAME**
hg commit -m "Forget FOLDERNAME"
hg help forget
hg forget [OPTION]... FILE...
(...)
options ([+] can be repeated):
-I --include PATTERN [+] include names matching the given patterns
or use a one-line script:
for i in $(hg ma | grep FOLDERNAME); do hg forget $i; done
You can read hg help filesets and use one of it's samples
Forget files that are in .hgignore but are already tracked:
hg forget "set:hgignore() and not ignored()"

Create a Mercurial repository out of an existing directory in another repository?

I want to split up one of my Mercurial repositories into two separate repositories. In particular, I want to take a directory sitting at the root level of the repository and convert that into it's own repository.
My initial thought on how to do this is to tell the existing repository to forget about that particular directory, add the directory to .hgignore, and then convert the directory into it's own repository. However, I'd like to preserve the history of the directory in the new repository.
How can I achieve this?
Convert extension with --filemap option will do it. See Converting from Mercurial part
It's also useful to filter Mercurial repositories to get subsets of an
existing one. For example to transform a subdirectory subfoo of a
repository foo into a repository with its own life (while keeping its
full history), do the following:
$ echo include subfoo > /tmp/myfilemap
$ echo rename subfoo . >> /tmp/myfilemap
$ hg convert --filemap /tmp/myfilemap /path/to/repo/foo /tmp/mysubfoo-repo

I want to create a versioned folder as a result of mercurial "hg clone <repo url>"

When cloning a repository in Mercurial, is there a way to create a target folder based on the latest changeset? Example:
$ hg clone http://hg.repo.com:8000/myrepo 'myrepo-$VERSION'
The folder should be named after the version of the project, e.g., myrepo-1.3.
If you are okay with using the changeset hash, then you can start with
$ hg identify -i http://hg.repo.com:8000/myrepo
to get the ID of the tip changeset. You can combine this with clone like this in a Unix shell:
$ hg clone http://hg.repo.com:8000/myrepo \
"myrepo-$(hg -i identify http://hg.repo.com:8000/myrepo)"
To make it more convenient to use, I would create an alias for this:
[alias]
vclone = !DEST=$(basename "$1")-$($HG identify -i "$1");
echo "destination directory: $DEST";
$HG clone "$1" "$DEST"
This let's you do hg vclone foo to get a foo-<ID> clone.
In the alias I took care of computing a suitable basename from the clone URL and to print the destination in the same way that hg clone normally does when you don't give an explicit destination. Finally, I took care to quote the arguments so that you can clone a directory with spaces in the name. (If you also have characters like " in your names, well then you're out of luck without better support for quoting in Mercurial shell aliases.)
You'll have to first clone it into some temporary folder, then inspect the repo's tip to see its revision or whatever trait you want to use in your naming scheme and then rename the previous (temporary) location to whatever it should be now ... it's not available in vanilla Hg to my knowledge.

Would like to do a mercurial clone with filter of patterns in hgignore

Over time a number of the developers have committed files that were then added to the .hgignore. From what I hear there is no way to remove items from the history of mercurial, which is ok. But I also heard that there is a way to do a clone, I think using the convert plugin, to clone/export a repo while specifying which files to not include in the conversion.
I can't help but think that someone out there has a script that does this export/filter/convert using the patterns from the .hgignore file.
Has anyone created such a beast?
You could create a filemap from .hgignore doing something like this:
hg clone -U yourrepo temprepo # create a temp repo with no files in working dir
cd tmprepo
hg revert --all # put files in working dir
hg forget ** # un-add the files
hg status --ignored --no-status | sed 's/^/exclude /' > ../filemap
that will get you a filemap you can pass into hg convert that removes all the added files that would be ignored given your .hgignore.
Do understand though, that running convert creates a whole new repo that is unrelated to your previous repo. All existing clones will be unusable with the new one. It's not normally worth it.
hg convert is indeed the thing you want to use.
You will want to create a file map (just a text file) which will list all of the things you either want to include, exclude, or rename:
include subfolder
exclude subfolder/supersub
etc...
Read the following for a more concrete example:
https://www.mercurial-scm.org/wiki/ConvertExtension#A--filemap
Once you have created this file you will just use the following command:
$ hg convert --filemap my_file_map /path/to/source/repo /path/to/dest/repo
The source repo will not be modified and a dest repo will be created. I don't want to just copy verbatim what the documentation already says so here is the link:
How to keep just a subdirectory (or run on the mercurial repo):
https://www.mercurial-scm.org/wiki/ConvertExtension#Converting_from_Mercurial

Putting home directory under source control (hg)

For a while I had just my code under source control, but I decided it would be cool to put things like my stuff in my .vim folder among other things in a repo. (I'm obviously not going to store everything in my repo, just various config files, my src directory, and maybe a few other things as well)
I was able to set up a repo fine, then push it to my server where I can access it from my other computers, but I can't clone it to my other computers. When I try to clone it it fails because the home directory isn't empty. Is there a way to do what I want here?
Since the versioned files between my computers are the same, what I did was:
~$ hg clone ssh://myserver/hg/dotfiles mydotfiles
~$ mv mydotfiles/.hg .
~$ rm -rf mydotfiles
and that's it, now your home folder is under version control, but of course if your dot files are not identical between computers you will have to do something about it.
Since I only want to version some files and not everything under my home folder, I have this simple rule in ~/.hgignore
# This .hgignore is for the dotfiles repository only,
# the rest of my HG repositories use the file
# .hgignore_global as referenced by [ui]'s ignore setting.
syntax:glob
*
This way I don't get an ocean of files when I do hg status and only see those files that I have under version control that have been modified.
But since I want to see unversioned files when working within another hg repository, I have this in my ~/.hgrc file
[ui]
ignore=/home/gajon/.hgignore_global
And ~/.hgignore_global contains some filters for common transient files:
syntax: glob
*.pyc
*~
.*.swp
.svn*
*.svn*
*.fasl
syntax: regexp
^\.pc/
Suppose you have proj1 and proj2. proj1 is a mercurial repo you want to clone to proj2, but proj2 already has files in it.
Try this:
hg clone proj1 proj3
mv proj3/.hg proj2
rmdir proj3
cd proj2
hg update -C -r tip
In the other directories that already exist, you could hg init, hg add what you want, hg commit that, hg pull from the central repo, and deal with the resulting merge.