将大的Git仓库拆分成许多较小的仓库

在成功地将一个SVN仓库转换为Git后,我现在有一个非常大的Git仓库,我想分解成多个较小的仓库并保存历史logging。

那么,有人可以帮助分解可能看起来像这样的回购:

MyHugeRepo/ .git/ DIR_A/ DIR_B/ DIR_1/ DIR_2/ 

进入如下所示的两个存储库:

 MyABRepo/ .git DIR_A/ DIR_B/ My12Repo/ .git DIR_1/ DIR_2/ 

我已经尝试了以前的问题中的指示,但是在尝试将多个目录放入单独的回购( 分离(移动)子目录到单独的Git存储库中 )时并不适合。

这将设置MyABRepo; 当然你也可以做My12Repo。

 git clone MyHugeRepo/ MyABRepo.tmp/ cd MyABRepo.tmp git filter-branch --prune-empty --index-filter 'git rm --cached --ignore-unmatch DIR_1/* DIR_2/*' HEAD 

.git / refs / original / refs / heads / master的引用仍然存在。 你可以删除它:

 cd .. git clone MyABRepo.tmp MyABRepo 

如果一切顺利,您可以删除MyABRepo.tmp。


如果由于某种原因,你得到一个关于.git-rewrite的错误,你可以试试这个:

 git clone MyHugeRepo/ MyABRepo.tmp/ cd MyABRepo.tmp git filter-branch -d /tmp/git-rewrite.tmp --prune-empty --index-filter 'git rm --cached --ignore-unmatch DIR_1/* DIR_2/*' HEAD cd .. git clone MyABRepo.tmp MyABRepo 

这将创build并使用/tmp/git-rewrite.tmp作为临时目录,而不是.git-rewrite 。 当然,只要你有写权限,而且目录不存在,你可以用你想要的path代替/tmp/git-rewrite.tmp

您可以使用git filter-branch --index-filtergit rm --cached来删除原始存储库的克隆/副本中不需要的目录。

例如:

 trim_repo() { : trim_repo src dst dir-to-trim-out... : uses printf %q: needs bash, zsh, or maybe ksh git clone "$1" "$2" && ( cd "$2" && shift 2 && : mirror original branches && git checkout HEAD~0 2>/dev/null && d=$(printf ' %q' "$@") && git for-each-ref --shell --format=' o=%(refname:short) b=${o#origin/} && if test -n "$b" && test "$b" != HEAD; then git branch --force --no-track "$b" "$o" fi ' refs/remotes/origin/ | sh -e && git checkout - && git remote rm origin && : do the filtering && git filter-branch \ --index-filter 'git rm --ignore-unmatch --cached -r -- '"$d" \ --tag-name-filter cat \ --prune-empty \ -- --all ) } trim_repo MyHugeRepo MyABRepo DIR_1 DIR_2 trim_repo MyHugeRepo My12Repo DIR_A DIR_B 

您将需要手动删除每个存储库的不需要的分支或标签(例如,如果您有一个feature-x-for-AB分支,那么您可能想从“12”存储库中删除)。

这是一个ruby脚本,将做到这一点。 https://gist.github.com/4341033

git_split项目是一个简单的脚本,完全符合你的要求。 https://github.com/vangorra/git_split

把git目录转到他们自己的仓库中。 没有子树有趣的业务。 这个脚本将会在你的git仓库中获得一个现有的目录,并把这个目录转换成一个独立的仓库。 一路上,它将复制您提供的目录的整个更改历史logging。

 ./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo> src_repo - The source repo to pull from. src_branch - The branch of the source repo to pull from. (usually master) relative_dir_path - Relative path of the directory in the source repo to split. dest_repo - The repo to push to. 

感谢您的答案,但我最终只是复制存储库两次,然后删除我不想从每个文件。 我将在稍后的date使用filter-branch来删除已删除文件的所有提交,因为它们已经在其他地方受版本控制。

 cp -R MyHugeRepo MyABRepo cp -R MyHugeRepo My12Repo cd MyABRepo/ rm -Rf DIR_1/ DIR_2/ git add -A git commit -a 

这为我所需要的。

编辑:当然,相同的事情在My12Repo对A和B目录。 这给了我两个具有相同历史的回购,直到我删除不需要的目录。