Split a repository in two

A code repository typically has multiple directories. For example, you could have separated your project's features into appropriately named directories within your repo. Occasionally, you might need to reorganize (or refactor) your repo's code. For example, you might want to move a directory from an existing project's repository into a new repository of its own.

When refactoring, it is good practice to retain in the new project all the source history from the old project. The procedures on this page explain how to move a directory from one repository into another and retain the history.

Using Git to split-out a directory

Before you begin to split-out a directory, you should decide on a name for your new project. In this example,  you'll be refactoring with the following:

splitpractice An existing Bitbucket repository created just to practice with.
bigdir The directory in splitpractice you split out.
freshrepo A new repository for holding the contents of bigdir. You'll create this using the directions below.

To run this example, log into Bitbucket Cloud and do the following:

  1. Create new Git repository called freshrepo.
    This repository is under your account. 
  2. On your local system, open a command-line window.
  3. Clone the splitpractice repository to your local system into the clone freshrepo.

    git clone git@bitbucket.org:tutorials/splitpractice.git freshrepo

    Cloning with this command creates a freshrepo directory on your local system that contains the splitpractice repository.

  4. Change directory into the root of the freshrepo.
  5. List the contents of directory.
    You should see the following:

    bigdir	lildir	lildir2

    At this point, freshrepo is a git repository that is linked back to the splitpractice repository on Bitbucket.

  6. Remove the link back to the Bitbucket remote splitpractice repository.

    git remote rm origin

    You can verify the command worked by listing the contents of the freshrepo/.git/config file.

  7. Remove anything from the repository that is not in the bigdir directory.

    git filter-branch --index-filter 'git rm --cached -r lildir lildir2' -- --all

     This command goes through the history and files and removes anything that is not in bigdir.

  8. Link the local freshrepo repository to the freshrepo remote repository on Bitbucket.

    git remote add origin https://tutorials@bitbucket.org/tutorials/freshrepo.git

    You can get the URL to add from the repo's Clone option on Bitbucket. This examples uses HTTPS but you could also use SSH.

  9. Push to the newly refactored repo back to Bitbucket.

    git push origin master

Now, view your freshrepo repository on Bitbucket. You'll find source files and their history show only the bigdir directory activity. The history for the "lil" directories. How do you know? Compare the original commit of splitpractice against your freshrepo repository. Notice, however, the history for source file 1 was retained by the move.

The new freshrepo/bigdir is totally separate from the original splitpractice/bigdir directory. If you were splitting a repository in a production environment, you would probably remove the splitptractice/bigdir folder from splitpractice.

Using Mercurial to Split-out a Directory

Before you begin to split-out a directory, you should decide on a name for your new project. In this example, you'll use freshrepo for the new repository name. You'll be refactoring the hgsplitpractice repository an existing public repository on Bitbucket.  

Enable the convert extension

The Mercurial convert extension is a relatively easy way to convert a directory. Before you can do use it, you need to enable the extension. Enable the extension by doing the following:

  1. Open a terminal on your local system.
  2. Edit the ~/.hgrc configuration file.
  3. Add the following to the configuration:

    [extensions]
    hgext.convert=
  4. Save and close the file.

Create the new repository on Bitbucket and clone the old locally

 You'll need to create the new repository on Bitbucket and clone the old locally by doing the following:

  1. Open Bitbucket in your browser and log into your account.
  2. Create a new Mercurial repository called hgfreshrepo.
    This is the remote repo where your new repository will end up. 
  3. Open a terminal on your local system.
  4. Clone the hgsplitpractice repository to your local system.

    hg clone https://bitbucket.org/tutorials/hgsplitpractice

Split the original repository locally 

The conversion extension takes a --filemap mapfile option.  The mapfile  can contain any of the following directives:

# comment line
include /path/to/file
exclude /path/to/file
rename from/file to/file

Splitting the hgsplitpractice requires calling the convert extension and passing it a mapfile

  1. Navigate to the parent directory of the repository.
  2. Create a file called mymapfile.
  3. Add the following directives:

    include bigdir

    All the file names are relative to the repository root.

  4. Save and close the file.
  5. Convert the repository.

    hg convert -s hg -d hg --filemap mymapfile hgsplitpractice hgfreshrepo

Push the new repository back to Bitbucket

  1. Change directory to the new hgfreshrepo.
  2. Update the repository:

    hg update
  3. List the repo contents to verify the conversion:

    $ ls bigdir
    1 2 3 4 5 6 7 8 9
  4. Create a .hg/hgrc file in the repository.
  5. Add the URL for your remote hgfreshrepo to the configuration:

    [paths]
    default = https://tutorials@bitbucket.org/tutorials/hgfreshrepo

    The URL depends on which protocol you are using to connect. In this case, the protocol is HTTPS instead of SSH.

  6. Save and close the file.
  7. Commit the new repository.
  8. Push the changes up to Bitbucket.

Now, view your hgfreshrepo repository on Bitbucket.  You'll find source files and their history show the full history.  How do you know? Compare the original commit of hgsplitpractice against your hgfreshrepo repository.  Notice, however, the history for source file 1 was retained by the move.

The new hgfreshrepo/bigdir is totally separate from the original hgsplitpractice/bigdir directory. If you were splitting a repository in a production environment, you would probably remove the hgsplitpractice/bigdir folder from hgsplitpractice.

Was this helpful?

Thanks for your feedback!

Why was this unhelpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport