将大型Git repo强烈重组为多个新的回购

Chi*_*aul 6 git git-filter-branch git-subtree

我发现了几个使用filter-branch和subtree的简单例子,但它们总是只移动1个目录.我想采取以下回购:

/
  Project1.sln
  Project2.sln
  Source/
    CommonLib.Data/
    CommonLib.Web/
    Project1.Data/
    Project1.Web/
    Project1.Other/
    Project2.Data/
    Project2.Web/
Run Code Online (Sandbox Code Playgroud)

并将事物移到他们自己的回购中,具有以下结构:

# CommonRepo
/
  CommonLib.Data/
  CommonLib.Web/

# Project1Repo
/
  Project1.sln
  Project1.Data/
  Project1.Web/
  Project1.Other/

# Project2Repo
/
  Project2.sln
  Project2.Data/
  Project2.Web/
Run Code Online (Sandbox Code Playgroud)

同时保持整个历史.更复杂的是,原始仓库的一个或多个分支对应于每个项目,因此所引用的其他项目的CommonLib版本可能略有不同.

我想使用git子树添加在正确的标签/版本的每个新repos中添加一个返回CommonLib的引用,但首先我需要一种方法将一些目录一次性拆分到它们自己的位置.

git子树拆分-P似乎只想要一个目录,而且我也无法获得filter-branch来获取倍数.我在一个Windows框上,所以没有设置所有的脚本细节,以使这更容易.

有什么建议?

joh*_*003 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/
Run Code Online (Sandbox Code Playgroud)

现在来处理拆分:

当你拆分时,只要你不使用不同的注释或什么东西,提交ID就会兼容,并且应该很好地与合并一起使用.因此,您可以从提取CommonLib开始.

  1. 我建议你在开始之前克隆你的整个depo,以确保你不会丢失任何东西.

    git clone <big-repo> <big-repo-clone>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 准备旧的回购

    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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 现在我们需要清理那些我们不想要的项目部分.由于它们混合在一起你不能真正使用子树,但你可以过滤分支来重写历史而不需要其他部分.

    # 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
    
    Run Code Online (Sandbox Code Playgroud)

    prune empty将删除变为空的提交,因为它们仅包含您删除的文件夹中的更改.

    注意:所有这些更改都位于/ source级别,因此它可以是每个项目的新根.您可以稍后再添加您的解决方案.或者您可以将此修剪技术用于克隆而不是子树,当您完成所有操作后,您可以将所有内容从"/ Source"移动到"/"

    现在你将有额外的分支和备份refs/original/refs/heads/<branch-name>.如果在此过程中您遇到了filter-branch的致命错误,您可以重新创建分支并重新启动,或者如果您确信它没有执行任何操作,则可以使用以下命令删除此备份:git update-ref -d refs/original/refs/heads/<branch-name>.

  4. 现在只需创建新的存储库来存储从这些分支创建的项目

    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>
    
    Run Code Online (Sandbox Code Playgroud)
  5. 最后一件事,让我们将CommonRepo拉入项目中.

    pushd <new-project-repo>
    git subtree add --prefix=CommonLib <new-commonlib-repo>
    
    Run Code Online (Sandbox Code Playgroud)

然后你只需要引入.sln文件(我将最后一步留给你).