在 Git 中导出带有历史记录的子树

Posted

技术标签:

【中文标题】在 Git 中导出带有历史记录的子树【英文标题】:Export subtree in Git with history 【发布时间】:2010-12-12 09:00:48 【问题描述】:

我的 Git 存储库中有一个文件夹,我想将它移到它自己的存储库中。是否可以将该文件夹的历史记录与文件夹一起移动?

我以前只在子文件夹上执行git rm -r --cached subfolder/git init。但是,历史不会导入到新的存储库中。

【问题讨论】:

类似于或重复:***.com/questions/811251/… How can I move a single directory from a git repository to a new repository whilst maintaining the history?的可能重复 【参考方案1】:

对于 2021 年(或之后)到达这里的任何其他人,核心 git 团队不强烈推荐 git filter-branch。

警告 git filter-branch 有很多陷阱,可能会对预期的历史重写产生不明显的破坏(并且由于它的性能如此糟糕,因此您几乎没有时间调查此类问题)。这些安全和性能问题不能向后兼容修复,因此不建议使用它。请使用替代的历史过滤工具,例如 git filter-repo。如果您仍然需要使用 git filter-branch,请仔细阅读安全(和性能)以了解 filter-branch 的地雷,然后尽可能合理地避免其中列出的许多危害。

推荐的工具是git-filter-repo,它可以轻松解决这个问题

git filter-repo --path subfolder/   # Filter the repo to just the sub-dir
git mv subfolder/* .                # Move the contents of the sub-dir to the root
git commit -m "Filtered from main repo"

【讨论】:

您甚至可以将其合并为一个步骤:git filter-repo --path subfolder/ --path-rename 'subfolder/':''【参考方案2】:

引用git-filter-branch(1)的例子

重写存储库,使其看起来好像 foodir/ 一直是它的项目根,并丢弃所有其他历史记录:

git filter-branch --subdirectory-filter foodir -- --all

因此,例如,您可以将库子目录转换为自己的存储库。注意 -- 将过滤器分支选项与修订选项分开, --all 用于重写所有分支和标签。

【讨论】:

只需确保在原始存储库的克隆上运行它,因为它会擦除存储库的其余部分。 太棒了!如果没有工作示例,我无法理解该选项。谢谢! 另外,感谢@bobDevil 的提醒。我将所有更改推送到我的遥控器 /before/ 尝试这个,所以如果它擦除了我的仓库,我会很安全;但这肯定是出乎意料的。 当您只保留一个目录的历史记录时,您会期望生成的克隆更小,但需要做更多的工作。在执行 filter-branch 之后缩小它的最简单方法是再次克隆。有关详细信息,请参阅 git-filter-branch(1) 手册页(“缩小存储库的检查表”)。 @AdamMonsen:你可以做git gc 而不是克隆回购。

以上是关于在 Git 中导出带有历史记录的子树的主要内容,如果未能解决你的问题,请参考以下文章

合并两个 Git 存储库而不破坏文件历史记录

sh 带有颜色的完整git存储库历史记录

如何导出 Windows 计划任务历史记录

SVN 到带有提交历史的 GIT 迁移(使用 git svn)

如何在 Git 中查看文件历史记录?

Git日志(--follow)无法显示重命名之外的历史记录