0

这是我简单直接历史的最后一部分的图片(来自 SourceTree,时间从底部到顶部):

在此处输入图像描述

因此,在这种情况下,我要求 SourceTree 对最底部提交(“Xcode 10.2,Swift 5”)的子项进行交互式变基,因为我想折叠接下来的两个提交(“该死,属性列表编码”和“ v1.1.1build24") 到单个提交中。没有遥控器,所以我可以自由地重写历史并保持它的清洁和信息量。

但是当我这样做时,从“Xcode 10.2,Swift 5”分支创建了一大堆新的提交——现有提交链的副本。我不明白为什么,我花了很多时间来清理它。

它不完全是一个新的“分支”(正如我的问题标题所言);但是通过“v1.1.2build28”的现有提交最终在他们自己的死胡同分支线上,master现在有这些新的提交,复制这些提交但没有标签和今天的日期。

我的问题是:为什么会发生这种情况,我应该怎么做?

4

2 回答 2

1

它按预期完成。

“该死,属性列表编码”和“v1.1.1build24”被压缩为一个提交。Git 通过创建一个新的提交来实现这个 squash,其父提交是“Xcode 10.2, Swift 5”,其更改等同于“darn,属性列表编码”和“v1.1.1build24”的更改。

“v1.1.1build25”的父或基是“v1.1.1build24”。现在一个新的提交已经取代了“v1.1.1build24”和“该死的,属性列表编码”。因此,“v1.1.1build25”的父级需要是新的提交。否则,“v1.1.1build24”之上的提交将不再存在于master. 为了将“v1.1.1build25”从旧库移动到新库,Git 还为“v1.1.1build25”生成了一个新提交,其父级现在是压缩提交,其更改等同于“v1” .1.1build25”。因此,所有其余的后代都被重新创建,因为它们的父母/基地发生了变化。

Git 创建新的提交,就好像旧的被替换了一样,但旧的仍然存在于存储库中,只是它们不再可以从master. 然而,像“v1.1.1build25”这样的标签和像“temp”这样的分支仍然指向旧的提交。由于这些旧提交现在不在当前master,因此这些标签和分支也看不到master

于 2019-05-06T03:48:06.983 回答
1

没有错。这正是 git 的工作原理。Git rebase 只不过是一个小型机器人,它可以进行一系列提交的新版本。

有些人,甚至是文档,说“改写历史”,这简直是糟糕的措辞。在 git 中重写历史是不可能的——曾经提交过的东西,再也不能改变了。git rebase 仅有助于将旧历史复制到新版本的历史。但是 - 如果旧历史(如您的情况)具有其他标签或分支,即使在变基后它们仍将继续指向旧历史。

因此,一个 git 存储库包含许多死分支是完全正常的。有时你可以看到它们(因为其他标签/分支仍然引用它们),有时你不能 - 但如果你碰巧记住了 SHA ID,你总是可以参考它们。(有时,git 的垃圾收集器会出现并收集历史中真正死气沉沉的部分,没有任何意义)。

这很好,因为你不能犯任何错误(1)。你总是可以简单地git reset --hard到历史的某个点,因为历史永远不能在 git 中改变。如果您尝试了 rebase、merge 或其他任何操作,但它没有像预期的那样工作 - 如果您记住了之前的 SHA(或者如果您标记了它),您可以返回那里。(如果没有,您可以通过 找到它git reflog)。在收集垃圾之前,您总是有几天的时间这样做。

显然这对您不利,因为您有很多标签还想指向新的历史记录。我google了一下,可能有工具可以将它们带到新的分支,但我从未使用过这样的工具。试试看,或者把它当作一个事实,git 有一个不可改变的历史。也许有一天,你会开始喜欢你可以毫无风险地进行试验:-)

(1) 真正失去工作的唯一方法是在您的工作目录中进行更改并且不提交它们。如果您有未提交的更改并进行了reset --hard,它们将永久丢失,并且没有人会警告您。

于 2019-05-06T03:52:59.413 回答