Convert a subdirectory into a subrepository

This is a modification and elaboration of the procedure described in
http://mercurial.aragost.com/kick-start/en/subrepositories/#converting-folder-into-a-subrepository

Goal

You’re using Mercurial to source-control a project. You want to split a given subset off into a separate Mercurial repository. (For example, suppose you’ve decided that the subset should be a separately managed subproject.)

This article assumes that you’re starting with the following directory structure:

project/
        .hg/
        subdir1/
            sub1-files
        subdir2/
            sub2-files
        subdir3/
            sub3-files
        root-files

and that your goal is to split subdir2 off into a separate Mercurial repository, while leaving everything else (subdir1, subdir3, and root-files) within the main repo.

Procedure

Split into two repositories

  • Change directory to project‘s parent (i.e. to project/..)
  • Create a new repository newmain for the top-level project, consisting of everything except subdir2:
    • Create a file rootmap containing:
exclude subdir2
    • Type:
hg --config extensions.hgext.convert= convert --filemap rootmap project newmain
cd newmain; hg update
  • Create a new sub-repository within newmain, consisting of only subdir2:
    • Create a file submap containing:
include subdir2
rename subdir2 .
    • Type:
hg --config extensions.hgext.convert= convert --filemap submap project newsub
cd newsub
hg update

At this point, we have two new subdirectories, newmain and newsub, but they’re
entirely independent of each other. (The original project directory/repo has not been modified.)

The new directories look like:

newmain/
    .hg/
    subdir1/
        sub1-files
    subdir3/
        sub3-files
    root-files

newsub/
    .hg/
    sub2-files

Note that:

  • Each of newmain and newsub contains a .hgdirectory; they’re both Mercurial repositories
  • newmain does not contain a subdir2
  • What was the content of project/subdir2 is now at the root level of newsub

Configuring the subrepository relationship

Nested

Now that we have newmain and newsub, the next step is to glue them together into a
subrepository configuration. The easiest way is to put newsub back into newmain/subdir2:

mv newsub newmain/subdir2
cd newmain
echo subdir2 = subdir2 >.hgsub
hg add .hgsub
hg commit .hgsub

The result looks just like the original project layout, except that newmain/subdir2 is now a subrepository, rather than simply a directory within the newmain repository. Note that newmain/subdir2 is so far the only repository for the new subproject (though the revision history still exists in project).

Separate

If newsub really is an independent project, one probably wants to host its repository independently of project‘s. Suppose the new project should be called module-name:

mv newsub module-name
cd newmain
hg clone ../module-name
echo subdir2 = ../module-name >.hgsub
hg add .hgsub
hg commit .hgsub

The result of this is, again, a newmain that looks like project except that newmain/subdir2 is a subrepository. The difference is that the main repository for the new project is module-name, and newmain/subdir2 is a clone of that.

Cleanup

Presumably one wants to install the new repository in place of the old one:

  • Type:
mv project project.OLD
mv newmain project
  • if necessary, update the path/URL on the right side of the “=” in .hgsuband commit the change
  • check for any commits that might have been made to (what is now) project.OLD while you were making these changes, and so aren’t yet in (the new version of) project

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply