Git子树拆分了两个目录

时间:2014-08-29 18:45:10

标签: git git-subtree

我一直关注this excellent answer将git存储库的子目录解压缩到自己的存储库中,同时保留完整的历史记录。

我的存储库看起来像:

src/
    http/
    math/
tests/
    http/
    math/

我想创建一个仅包含src/mathtests/math目录的新分支。

如果我运行以下命令:

git subtree split -P src/math -b math

它创建一个包含src/math目录内容的分支,但丢弃src/math/前缀。

如果我使用两个目录尝试相同的命令:

git subtree split -P src/math -P tests/math -b math

它只会提取tests/math的内容,忽略src/math,同时也会丢弃tests/math前缀。

总结一下,我希望我的最终存储库看起来像:

src/
    math/
tests/
    math/

即保留原始目录结构,但丢弃命令行中未明确提及的所有内容。

我该怎么做?

3 个答案:

答案 0 :(得分:4)

根据您的需要,您可能会使用git filter-branch

我不完全确定你想要实现的目标,但是如果你只想拥有一个删除了两个目录的存储库(在历史记录中?),这可能是你最好的选择。

另见Rewriting Git History

$ git filter-branch --tree-filter 'rm -rf tests/http src/http' --prune-empty HEAD

这将调查每次提交并从此提交中删除两个目录。 请注意,这会重写历史记录(即:改变您的提交标准),如果您与另一个存储库有共同的历史记录,则会导致头痛。

答案 1 :(得分:1)

使用git-subtree add 拆分

# First create two *split-out* branches
cd /repos/repo-to-split
git subtree split --prefix=src/math --branch=math-src
git subtree split --prefix=test/math --branch=math-test

# Now create the new repo
mkdir /repos/math
cd /repos/math
git init

# This approach has a gotcha:
# You must commit something so "revision history begins",
# or `git subtree add` will complain about.
# In this example, an empty `.gitignore` is commited.
touch .gitignore
git add .gitignore
git commit -m "add empty .gitignore to allow using git-subtree"

# Finally, *split-in* the two branches
git subtree add --prefix=src/math ../repo-to-split math-src
git subtree add --prefix=test/math ../repo-to-split math-test

它适用于 git --version 2.23.0 。另外请注意,您可以在插入时间设置不同的前缀,即将src/math/添加到src/并将test/math/添加到test/

旁注:在提交给远程用户之前,请在新存储库中使用git log,以查看生成的历史记录对您是否足够。就我而言,我有一些提交带有重复消息的提交,因为我的回购记录太脏了,但是对我来说没关系。

Source

答案 2 :(得分:1)

使用git-filter-repo 从2.25版开始,这不是git的一部分。 这需要Python3(> = 3.5)和git 2.22.0

git filter-repo --path src/math --path tests/math 

对于我的包含约12000次提交的repo, git-filter-branch 花了超过24小时,而 git-filter-repo 花了不到一分钟。