你真的做不到
那个
,因为这将涉及更改某些现有提交。在本例中,现有提交
F
商店
B
的哈希ID作为其父项。任何现有的提交都不能更改:提交是完全只读的(事实上,Git的所有内部对象都是只读的)。
我想你是想假装
F
商店
E
的哈希ID作为其父项,而不更改与任何现有提交关联的快照。你
可以
做
这
,您可以做许多类似的事情。在我们研究这些之前,让我们先看看
git rebase
.
使用的问题
git再基
下面是rebase函数
正在复制
提交(到目前为止一切都很好),每一份副本都像
1.
通过使用
git cherry-pick
(这就是事情开始出错的地方)。为了准确地选择一个提交,Git将:
-
比较提交的快照与提交的父快照,例如。,
J
vs公司
I
或
F
vs公司
B
. 你可以自己跑步
git diff <hash1> <hash2>
,或者更简单地说
git show <hash2>
.
-
将此处显示的差异与父级的差异(
<hash1>
以上)到当前或
HEAD
提交,并使用合并结果进行新的提交。
-
将原始提交的消息复制到新提交。
像往常一样,新的提交会进入当前分支,使分支的提交时间更长,并更改
头部
提交以命名新提交。
合并步骤,加上Git正在将快照(提交)转换为变更集(差异),意味着最终挑选的结果可能与原始快照截然不同。这一切都取决于有多不同
<哈希1>
不管是什么
头部
当您开始此过程时。
这个
git再基
命令本质上自动化了一次挑选一系列提交的过程。在所有复制结束时,
git再基
强制分支标签指向最终复制的提交。这将允许您复制
F
到一个新的
F'
谁的父母是
E
,然后复制
G
到一个新的
G'
谁的父母是
F'
,等等:
A--B--F--G--H--I--J <-- (original)
\
C--D--E <-- (target of rebase)
\
F'-G'-H'-I'-J' <-- branch
1.
有时
git再基
字面上的运行
吉特樱桃采摘
,有时它使用的方法通常会产生相同的结果,但在某些奇怪的情况下,不会产生相同的结果。
现在,假设我们不做这些,而是创建一个Git对象,Git可以在任何时候使用它时将其“放在一边”
F
. 此替换为-
F
进入图表如下:
A--B--F--G--H--I--J <-- branch
\
C--D--E <-- some_name
\
Frepl <-- refs/replace/<hash>
我们为复制提交消息
F
为了这个
Frepl
,并复制大多数其他字段,包括提交树对象的内部Git哈希ID。但不是指向提交
B
犯罪
Frepl公司
要提交的点
E
.
现在我们只需要Git来“转眼”
F
到
Frepl公司
每次它都将与commit一起工作
F
出于任何原因。有一种方法可以做到这一点:我们给予
Frepl公司
一个特殊的名字,
refs/replace/
big-ugly-hash-id
哪里
big-ugly-hash-id
是提交的实际哈希ID
F
.
进行替换的Git命令是
git replace
. 旁视是自动的:Git总是这样做,除非我们运行
git --no-replace-objects
. 一切都结束了
没有
更改任何
现有的
Git对象,所以它只是添加到存储库中。
替换对象的最大缺点是
git clone
默认情况下
没有
复制替换对象(它不提取它们,也不提取它们的名称)。这意味着克隆在视图中没有替换项,并且从不将其放在一边。您可以显式地将替换项添加到fetch refspec以获取它们,但这有点麻烦。这个
git push
默认情况下,操作也不会传输它们。
最大的优点是,它们不要求每个人都停止使用原始的提交,转而使用新的和改进的提交。如果你
可以
但是,让每个人都切换,您可以使用
git再基
复制多个提交并移动分支标签。或者,您可以使用
git替换
首先创建替换对象,然后运行
git filter-branch
没有筛选器,但告诉它筛选发生替换的分支。
什么
git筛选器分支
是否要复制
每一个
提交(在要求筛选的一个或多个分支上)。至少在逻辑上;有很多优化–提取每个提交,从最旧的提交到最新的提交,到临时目录,按一定顺序应用每个过滤器,然后使用过滤器所做的任何操作进行新的提交。如果新提交与原始提交完全相同,则两次提交实际上只是一次提交,否则副本是一次新的不同提交。每个新副本的默认父级是在父级的早期副本中进行的提交(尽管有
--parent-filter
让你改变它!)。所有这些都是通过替换lookaside的手法实现的,
2.
所以当Git去复制
F
,它实际上是复制的
Frepl公司
相反,然后
Frepl公司
返回到
E
. 如果我们有这个过滤器名称
branch
,结果是Git复制
A
然后
B
然后
C
然后
D
然后
E
然后
Frepl公司
然后
G
然后
H
然后
我
,然后
J
,给出:
A--B--F--G--H--I--J <-- refs/original/refs/heads/branch
\
C--D--E <-- some_name
\
Frepl <-- refs/replace/<hash>
\
G'-H'-I'-J' <-- branch
请注意
树枝
要提交的点
J'
,其父级为
I'
但其树(快照)与
J
. 犯罪
我是
点返回到
H'
,它指向
G'
,它指向
Frepl公司
(我们运行时制作的副本
git替换
:在过滤过程中保持不变)。这指向
E
(这是它自己的未更改副本),它指向
D
,等等返回到
A.
.
如果我们把所有的
refs/original/
名称如下
refs/original/refs/heads/branch
,即“水泥到位”任何替换承诺。然后我们可以删除
refs/replace/
的名称
Frepl公司
看起来我们只有一次承诺
A-B-C-D-E-Frepl-G'-H'-I'-J'
在存储库中。这个
哈希ID
许多提交中的个已更改,因此此存储库不再与原始存储库兼容;但如果我们从名字开始
树枝
,我们只能在所有正确的位置看到闪亮的新复制提交。
2.
当然,如果你跑
git --no-replace-objects filter-branch
,这将禁用替换lookaside。可能从来没有任何理由这样做。