正如Makoto已经指出的那样,您可能不需要费心撤销此次变基:这可能是您想要的。尽管如此,如果您想要撤销它,请继续阅读以下内容。
使用reflog来查看分支信息,因为它更易于阅读。(HEAD reflog中也有相同的信息,但是包含了大量其他内容,因此很难找到你要查找的内容。)
例如,如果我刚刚对mybranch进行了rebase,我将会看到:
$ git reflog mybranch
nnnnnnn mybranch@{0}: rebase finished: refs/heads/mybranch onto biguglysha1
ooooooo mybranch@{1}: commit: some sort of commit message
...
这里的名字mybranch@{1}
目前等同于旧的简称SHA-1码ooooooo
。每次对该分支进行操作(例如git reset
),@{...}
部分的数字会改变,而SHA-1码则永久不变,因此使用SHA-1码(完整或简称)进行剪切和粘贴更加安全。
接下来:
$ git checkout mybranch # if needed
并且:
$ git reset --hard ooooooo # or mybranch@{1}
您应该拥有原始版本。这是因为
rebase
仅仅是复制提交并移动标签。在rebase之后,但在reset之前,提交图看起来像这样,其中
A
到
C
是"您"的提交:
A - B - C <
/
... - o - o - o - A' - B' - C' <-- mybranch (after rebase)
git reset
只是简单地擦除当前分支标签,并将其粘贴到提供的 SHA-1 上(如果需要,首先将 reflog 名称转换为 SHA-1)。 因此,在执行 reset
后:
A - B - C <-- mybranch, plus older reflog
/
... - o - o - o - A' - B' - C' <-- (only in reflog now)
请注意,现在在
reset
之后,rebase所做的提交副本是“废弃”的,只能在reflog条目中找到。被废弃的原始提交现在又归属于
mybranch
了。
思考这些东西的方法是画出提交图(新提交指向其父提交),然后用长箭头标记分支标签。图形从不改变,除了添加新提交,这些提交具有新的和不同的SHA-1哈希值(这就是为什么我使用字母如
A
、
B
和
C
,并附加像
A'
这样的副本)。SHA-1哈希保证是唯一且永久的,但带有长箭头的标签却经常被擦除和重新指向。(如果你在白板上做这个,你应该通常用黑色表示提交图和颜色或几种颜色表示标签。)
1嗯,git reset
并不仅仅是移动标签,除非您添加一些命令行标志。默认情况下,它移动标签并且重置索引;使用--hard
,它移动标签并且重置索引并且清空您的工作树。使用--soft
,它只是移动标签,保留索引和工作树。由于git是什么样的工具,还有许多其他标志可以进一步扭曲其含义,但这些是最重要的三个:--soft
,无标志即--mixed
和--hard
。
2如果git只添加而不删除,你的仓库会随着时间变得非常庞大。因此,当“不可达”提交(即没有标签,也没有任何剩余的reflog条目指向它们,并且没有被某个具有标签或其他指向的提交所指向的提交)存在时,git会在自动运行git gc
时删除这些不可达的提交(以及任何其他不可达的对象)。你可以强制提前删除它们,但很少有充分的理由去打扰它们。
3Git本身依赖于这种保证。任何两个不同的对象出现相同SHA-1的可能性是数学上可能的,但极其不可能。如果发生这种情况,git就会出问题。4如果分布足够好,则概率为2160中的1,这非常微小。这是一件好事,因为"生日悖论"会很快提高可能性,但由于开始非常微小,因此保持微小,在实践中从未成为问题。
按照设计,“breakage”的意思是git停止添加对象,这样到目前为止的一切仍然是好的。然后你需要转移到处理数十亿个对象存储库的新系统,即“下一代”git或其他系统。
git rebase master
基本上是将你本地主分支中的内容移动到了你本地主分支中的最新位置。你的本地主分支是否与远程分支不同步?解决这个问题并不是一个简单的过程。 - Makotogit rebase master
命令。我只是想让最后一次提交也出现在branch2上,但它却做了其他的事情(我对Git还不熟悉,所以不确定如何解释它做了什么)。但是有几个提交消失了或被合并在一起了,不确定是哪个。我想将其恢复到所有这些操作之前的状态。 - user1960364