我有一个Git存储库,其中包含许多子目录。现在我发现其中一个子目录与另一个子目录无关,应该分离到一个单独的存储库中。
如何在保留子目录中文件的历史记录的同时执行此操作?
我想我可以制作一个克隆并删除每个克隆中不需要的部分,但我想这会在检查旧版本等时提供完整的树。这可能是可以接受的,但我更希望能够假装这两个存储库没有共享的历史。
为了清楚起见,我有以下结构:
XYZ/
.git/
XY1/
ABC/
XY2/
但我想改为:
XYZ/
.git/
XY1/
XY2/
ABC/
.git/
ABC/
这里的大多数答案似乎都依赖于某种形式的gitfilter分支——子目录筛选器及其类似的分支。这可能在“大多数情况下”有效,但在某些情况下,例如重命名文件夹时,例如:
ABC/
/move_this_dir # did some work here, then renamed it to
ABC/
/move_this_dir_renamed
如果您使用普通的git过滤器样式来提取“move_this_dir重命名”,则会丢失最初为“move_this_dir”(ref)时发生的文件更改历史记录。
因此,似乎真正保留所有更改历史的唯一方法(如果您的情况是这样的),本质上就是复制存储库(创建一个新的repo,将其设置为原点),然后对所有其他内容进行核处理,并将子目录重命名为父目录,如下所示:
在本地克隆多模块项目分支-检查有什么:gitbranch-a对要包含在拆分中的每个分支进行签出,以在您的工作站上获得本地副本:gitcheckout--trackorigin/branchABC在新目录中创建副本:cp-r oldmultimodsimple进入新项目副本:cd simple删除此项目中不需要的其他模块:git rm other模块1 other2 other3现在只剩下目标模块的子磁盘删除模块子目录,使模块根目录成为新的项目根目录git-mv模块Subdir1/*。删除遗迹子目录:rmdir moduleSubdir1随时检查更改:git状态创建新的git repo并复制其URL以将此项目指向其中:git远程设置url源http://mygithost:8080/git/our-分裂模块回购验证这是否正确:gitremote-v将更改推送到远程存储库:git Push转到远程回购并检查所有内容对所需的任何其他分支重复此操作:git checkout branch2
接下来是github文档“将子文件夹拆分为新存储库”的步骤6-11,以将模块推送到新存储库。
这不会在.git文件夹中节省任何空间,但它会保留这些文件的所有更改历史记录,即使是跨重命名。如果没有“很多”历史记录丢失等,这可能不值得。但至少可以保证您不会丢失以前的提交!
我找到了非常直接的解决方案,这个想法是复制存储库,然后删除不必要的部分。这是它的工作原理:
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