1

Say I have a git repository with the structure:

my-repo/
  .git/
  directory-one/
    [...]
  directory-two/
    [...]

I need to split the repo into two repositories (one for directory-one and the other for directory-two). I'd like to maintain the history of each of those subdirectories, but no code from directory-one can appear in the history of directory-two, and vice versa.

Is this possible?

Kerrick
  • 7,420
  • 8
  • 40
  • 45
  • 1
    Possible dupe of http://stackoverflow.com/questions/359424/detach-subdirectory-into-separate-git-repository or http://stackoverflow.com/questions/3910412/split-large-git-repository-into-many-smaller-ones ? – willoller Jul 28 '14 at 19:21

2 Answers2

2

You can use git filter-branch with --subdirectory-filter, which was built exactly for this:

# Clear the two directories entirely
rm -rf directory-one/ directory-two/
mkdir directory-one/ directory-two/

# Add the original .git to each one
cp -R .git directory-one/
mv .git directory-two/

# Check out the repo into the empty directory and filter it to that directory
cd directory-one/
git checkout -f
git filter-branch --subdirectory-filter directory-one/

# Repeat
cd ../directory-two/
git checkout -f
git filter-branch --subdirectory-filter directory-two/

Make a backup first.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • The problem with that method is that there is still code from `directory-one/` in the diffs of the repo that was created at `directory-two/`. For data security reasons, no code that was ever in `directory-one/` is allowed to be visible in `directory-two/`'s history. – Kerrick Jul 31 '14 at 15:46
  • @Kerrick: There shouldn’t be… how do they appear? – Ry- Jul 31 '14 at 16:29
  • In commits that touched both directories, I can see diffs that include code from the other directory. – Kerrick Jul 31 '14 at 16:33
  • @Kerrick: What filename does the other directory appear as? You could try using that with `--index-filter`… – Ry- Jul 31 '14 at 16:39
  • I figured it out! Your answer is step 2. Step 1 is `git filter-branch --tree-filter "rm -rf directory-one" HEAD`. This leaves you with a repo that only has `directory-two/`'s history, and all the files that were directly inside `directory-one/` are now at the repo root. – Kerrick Jul 31 '14 at 21:33
0

Note: You lose any non-merged, non-master branches with this process.

  1. cp -R my-repo/ my-repo-one/
  2. cd my-repo-one/
  3. git filter-branch --tree-filter "rm -rf directory-two" HEAD
  4. mv .git directory-one/
  5. git checkout -f
  6. git filter-branch --subdirectory-filter directory-one

This gets you a repo with only the history from directory-one/. Repeat the process for directory-two/.

Thanks to minitech for steps 4-6!

Kerrick
  • 7,420
  • 8
  • 40
  • 45