Detach many subdirectories into a new, separate Git repository
An easy solution: git-filter-repo
I had a similar issue and, after reviewing the various approaches listed here, I discovered git-filter-repo. It is recommended as an alternative to git-filter-branch in the official git documentation here.
To create a new repository from a subset of directories in an existing repository, you can use the command:
git filter-repo --path <file_to_keep>
Filter multiple files/folders by chaining them:
git filter-repo --path keepthisfile --path keepthisfolder/
So, to answer the original question, with git-filter-repo you would just need the following command:
git filter-repo --path apps/AAA/ --path libs/XXX/
Instead of having to deal with a subshell and using ext glob (as kynan suggested), try this much simpler approach:
git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- apps/AAA libs/XXX' --prune-empty -- --all
As mentioned by void.pointer's comment, this will remove everything except apps/AAA
and libs/XXX
from current repository.
Prune empty merge commits
This leaves behind lots of empty merges. These can be removed by another pass as described by raphinesse in his answer:
git filter-branch --prune-empty --parent-filter \
'sed "s/-p //g" | xargs -r git show-branch --independent | sed "s/\</-p /g"'
⚠️ Warning: The above must use GNU version of sed
and xargs
otherwise it would remove all commits as xargs
fails. brew install gnu-sed findutils
and then use gsed
and gxargs
:
git filter-branch --prune-empty --parent-filter \
'gsed "s/-p //g" | gxargs git show-branch --independent | gsed "s/\</-p /g"'