3

I have a git repository which contains multiple subdirectories. I now want to split multiple subdirectories into a new repository. It looks like git subtree makes this easy if you only have one subdirectory that you want to extract out into a new repo but what about extracting multiple subdirectories? I'm not seeing a clean way of doing this.

This is the structure I have now (with the repository in AlphaDirectory):

AlphaDirectory
    AlphaSubDirectory1
    AlphaSubDirectory2
    BetaSubDirectory1
    BetaSubDirectory2

This is what I need (with a separate repository in each of AlphaDirectory and BetaDirectory):

AlphaDirectory
    AlphaSubDirectory1
    AlphaSubDirectory2
BetaDirectory
    BetaSubDirectory1
    BetaSubDirectory2

This is related to Splitting many subdirectories into a new, separate Git repository and its referenced questions but not same as structure in all 3 asking questions differ.

Community
  • 1
  • 1
Marquis Blount
  • 7,585
  • 8
  • 43
  • 67
  • 2
    Do you need the history of the material in the beta subdirectories? Did you consider cloning (forking) the repository, and then removing the unwanted material from each separate repository? There are probably better ways to deal with it, but brute force occasionally has its merits. – Jonathan Leffler Jul 13 '16 at 17:05

2 Answers2

4

This type of splitting must be done with git filter-branch:

git clone AlphaDirectory BetaDirectory

cd AlphaDirectory
git filter-branch --tree-filter "rm -rf BetaSubDirectory*" --prune-empty -- --all

cd ../BetaDirectory
git filter-branch --tree-filter "rm -rf AlphaSubDirectory*" --prune-empty -- --all
Leon
  • 31,443
  • 4
  • 72
  • 97
3

I'm assuming that in the new repository, you only want to preserve history related to the directories that are moved instead of complete history of the original repository. I had the same problem and this is what worked for me.

First, separate history for the two projects into two new branches (or more than two if you wish) in the original repository. You might want to do this on a clone of AlphaDirectory so that you don't pollute your original repository.

cd AlphaDirectory
git subtree split -P BetaSubDirectory1 -b BetaSubDirectory1Branch
git subtree split -P BetaSubDirectory2 -b BetaSubDirectory2Branch
cd ..

Then, create new repository and add old repository as remote (git repositories can have multiple remotes and that's OK!).

cd BetaDirectory
git init
git remote add alpharepo ../AlphaDirectory
git fetch alpharepo

And then for each branch, you basically merge each branch, but it will be merged outside of original subdirectory. You can fix that by creating subdirectory as it was in original repo, and moving all its files back inside, and then commiting it. Of course, while moving stuff, you don't want to move .git and BetaSubDirectory? directories.

git merge alpharepo/BetaSubDirectory1Branch
mkdir BetaSubDirectory1
<move stuff from BetaDirectory into BetaSubDirectory1>
git commit -m "merge BetaSubDirectory1"

git merge alpharepo/BetaSubDirectory2Branch
mkdir BetaSubDirectory2
<move stuff from BetaDirectory into BetaSubDirectory2>
git commit -m "merge BetaSubDirectory2"

And finally, remove the old remote:

git remote remove alpharepo

This also works for more than two subdirectories (I had 15).

Domchi
  • 10,705
  • 6
  • 54
  • 64