我有一个Git存储库,其中包含许多子目录。现在我发现其中一个子目录与另一个子目录无关,应该分离到一个单独的存储库中。
如何在保留子目录中文件的历史记录的同时执行此操作?
我想我可以制作一个克隆并删除每个克隆中不需要的部分,但我想这会在检查旧版本等时提供完整的树。这可能是可以接受的,但我更希望能够假装这两个存储库没有共享的历史。
为了清楚起见,我有以下结构:
XYZ/
.git/
XY1/
ABC/
XY2/
但我想改为:
XYZ/
.git/
XY1/
XY2/
ABC/
.git/
ABC/
编辑:添加了Bash脚本。
这里给出的答案对我来说只是部分奏效;缓存中仍有大量大文件。什么最终奏效了(在freenode上的#git中的几个小时后):
git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now
在以前的解决方案中,存储库大小约为100 MB。这一次将其降至1.7 MB。也许这对某人有帮助:)
以下bash脚本自动执行任务:
!/bin/bash
if (( $# < 3 ))
then
echo "Usage: $0 </path/to/repo/> <directory/to/extract/> <newName>"
echo
echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
exit 1
fi
clone=/tmp/${3}Clone
newN=/tmp/${3}
git clone --no-hardlinks file://$1 ${clone}
cd ${clone}
git filter-branch --subdirectory-filter $2 --prune-empty --tag-name-filter cat -- --all
git clone file://${clone} ${newN}
cd ${newN}
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now
我找到了非常直接的解决方案,这个想法是复制存储库,然后删除不必要的部分。这是它的工作原理:
1) 克隆要拆分的存储库
git clone git@git.thehost.io:testrepo/test.git
2) 移动到git文件夹
cd test/
2) 删除不必要的文件夹并提交
rm -r ABC/
git add .
enter code here
git commit -m 'Remove ABC'
3) 使用BFG从历史记录中删除不必要的文件夹
cd ..
java -jar bfg.jar --delete-folders "{ABC}" test
cd test/
git reflog expire --expire=now --all && git gc --prune=now --aggressive
对于多个文件夹,可以使用逗号java-jar bfg.jar--删除文件夹“{ABC1,ABC2}”metric.git
4) 检查历史记录是否不包含您刚刚删除的文件/文件夹
git log --diff-filter=D --summary | grep delete
5) 现在您有了没有ABC的干净存储库,所以把它推到新的原点
remote add origin git@github.com:username/new_repo
git push -u origin master
就是这样。您可以重复这些步骤来获取另一个存储库,
只需在步骤3中删除XY1、XY2并重命名XYZ->ABC