git移植和replace如何不同? (移植已经过时了吗?)

Git graftsreplace相比,很less有Q&A。 search[git] +移植+replace只发现两个感觉相关的5. 什么是git-info-grafts-for和git-what-is-a-graftcommit-or-a-graft-id 。 还有关于git.wiki.kernel.org:GraftPoint的说明

移植现在是完全replacefilter-branchreplace ,还是还需要一些特殊的angular落案例(和向后兼容性)?

一般来说,它们是如何不同(例如在回购之间运输的),它们又是如何一致的? 我已经看到,莱纳斯目前在讨论承诺代数(最大的父母回到任何根系品种)方面似乎并不关心移植问题。 “移植已经不可靠”。

编辑:find更多的信息。
searchwww.kernel.org/pub/software/scm/git/docs graft只发现3结果:

  1. GIT-滤波器分支(1),
  2. v1.5.4.7 / GIT-滤波器分支(1),
  3. v1.5.0.7 / GIT-s​​vn的(1)。

RelNotes / 1.6.5.txt包含以下更广泛的search:

  • refs / replace / hierarchy被devise成可用作“嫁接”机制的替代品,还具有可以跨库传输的优点。

不幸的是, gitrepository-layout(5)还没有和refs / replace / repository布局信息(和注释)保持同步 ,也没有info / grafts的任何弃用笔记。

这接近于支持我的想法,但我欢迎任何确认或澄清。

JakubNarębski在同样的关于提交代数的 讨论 中确认移植比解决scheme更具有说服力 :

移植是如此可怕的破解,如果使用的话,我不会反对closures代号。
在replace对象的情况下,您需要同时replace和replaceDAG生成号。
移植是不可转让的,如果你用它们来剔除而不是添加历史,他们对垃圾收集是不安全的…我想。

(发布一直由git filter-branch ,正如2008年移植工作stream程所示) 。

移植和gitreplace之间的区别最好的例子是这个SO问题“设置git父指针到不同的父” ,和(Jakub的再次)的评论答案 。

它包含对Git1.6.5的引用

从我的理解(从GraftPoints ), git replace已经取代了git grafts (假设你有git 1.6.5或更高版本)

(:)的Jakub

  • 如果你想重写历史,那么grafts + git-filter-branch (或者交互式rebase,或者快速导出+例如reposurgeon)就是做这件事的方法。
  • 如果你想/需要保存历史 ,那么git-replace远远胜过移植

如果你需要使用git replace来重写一个父提交,那么就是这样做的。

正如菲利普·奥克利(Philip Oakley)所说的,gitreplace只是用另一个replace一个提交 为了将父项移植到现有的提交中,您需要先使用正确的父项创build一个伪提交。

假设你有两个你想要嫁接的git分支:

 (a)-(b)-(c) (d)-(e)-(f) 

现在我们要(d)成为(c)的父母。 所以我们使用正确的父项(我们称之为c1)创build(c)的replace,然后用(c1) git replace (c)。 在这些步骤中,每个字母都指代表示提交的SHA1哈希。

要创build新的提交:

 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)replace现有的(c):

 git replace c c1 

现在你的历史看起来像这样:

 (a)-(b)-(c1)-(d)-(e)-(f) 

答对了!

编辑: git replace --graft <commit> [<parent>…​]做移植和做同样的事情,它可以添加或删除父母。 文档中说:“创build一个嫁接提交。一个新的提交创build与相同的内容,除了它的父母,而不是父母。然后创build一个替代ref,以取代新创build的提交。

(我将下面的旧答案作为参考。)


AFAIK,有一个用例, grafts可以处理,但replace不能:添加或删除父母。 这是重构历史的强大工具。

例如,如果您要将历史logging从旧的SVN存储库导入Git,则不存在合并信息。 你可以做什么(而且我已经做了很多次)是通过提交消息来了解SVN“合并”完成的地方,然后使用Git移植向合并提交中添加父项。

IIRC,我也有一些情况,我已经删除了一个提交的父母,以使其成为历史上的第一个提交。 基于多个混乱的旧式存储库创build一个清洁的历史logging有时需要采取激烈的措施(在我的博客中有一些将项目迁移到Git的经验 )。

然后,在清理完整个历史logging之后,在发布新的Git存储库之前,您需要做一个git filter-branch