如何在保留子目录的同时拆分 git 存储库? [英] How to split a git repository while preserving subdirectories?

查看:23
本文介绍了如何在保留子目录的同时拆分 git 存储库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要的是类似于这个问题.但是,我希望拆分为单独存储库的目录保留为该存储库中的子目录:

What I want is similar to this question. However, I want the directory that is split into a separate repo to remain a subdirectory in that repo:

我有这个:

foo/
  .git/
  bar/
  baz/
  qux/

我想把它分成两个完全独立的存储库:

And I want to split it into two completely independent repositories:

foo/
  .git/
  bar/
  baz/

quux/
  .git/
  qux/  # Note: still a subdirectory

如何在 git 中执行此操作?

How to do this in git?

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

I could use the method from this answer if there is some way to move all the new repo's contents into a subdirectory, throughout history.

推荐答案

您确实可以使用子目录过滤器后跟索引过滤器将内容放回子目录中,但是为什么要麻烦,当您可以只使用索引过滤器时自己?

You could indeed use the subdirectory filter followed by an index filter to put the contents back into a subdirectory, but why bother, when you could just use the index filter by itself?

以下是手册页中的示例:

Here's an example from the man page:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

这只是删除一个文件名;您想要做的是删除除给定子目录之外的所有内容.如果您想保持谨慎,可以明确列出要删除的每个路径,但如果您只想全力以赴,则可以执行以下操作:

This just removes one filename; what you want to do is remove everything but a given subdirectory. If you want to be cautious, you could explicitly list each path to remove, but if you want to just go all-in, you can just do something like this:

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

我希望可能有更优雅的方式;如果有人有什么,请提出建议!

I expect there's probably a more elegant way; if anyone has something please suggest it!

关于该命令的一些说明:

A few notes on that command:

  • filter-branch 在内部将 GIT_COMMIT 设置为当前提交的 SHA1
  • 我不希望 --full-tree 是必要的,但显然 filter-branch 从 .git-rewrite/t 运行索引过滤器目录而不是存储库的顶层.
  • grep 可能有点矫枉过正,但我​​认为这不是速度问题.
  • --all 将此应用于所有引用;我想你真的想要那个.(-- 将它与过滤器分支选项分开)
  • -z-0 告诉 ls-tree、grep 和 xargs 使用 NUL 终止来处理文件名中的空格.
  • filter-branch internally sets GIT_COMMIT to the current commit SHA1
  • I wouldn't have expected --full-tree to be necessary, but apparently filter-branch runs the index-filter from the .git-rewrite/t directory instead of the top level of the repo.
  • grep is probably overkill, but I don't think it's a speed issue.
  • --all applies this to all refs; I figure you really do want that. (the -- separates it from the filter-branch options)
  • -z and -0 tell ls-tree, grep, and xargs to use NUL termination to handle spaces in filenames.

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

Edit, much later: Thomas helpfully suggested a way to remove the now-empty commits, but it's now out of date. Look at the edit history if you've got an old version of git, but with modern git, all you need to do is tack on this option:

--prune-empty

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

That'll remove all commits which are empty after the application of the index filter.

这篇关于如何在保留子目录的同时拆分 git 存储库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆