说我有这个:
A - B - C - E - F [integration]
\
G - H - I [feature]
在提交I
之后,我们以集成为基础:
git fetch origin
git rebase integration
所以我们现在有:
A - B - C - E - F [integration]
\
B - C - E - F - G - H - I [feature]
然后说我们将特征分支合并到集成中,然后得到:
A - B - C - E - F - G - H - I [integration]
\
B - C - E - F - G - H - I [feature]
(我认为是正确的),但是我不知道这与不重新定基有什么不同?
答案 0 :(得分:2)
您的绘画误导了您。
记住这些事情:
如果有帮助,可以将提交视为坚固的大物件:例如,砖和梁组成建筑物。 (就像超大乐高积木一样,每个积木都有一些与其他积木的连接器,我们将积木插入在一起以形成链。这些连接通过哈希ID:它们来自子提交,并指向父提交。 )
另一方面,分支名称是重量很轻的商品。它们就像便签一样,您先拍一下,然后再剥下来再拍一次。
所以,如果您有这个:
A <-B <-C <-E <-F <-- integration
\
G <-H <-I <-- feature
您无法获取第二张图片,因为现有提交G
记录了A
的哈希ID。您不能拥有一个以G
作为其父元素的F
。您也不应绘制两次提交,如果可能的话:提交是唯一的东西,只有一个提交G
。
git cherry-pick
是复制提交的构建基块通常,我们发现自己处于G
之类的提交状态,这种状态就可以了,但是如果它有所不同,我们会更喜欢它。我们想要一个新的副本,它像 G
,但以F
作为其父副本,并且也具有与原始G
不同的源树快照。让我们将新提交称为G'
来与G
区别开来,但提醒我们,它非常像 G
。我们希望 F
和G'
之间的差异与 A
和G
之间的差异相同,从而也考虑了由于提交B-C-E-F
而需要进行的任何更改。所以我们想要的是一个看起来像这样的提交图:
G' <-- new-and-improved-feature
/
A--B--C--E--F <-- integration
\
G--H--I <-- feature
如果我们然后将提交H
复制到新的和改进的 H'
,然后将I
复制到新的和改进的 I'
,我们得到了:
G'-H'-I' <-- new-and-improved-feature
/
A--B--C--E--F <-- integration
\
G--H--I <-- feature
git reset
移动标签 git reset
所做的事情-可以做的几件事之一,但这就是我们现在要处理的事情-移动分支名称sticky-labels。
有一个粘贴标签,上面我们写了feature
一词。该粘性标签现在附加到提交I
上。但是在新的和改进的设置中,我们仅使用git cherry-pick
三次,将G-H-I
序列复制到G'-H'-I'
序列中。
如果现在我们有Git,将标签feature
从提交I
上剥离下来,然后将其粘贴到提交I'
上,我们将得到:
G'-H'-I' <-- feature (HEAD), new-and-improved-feature
/
A--B--C--E--F <-- integration
\
G--H--I <-- ORIG_HEAD
要实现这一点,我们运行:git checkout feature; git reset new-and-improved-feature
。
git reset
命令设置此特殊名称ORIG_HEAD
来记住feature
过去的去向。现在,标签feature
已附加到提交I'
,但是有多种方法可以找到I
,包括此ORIG_HEAD
技巧。
(我们不再需要“新功能和改进功能”标签,因此我们现在可以将其删除。)
请注意,没有提交已更改。原始G
仍在存储库中。运行git log ORIG_HEAD
,我们仍然可以看到它,至少直到执行另一个使用ORIG_HEAD
来记住其他提交的Git命令为止。我们将看到I
,然后是H
,然后是G
。我们还可以对feature
使用 reflog 来查找提交G
,H
和I
的哈希ID。只要我们具有哈希ID或哈希ID的名称,就可以找到提交。 (那些引用日志条目最终会过期,它们带有日期戳,一三个月后,Git会删除引用日志条目。)
但是,如果我们使用名称feature
,则会查找新副本,而不是原始提交。只要我们不密切注意并注意到实际上它们是 new 提交,就可以使好像提交已更改。
最重要的是:我们复制提交之后,如果我们使用git reset
放弃原始文档,而使用经过改进的新副本,那么我们只会看到新的和改进的副本,我们可以像那样更改提交内容。提交内容没有改变,如果真的有人仔细观察,他们会发现我们的秘密,但是如果其他人从不了解原著,他们就不会发现这些是廉价仿冒品< / strike>改进的副本。
git rebase
=樱桃选择加重置这使我们得出以下结论: git rebase
从根本上说是git cherry-pick
的一组提交中的一个,之后是 git reset
。也就是说,我们从复制提交到新的并且我们希望改进的版本开始。然后我们使用git reset
尝试诱使所有人使用改进的提交来代替原始提交。
任何仍然拥有原始内容的人都不会上当!如果其他人(其他Git存储库)仍然拥有原始内容,我们必须说服他们切换到新的改进的提交。但是,如果我们是唯一有权访问提交的人,则只需要愚弄自己,这可能会更容易。
答案 1 :(得分:1)
从本质上讲,我已经阅读并发现的是,只有在您想删除提交历史记录时才进行重新设置。 Git重置将更改参考文件中的参考历史记录。
我对堆栈溢出两者之间的区别找到了很好的解释:here
我希望这有助于弄清哪种选择是在哪种情况下工作的最佳工具。