51

我试图弄清楚 Git 中的“移植物”是什么。

例如,在这里的最新评论之一中,Tobu 假设使用git-filter-branch.git/info/grafts来加入两个存储库。

但我不明白为什么我需要这些移植物?看来,所有工作都没有最后两个命令。

4

3 回答 3

38

来自Git 维基

移植点或移植物使两条不同的发展线能够连接在一起。它的工作原理是让用户记录提交的虚假祖先信息。这样,您可以让 git 假装提交所具有的父集与创建提交时记录的不同。

使用移植物的原因

在将开发转移到 git 时,Grafts 很有用,因为它允许您克隆从另一个 SCM 导入的旧历史记录,这是可选的。这为只想遵循最新版本的用户保留了初始克隆,而开发人员可以获得完整的开发历史记录。

当 Linus 开始使用 git 来维护他的内核树时,并没有任何工具可以转换旧的内核历史。后来,当旧的内核历史从 bkcvs 网关导入到 git 时,grafts 被创建为一种可以将两个不同的存储库绑定在一起的方法。

于 2008-10-02T12:11:07.160 回答
12

Chris Johnsen提到的加入两个存储库的移植方法不再完全有效(仅使用移植)。 在 Git 2.18(2018 年第二季度)中,“ ”的功能已被“ ”机制所取代(一段时间以来)。内部代码在很多地方都支持它,为了放弃对“嫁接”机制的支持, 已经对其进行了清理 。
$GIT_DIR/info/graftsrefs/replace/

请参阅提交 a3694d9提交 f42fa47提交 8d0d81a提交 e2d65c1提交 f9f99b3提交 0115e03提交 fb40429提交 041c98e提交 e24e871(2018 年 4 月 28 日)和提交 d398f2e 提交Jodb25461e 2018年aa ( dscho)
(由Junio C Hamano 合并 -- gitster--提交 352cf6c中,2018 年 5 月 23 日)

所以而不是

echo "$commit-id $graft-id" >> .git/info/grafts

你现在做:

git replace --graft $commit-id $graft-id
git filter-branch $graft-id..HEAD

弃用支持.git/info/grafts

移植功能是将古代历史“缝合”到新的开始的便捷方式linux.git

然而,它的实现并没有达到 Git 的标准,因为有太多的方式会导致令人惊讶和不受欢迎的行为。

例如,当从具有活动移植的存储库推送时,可能会错过已“移植”的提交,从而导致另一侧处于损坏状态。

此外,grafts 功能仅限于“重写”提交的父级列表,它不能替代任何其他内容。

实施的更年轻的功能git replace旨在纠正这些限制和危险的错误。

看到git replace现在已经相当成熟了(因为4228e8b (替换:添加--graft选项,2014-07-19,Git 2.1.0)它可以执行嫁接文件的职责),是时候弃用对嫁接文件的支持并退休了它最终。

现在(再次,Git 2.18,2018 年第二季度),你有:

replace: 添加--graft选项

此选项的使用字符串是:

git replace [-f] --graft <commit> [<parent>...]

首先,我们创建一个新的提交,<commit> 除了它的父母是[<parents>...]

然后我们创建一个替换引用,用我们刚刚创建的提交替换。

使用这个新选项,将移植物转换为替换参考应该很简单。


而在 Git 2.20(2018 年第四季度)之前,最近引入的提交图辅助数据与“破坏”对象引用关系的不可变性质的替换和移植等机制不兼容。
当存储库中使用这些不兼容的功能时,根据其使用(并更新现有的提交图)禁用优化。

请参阅Derrick Stolee ( ) 的提交 829a321提交 5cef295提交 20fd6d5提交 d653824提交 b775896提交 950c62b(2018 年 8 月 20 日。 请参阅Stefan Beller ( ) 的提交 212e0f7提交 4a6067c(2018 年 8 月 20 日(由Junio C Hamano 合并 -- --6d8f8eb 提交中,2018 年 10 月 16 日)derrickstolee
stefanbeller
gitster


使用 Git 2.24(2019 年第四季度),在响应浅层克隆/获取请求时需要禁用提交图的“ upload-pack”(“”的对应物git fetch)不再恐慌。

请参阅Jeff King ( ) 的提交 6abada1提交 fbab552(2019 年 9 月 12 日(由Junio C Hamano 合并 -- --提交 098e8c6中,2019 年 10 月 7 日)peff
gitster

## upload-pack: 更温和地禁用提交图以进行浅层遍历

当客户要求某些浅层选项(例如“deepen-since”)时,我们会进行自定义的 rev-list walk 假装是浅层的。
在这样做之前,我们必须禁用提交图,因为它与存储库的浅视图不兼容。这是由829a321处理的(commit-graph:close_commit_graph before shallow walk,2018-08-20,Git v2.19.2)。
该提交实际上关闭并释放了我们的repo->objects->commit_graph struct.

对于已经使用提交图解析的提交,这会产生一个有趣的问题。
他们的commit->object.parsed标志已经设置,他们commit->graph_pos的设置,但他们commit->maybe_tree可能仍然是NULL
当有人稍后调用repo_get_commit_tree()时,我们看到我们还没有加载树 oid,并尝试从提交图中获取它。
但是既然它已经被释放了,我们就会出现段错误!

所以问题的根源是提交的延迟加载树 oid 和提交图可以在进程中消失的事实之间的数据依赖关系。

于 2018-05-24T20:37:34.430 回答
8

使用 git-svn 时:

git 移植对于将 Git 树导入 Subversion 存储库非常有用。

例如,我创建了一个本地 Git 存储库作为开始。经过几天的工作,创建了大量的提交,我不得不将它发布到中央 Subversion 存储库中,我不想丢失历史记录。

我找到了以下操作方法文章: http ://eikke.com/importing-a-git-tree-into-a-subversion-repository/

于 2011-04-14T15:25:19.513 回答