听起来您想修改您的提交图不修改任何trees附加到这些提交。
如果您了解 git 内部的工作原理,这个说法就会更有意义。这里的关键项目是:
所有提交都是永久且不变的,因为提交(或者实际上 git 的四个内部对象中的任何一个)的“真实名称”是其内容的 SHA-1 加密校验和。这意味着,如果您尝试更改任何内容(或者发生故障的磁盘驱动器更改某些内容),git 会抱怨校验和错误,因为您在每个对象中看到的内容不再与其“真实名称”匹配。
每个提交都带有“树”对象的 SHA-1 ID,该对象充当该提交附带的源的完整快照。 (该树给出了每个文件或目录的文件名和 SHA-1“真实名称”。子目录由另一棵树表示。这里的细节并不重要。)
每个提交还列出其父级的“真实姓名”SHA-1 ID。因此,鉴于提示提交develop
,git 可以读取该提交并找到其直接父级。读取该父项(或那些父项)后,git 会找到下一个 ID,并为其父项读取,依此类推。该过程在读取“根”提交(没有父提交)时停止。做一个--orphan
签出后进行提交会产生新的根提交,这无疑是您创建分支的方式。
这些父 ID 和树 ID 存储在任何给定的提交中,据说“指向” git 存储库中的其他对象。 (存储库中只有四种类型的对象。我们已经提到了“提交”和“树”,另外两个是“blob”(git 保存文件的方式)和“标签”。树指向 blob 和 sub -树和“标签”对象用于带注释的标签。)
因此,您要做的就是更改您的根提交develop
分支,以便它现在有一个父提交,特别是可以从当前提示到达的一些提交master
分支。 (也许您想要小费本身,也许您想要类似的东西master~100
:这个细节仅在您进行更改时才重要。)
坏消息是,由于第 1 项,您无法完全做到这一点。
好消息是你can可以使用三种替代方法中的任何一种来完成此操作(如果需要和需要,然后使移植物永久化)。
首先,git有一个东西叫做“移植”。它们的工作效果不太好,所以 git 有一个更好的新东西,称为“替换”。根据您的 git 年份,您应该至少拥有一个,并且几乎肯定两者都有。
它们都使用相同的总体思想。当 git 进行图形遍历时,从提交到父级,您希望在某个时刻能够让 git 更改其遍历。使用 gitrafts,你只需指定当对象具有 id 时<X>
它应该遍历到父级<Y>
。这可以让你找到当前的根提交develop
并将其直接移植到某些提交上master
.
这些移植物不会被复制git clone
,并引入其他问题,所以现在 git 有git replace https://www.kernel.org/pub/software/scm/git/docs/git-replace.html。这会在存储库中创建一个实际对象,并允许您检查有替换和没有替换的提交图。要在这种情况下使用它,您需要为您的根提交进行替换提交,这与现有的根提交完全相同,只是它具有您所需的父提交。
如果您想完全重写历史记录,使所有用户在经历了一个痛苦的重写步骤后都可以轻松完成,您可以设置一个移植,然后使用git filter-branch
复制并替换移植物。或者,也许稍微容易一些,指定一个父过滤器(并且没有其他过滤器)。看the git filter-branch文档 https://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html了解详情;它有一个这样的例子。 (文档表明创建移植物更简单,我认为使用--parent-filter
更简单;但无论哪种方式,都有一个方便的例子。)
注意过滤器分支copies每个“过滤”提交,通过(虚拟)检查该提交,应用一些更改,然后应用过滤器,然后根据结果创建新的提交。在本例中,第一个更改是将父 ID 添加到根提交。第二个更改是一个过滤器分支自动执行:进行提交follows不再孤立的根副本指向根副本。第三个改动与第二个相同,以此类推:
A--B--C <-- develop (before filtering)
...--o--o--... <-- master
\
A'-B'-C' <-- develop (after filtering)
在这里,提交A'
与提交完全相同A
除非它有一个家长 ID;B'
完全就像B
除了它的父级是A'
代替A
;等等。
(顺便说一下,请注意,父箭头在这里全部指向左侧,但是filter-branch
从左到右工作。它通过首先枚举要过滤的所有提交,以从右到左的方式获取它们的 ID,然后从左到右进行过滤来实现这一点。)
现有的 SO 问答有更多关于使用移植或替换的内容。 https://stackoverflow.com/q/6800692/1256452
上面我确实提到了第三种方法。此功能仅在以下情况下有效develop
没有现有的合并提交。然后你可以简单地对每个提交进行变基develop
到你的目标提交,如西里德在评论中建议 https://stackoverflow.com/questions/32954312/how-can-i-attach-an-orphan-branch-to-master-as-is#comment53733496_32954312。您需要运行该 rebase 命令--root
从独立的根目录复制每个提交develop
branch.
这有效是因为git rebase
简单地复制提交,方式大致相同git filter-branch
做。从某种意义上说,这是更多的工作,因为way变基副本提交是通过应用差异(使用重复git cherry-pick
s,或多或少)而不是简单地保留每个复制的提交的现有“树”对象,但它比git filter-branch
。这里的缺点是 rebase 根本不处理合并提交(好吧,除非你使用--preserve-merges
,它使用交互式变基代码)。