git filter-tree和修改子模块

时间:2017-10-20 20:37:54

标签: git git-submodules git-filter-branch

我将git存储库的内容移动到另一个存储库中,对于所有常规提交,一切都很好。不过,我遇到了子模块的问题。

设置,我们从两个回购开始。我们会打电话给他们" docs"和"操作",我们想要移动" docs"的内容。进入" operations"的子目录,如下所示:

docs/
  file1.txt
  dir1/
    file2.txt
  other-docs/  <- This is a git submodule

operations/
  bin/
    do-things
  docs/
    important.txt

我们希望最终版本看起来像这样,&#34; docs&#34; repo最终归于&#34; docs / legacy&#34;在操作仓库:

operations/
  bin/
    do-things
  docs/
    important.txt
    legacy/
      file1.txt
      dir1/
        file2.txt
      other-docs/  <- This is a git submodule

我有一个脚本,它使用git filter-branch --tree-filtergit rebase的组合(将新内容重新绑定到现有内容并处理.gitignore文件之类的冲突)来执行实际迁移,但是,在运行迁移后,我最终得到:

operations/
  bin/
    do-things
  docs/
    important.txt
    legacy/
      file1.txt
      dir1/
        file2.txt
  other-docs/  <- This is a git submodule

other-docs子模块仍位于新仓库的根目录。

我明白为什么会这样。当我通过提交移动东西时,没有子模块的实际文件,因此,在&#34;这个目录中的所有内容都完全按照你保留的方式提交&#34; git filter-branch --tree-filter的模型,没有到&#34;离开&#34;对于子模块。

所以,第一个问题:使用git filter-branch的某些方面我可以解释这个问题吗?我想知道的一个地方是,我是否可以添加--commit-filter并弄乱那里的东西,但我还不完全清楚提交过滤器周围的不变量是什么。

如果没有,那么我还能在其他地方做到这一点。据我所知,我将不得不修改子模块的现有提交,基本上&#34;删除&#34;旧的,不正确的位置的子模块和&#34;添加&#34;子模块在新的正确位置。我想我可以通过交互式rebase操作编写脚本,找到这些提交并修改它们。如果有更好的方法,这听起来像是很多工作。

任何想法都赞赏。

2 个答案:

答案 0 :(得分:3)

树过滤器很容易,但它们很慢,而且你发现它们是不经意的。最好只检查您需要更改的内容,然后使用git read-tree

git filter-branch --index-filter='

        # load up the docs-repo commit we're importing under docs/legacy/
        git read-tree --prefix=docs/legacy/ $(imported-commit-for $GIT_COMMIT):

        # hoist any imported submodule configs
        git checkout .gitmodules
        git checkout docs/legacy/.gitmodules 2>&- &&
        sed -n "s,path ,path docs/legacy/,
             s,^,git config -f .gitmodules ,e"  &&
        git rm docs/legacy/.gitmodules &&
        git add .gitmodules

        # any other needed content updates here
'

答案 1 :(得分:1)

  

我明白为什么会这样。当我通过提交来移动东西时,子模块没有实际的文件,因此,在“这个目录中的所有内容都完全按照你保留的方式提交”模型git filter-branch --tree-filter中,有没有来“离开”子模块。

这正是问题所在。这看起来有点讨厌。

  

所以,第一个问题:使用git filter-branch的某些方面我可以解释这个问题吗?我想知道的一个地方是,我是否可以添加--commit-filter并弄乱那里的东西,但我并不完全清楚提交过滤器周围的不变量是什么。

你可以。它不是很漂亮。

更好的地方是--index-filter。正如the documentation所述,过滤器按列出的顺序运行,因此索引过滤器在树过滤器之后运行。它可以对树过滤器周围代码编写的索引进行任何操作。 (树过滤器使用git update-index --add-remove更新索引条目,根据您的过滤器留下的树,根据需要自动add个文件。)

您也可以直接在索引过滤器中执行所有操作,速度要快得多,因为这不需要对实际文件系统操作(mkdir,创建文件等)进行捣乱。索引过滤器一般很难编写,但是git update-index命令可以构造一个全新的索引,或者只是更新现有索引的一部分,但是你必须首先读出一个或一些变化。旧索引(可能使用git ls-files --stage)并操纵生成的文本。

但是这个让你做你想做的事。