我有一个Subversion服务器,在标准布局中有几个不同的项目,如下所示:
ProjectA/
trunk/
branches/
tags/
ProjectB/
trunk/
FolderOfBinaries/
SourceFolderA/
SourceFolderB/
SourceFolderC/
branches/
tags/
v1.0/
v1.1/
v2.0/
ProjectC/
trunk/
branches/
tags/
ProjectB将被迁移到Git,但不会迁移到标准克隆。我想将项目拆分为两个Git存储库 - 一个用于充满大量二进制文件夹的文件夹,这些二进制文件经常更改,另一个用于其他所有存储库。我完全克隆了存储库并且它只有几GB,但是二进制文件夹大概是其中的90%,并且运行git gc
需要很长时间。我宁愿拥有一个小型快速存储库,然后在开发人员需要时将二进制文件夹添加为子模块。
到目前为止,我找到了两个可能的选择。首先,我可以使用git branch-filter
尝试从Git Book中显示的历史记录中删除二进制文件夹。其次,我可以使用svndumpfilter
将当前的Subversion存储库拆分为两个,然后分别为git svn clone
。
我的问题是,所有的历史,特别是分支和标签会发生什么?我仍然想知道项目中每个标记的二进制文件夹是什么样的,即使两个标记之间的二进制文件可能没有变化。那可能吗?
编辑:二进制文件夹中没有构建文件(* .class,* .o,* .dll等),因此我不能将其删除并使其外部。它充满了从需要进行版本化的第三方程序输出的二进制文件(想想OpenOffice文档,Photoshop文件等)。
答案 0 :(得分:1)
我建议svndumpfilter
首先将ProjectB拆分为两个存储库。之后,您可以使用git svn clone
将新的SVN存储库转换为GIT存储库。
当--include
svndumpfilter
模式考虑trunk,branches和tags文件夹时,将保留拆分存储库的完整历史记录。因此,您可以查看新二进制存储库中FolderOfBinaries
的所有历史记录。
使用git svn clone
创建GIT存储库时,branches
文件夹的内容将转换为GIT分支,tags
文件夹的内容将转换为GIT标记。
答案 1 :(得分:1)
看看svndumpfilter。它使用起来非常简单。您执行Subversion存储库转储,然后使用过滤器来说出您想要的内容或您不想要的内容。
转储当前存储库,然后运行svndumpfilter两次 - 每个Git存储库一次。你可以链接它们。只需为每个Git存储库运行两次。
$ svndumpfilter include ProjectB < svn_repo_dump | svndumpfilter exclude ProjectB/trunk/folderofbinaries > svn_repos_no_binaries
我想提一件事:不要在您的存储库中存储构建的二进制对象。在Subversion中,如果没有转储和过滤器,它们就无法移除,即使在能够删除修订版本的版本控制系统中,这样做也需要花费大量的时间和精力。这是一个很大的维护问题。
为了什么?在版本控制系统中存储二进制文件并没有多大帮助。您不能 diff 二进制文件,历史记录没有帮助,非开发人员很难访问它们。
相反,请使用发布存储库,并将二进制文件存储在那里。即使您不使用Maven甚至使用Java,也可以使用Artifactory或Nexus等Maven存储库。
答案 2 :(得分:1)
好吧,我已经设法做到了这一点,但并不是那么简单。可能有更好的方法,但不是我可以解决的问题。我做了以下事情:
创建当前存储库的转储:svnadmin dump /opt/repo > full_dump
过滤转储以删除二进制文件夹:svndumpfilter exclude *folderofbinaries* --pattern --renumber-revs --drop-empty-revs < full_dump > filtered_dump
。我需要使folderofbinaries
成为一种模式,因为过去有人实际上已经将二进制文件直接检入标记(!),因此下一步因缺少文件夹而失败。
使用筛选转储创建本地SVN存储库:
mkdir repo-filtered;
svnadmin create repo-filtered;
svnadmin load repo-filtered < filtered_dump
将完整和已过滤的repo克隆到不同的文件夹中(我使用svn2git)。过滤后的仓库不包含任何二进制文件。如果在完整仓库中,只有二进制文件夹在标签A和B之间发生了变化,那么在新过滤的Git仓库中,两个标签将指向同一个提交,这正是我想要的。
在完整的Git仓库中,使用Git删除除二进制文件夹以外的所有内容。
我必须使用Git来隔离二进制文件夹的原因是因为我无法解决如何使用svndumpfilter
来维护标记(特别是考虑到我将二进制文件直接提交到标记中)。转换后,我得到与过滤后的repo相同的行为 - 如果两个标签之间没有更改二进制文件,那么它们都指向同一个提交。
最后一步的命令是:
git checkout master
git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter folderofbinaries -- --all
git reset --hard
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all
git gc --prune=now
我是从this question获得的。
现在我有一个80MB的源存储库和一个1.5GB的二进制存储库,来自我原来的4.4GB SVN转储文件!我可以通过添加二进制文件夹作为源repo的Git子模块并在每个上检查相同的标签来重新创建原始SVN repo的确切状态(这就是为什么我需要保留所有标签信息)而没有一个猛犸象使用缓慢的Git回购。