如何在保留子目录的同时拆分git存储库?

Tho*_*mas 20 git split git-filter-branch

我想要的是这个问题.但是,我希望拆分为单独仓库的目录仍然是该仓库中的子目录:

我有这个:

foo/
  .git/
  bar/
  baz/
  qux/
Run Code Online (Sandbox Code Playgroud)

我想将它拆分为两个完全独立的存储库:

foo/
  .git/
  bar/
  baz/

quux/
  .git/
  qux/  # Note: still a subdirectory
Run Code Online (Sandbox Code Playgroud)

如何在git中执行此操作?

如果有一些方法可以将所有新repo的内容移动到历史记录中的子目录中,我可以使用此答案中的方法.

Cas*_*bel 19

您确实可以使用子目录过滤器,后跟索引过滤器将内容放回到子目录中,但是为什么只能单独使用索引过滤器呢?

以下是手册页中的示例:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
Run Code Online (Sandbox Code Playgroud)

这只删除一个文件名; 你想要做的是删除除给定子目录之外的所有内容.如果你想谨慎,你可以明确列出要删除的每个路径,但如果你想全押,你可以这样做:

git filter-branch --index-filter 'git ls-tree -z --name-only --full-tree $GIT_COMMIT | grep -zv "^directory-to-keep$" | xargs -0 git rm --cached -r' -- --all
Run Code Online (Sandbox Code Playgroud)

我希望可能有更优雅的方式; 如果有人有东西请建议吧!

关于该命令的一些注意事项:

  • filter-branch在内部将GIT_COMMIT设置为当前提交SHA1
  • 我不希望--full-tree有必要,但显然filter-branch从.git-rewrite/t目录而不是repo的顶级运行索引过滤器.
  • grep可能有点矫枉过正,但我​​认为这不是速度问题.
  • --all适用于所有裁判; 我想你真的很想要那个.(--将其与filter-branch选项分开)
  • -z-0告诉ls-tree,grep和xargs使用NUL终止来处理文件名中的空格.

编辑,很久以后:托马斯有帮助地提出了一种删除现在空提交的方法,但它现在已经过时了.如果您有旧版本的git,请查看编辑历史记录,但使用现代git,您需要做的就是使用此选项:

--prune-empty
Run Code Online (Sandbox Code Playgroud)

这将删除应用索引过滤器后所有空的提交.