git grafts
与replace
上的Q& A很少。搜索 [git] + grafts + replace 只找到两个与5 what-are-git-info-grafts-for和git-what-is-a-graftcommit-or-a-graft-id相关的内容。 git.wiki.kernel.org:GraftPoint
replace
和filter-branch
现在完全超过的移植物,或者某些特殊的角落情况(以及向后兼容性)是否还需要它们?
一般来说,它们如何不同(例如哪些是在回购之间运输),它们通常是如何相同的? 我已经看到Linus在关于提交世代号的讨论中似乎并不关心移植物(最大父母回到任何根种类)"Grafts are already unreliable."
编辑:找到更多信息。
搜索www.kernel.org/pub/software/scm/git/docs graft
只找到3个结果:
稍微更广泛的搜索RelNotes/1.6.5.txt包含:
- refs / replace / hierarchy旨在用作替代品 “移植”机制,具有额外的优势,它可以 转移到存储库。
不幸的是,gitrepository-layout(5)还没有更新refs / replace / repository布局信息(和备注),也没有任何弃用的信息/移植信息。
这更接近于支持我的想法,但我欢迎任何确认或澄清。
答案 0 :(得分:16)
在您提及的same discussion约Commit Generation Number Jakub Narębski does confirm中,移植物比解决方案更具有问题:
移植物是如此可怕的黑客攻击,如果使用它们,我不会反对关闭世代数字 在替换对象的情况下,您需要非替换和替换 DAG代号。
[...]移植物不可转让,如果您使用它们来剔除而不是添加 历史他们对垃圾收集不安全......我想。
(git filter-branch
一直照着2008 thread on grafts workflow进行发布,如grafts所示。)
此git replace以及SO question "Setting git parent pointer to a different parent"的评论最能说明(Jakub's again) answer与Git1.6.5之间的差异。
它包含对GraftPoints
的引用根据我的理解(来自{{3}}),
git replace
已取代git grafts
(假设你有git 1.6.5或更高版本)(Jakub :)
- 如果您想重写历史记录,那么
grafts
+git-filter-branch
(或互动式rebase,或快速导出+例如reposurgeon)就是这样做的方法。- 如果您想要/需要保留历史记录,那么
git-replace
远远优于移植
答案 1 :(得分:13)
如果您需要使用git replace
重写父提交,则可以使用此方法。
正如Philip Oakley所说,git replace只是将一个提交替换为另一个提交。要将父级移植到现有提交,您需要首先使用正确的父级创建虚假提交。
假设您有两个要移植的git分支:
(a)-(b)-(c) (d)-(e)-(f)
现在我们希望(d)成为(c)的父母。因此,我们使用正确的父(我们称之为c1)创建(c)的替换,然后使用(c1)创建git replace
(c)。在这些步骤中,每个字母都引用表示该提交的SHA1哈希。
创建新提交:
git checkout d
git rm -rf * # remove all files from working direcotry
git checkout c -- . # commit everything from c over top of it
GIT_AUTHOR_DATE="..." GIT_COMMITTER_DATE="..." git commit -m "..." # create replacement commit with date author
现在你有提交(c1),它具有正确的父(d)。所以我们需要做的就是用(c1)替换现有的(c):
git replace c c1
现在您的历史记录如下:
(a)-(b)-(c1)-(d)-(e)-(f)
宾果!
答案 2 :(得分:7)
编辑:git replace --graft <commit> [<parent>…]
与移植物做同样的事情,它可以添加或删除父母。 documentation说:
创建移植提交。创建一个新提交,其内容与&lt; commit&gt;相同。除了它的父母将是[&lt; parent&gt; ...而不是&lt; commit&gt;的父母。然后创建替换引用以替换新创建的提交。
(我将以下旧答案作为参考。)
AFAIK,有grafts
可以处理的一个用例,但replace
不能:添加或删除父项。它是重构历史的强大工具。
例如,如果您将历史记录从旧的SVN存储库导入Git,则没有合并信息。您可以做的(我已经做了很多次)是通读提交消息以找出SVN“合并”的位置,然后使用Git grafts将父级添加到合并提交。
IIRC,我还有一些案例,我已经删除了提交的父级,以使其成为历史上的第一个提交。基于多个混乱的遗留存储库创建干净的历史记录有时需要采取严厉的措施(我的博客上有some experiences of migrating projects to Git)。然后,在清理完整个历史记录之后,在发布新的Git存储库之前,您将执行git filter-branch
。