成功将SVN存储库转换为Git之后,我现在拥有一个非常大的Git存储库,我希望将其分解为多个较小的存储库并保留历史记录。
所以,有人可以帮助拆分可能看起来像这样的回购:
MyHugeRepo/
.git/
DIR_A/
DIR_B/
DIR_1/
DIR_2/
进入两个看起来像这样的存储库:
MyABRepo/
.git
DIR_A/
DIR_B/
My12Repo/
.git
DIR_1/
DIR_2/
我已尝试按照上一个问题中的说明进行操作,但在尝试将多个目录放入单独的仓库(Detach (move) subdirectory into separate Git repository)时,它并不适合。
答案 0 :(得分:77)
这将设置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
这将创建并使用/tmp/git-rewrite.tmp作为临时目录,而不是.git-rewrite
。
当然,您可以替换任何路径而不是/tmp/git-rewrite.tmp
,只要您具有写入权限,并且该目录尚不存在。
答案 1 :(得分:10)
您可以git filter-branch --index-filter
使用git 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”存储库中删除它)。
答案 2 :(得分:5)
git_split项目是一个简单的脚本,可以完全满足您的需求。 https://github.com/vangorra/git_split
将git目录转换为自己位置的自己的存储库。没有子树有趣的业务。此脚本将获取您的git存储库中的现有目录,并将该目录转换为其自己的独立存储库。在此过程中,它将复制您提供的目录的整个更改历史记录。
./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.
答案 3 :(得分:4)
这是一个可以执行此操作的ruby脚本。 https://gist.github.com/4341033
答案 4 :(得分:1)
感谢您的回答,但我最后只是复制了两次存储库,然后删除了我不想要的文件。我将在以后使用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目录完成了同样的事情。这给了我两个历史相同的回购,直到我删除了不需要的目录。答案 5 :(得分:0)
虽然在问题出现时 utunbu 的回答是最好的,但现在连 git 本身都推荐 https://github.com/newren/git-filter-repo
它的速度要快几个数量级,而且相对来说非常容易使用
例如在这里你会做
git clone MyHugeRepo/ MyABRepo.tmp/
cd MyABRepo.tmp
git filter-repo --path DIR_A/ --path DIR_B/
查看更多示例