我发现了几个使用filter-branch和subtree的简单例子,但它们总是只移动1个目录。我想采取以下回购:
/
Project1.sln
Project2.sln
Source/
CommonLib.Data/
CommonLib.Web/
Project1.Data/
Project1.Web/
Project1.Other/
Project2.Data/
Project2.Web/
将事情移到他们自己的回购中,具有以下结构:
# CommonRepo
/
CommonLib.Data/
CommonLib.Web/
# Project1Repo
/
Project1.sln
Project1.Data/
Project1.Web/
Project1.Other/
# Project2Repo
/
Project2.sln
Project2.Data/
Project2.Web/
保持整个历史。更复杂的是,原始仓库中有一个或多个分支对应于每个项目,因此所引用的其他项目的CommonLib版本可能略有不同。
我想使用git子树添加在正确的标签/版本的每个新repos中添加一个引用回CommonLib,但首先我需要一种方法将一些目录一次性拆分到自己的位置
git subtree split -P似乎只想要一个目录,而且我也无法获得filter-branch来获取倍数。我在一个Windows框中,所以没有设置所有脚本细节,以使这更容易。
有什么建议吗?
答案 0 :(得分:5)
最后,我建议您保留项目中包含的公共库,特别是由于您所说的不同,所以理想的结构应该是:
# CommonRepo
/
CommonLib.Data/
CommonLib.Web/
# Project1Repo
/
Project1.sln
Project1.Data/
Project1.Web/
Project1.Other/
CommonLib/ # I recommend that you do whatever restructuring needed to support this in a sub-directory
CommonLib.Data/
CommonLib.Web/
# Project2Repo
/
Project2.sln
Project2.Data/
Project2.Web/
CommonLib/ # I recommend that you do whatever restructuring needed to support this in a sub-directory
CommonLib.Data/
CommonLib.Web/
当你拆分时,只要你不使用不同的注释或什么东西,提交ID就会兼容,并且应该很好地与合并一起使用。因此,您可以先自己解压缩CommonLib。
我建议您在开始前克隆整个depo,以确保不会丢失任何东西。
git clone <big-repo> <big-repo-clone>
准备旧的仓库
pushd <big-repo-clone>
# split for the common lib
git checkout master # assuming you want your common lib at master
git subtree split --prefix=Source --branch=temp-commonLib
# split the projects from their respective branches
git checkout <branch-for-project1>
git subtree split --prefix=Source --branch=temp-project1
# split the projects from their respective branches
git checkout <branch-for-project2>
git subtree split --prefix=Source --branch=temp-project2
现在我们需要清理那些我们不想要的项目部分。由于它们混合在一起你不能真正使用子树,但你可以过滤分支来重写历史而不需要其他部分。
# strip unrelated parts from the CommonLib
git checkout temp-commonLib
git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch Project1* Project2*' HEAD
# strip unrelated parts from the Project1
git checkout temp-project1
git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch CommonLib* Project2*' HEAD
# strip unrelated parts from the Project2
git checkout temp-project2
git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch CommonLib* Project1*' HEAD
prune empty将删除变为空的提交,因为它们只包含您删除的文件夹中的更改。
注意:所有这些更改都位于/ source级别,因此它可以是每个项目的新根。您可以稍后再添加您的解决方案。或者您可以将此修剪技术用于克隆而不是子树,当您完成所有操作后,您可以将所有内容从“/来源”移动到“/”
现在,您将在refs/original/refs/heads/<branch-name>
中拥有额外的分支和备份。如果在此过程中您遇到了filter-branch的致命错误,您可以重新创建分支并重新开始,或者如果您确信它没有执行任何操作,则可以使用以下命令删除此备份:git update-ref -d refs/original/refs/heads/<branch-name>
现在只需创建新的存储库来存储从这些分支创建的项目
popd # to get out of <big-repo-clone>
mkdir <new-repo>
pushd <new-repo>
git init
git pull <big-repo-clone> <name-of-branch> # like temp-project1
popd # to get out of the <new-repo>
最后,让我们将CommonRepo拉入项目中。
pushd <new-project-repo>
git subtree add --prefix=CommonLib <new-commonlib-repo>
然后你需要引入.sln文件(我会把这最后一步留给你)。
答案 1 :(得分:1)
我的程序git_filter可以为你做分组。我写它是因为我们的大型存储库上所有其他解决方案都很慢。它在这里:
https://github.com/slobobaby/git_filter
它为原始存储库的每个提取创建多个分支。目前我在这里有一个测试分支:
https://github.com/slobobaby/git_filter/tree/subdir
将创建一个新分支,其中包含原始存储库的子目录,并重命名为新的根目录。
与基于git-core的解决方案的小时或天相比,运行需要几分钟。
包含一个脚本,然后将这些新分支推送到新的干净存储库。
答案 2 :(得分:1)
对我而言,我不是试图弄清楚如何拆分回购的许多部分,而是更喜欢克隆原件,然后通过切掉我不想要的东西来削减它。然后在原版(或另一个克隆版)中,我将我分开的部分削减掉了。我发现它是一种更容易,更迭代的方法,可以更好地了解正在发生的事情。
请在此处查看我最近对此主题的回答:https://stackoverflow.com/a/22210682/955926