我不小心输入了git reset --hard origin/<branch>
(准确地说,我混淆了一些别名)。问题是我没有推动我的提交,现在他们已经丢失了。我能以某种方式回来吗?
答案 0 :(得分:4)
在错误的git reflog
之前,先向{1}}进行checkout
或reset
。 (也许先修复你的别名。)
答案 1 :(得分:2)
我看到你已经从中恢复了,但是,这是思考它的方法。您必须根据&#34; commit graph&#34;:一组提交(我用单个字母标记)来查看您的提交,其中每个提交都指向其父提交。带有一个分支并在其中合并的链看起来像这样:
C <- D
/ \
A <- B G <- H <- I
\ /
E <- F
所有箭头指向后方(或者对于有角度的箭头指向后退/上下,我没有箭头可用,所以我只使用\
和/
)。
分支,例如master
或devel
,只是带有箭头的标签,指向图表中的某个提交。 (特殊标签HEAD
通常只包含其他标签的名称,例如master
,因此我将其写为HEAD=master
。这会让您知道,如果有其他标签,哪一个是如果我们有颜色,我们可以将它变成鲜红色或绿色或其他颜色,但是对于文本,我们会选择HEAD=
。)所以有了两个分支,我们可能会有这个:
C <- D
/ \
A <- B G <- H <- I <-- HEAD=master
\ /
E <- F <-- feature
这告诉我们,我们在分支master
上,该分支master
将提交标记为I
(实际上是一些丑陋的SHA-1,如d1574b8...
- 这就是我使用单个字母绘制图形的原因!),并且该分支feature
将提交标记为F
。
git reset有什么作用 - 它有几个作业,但是用标签做什么来改变标签所指向的提交。由于您已经master
,如果您git reset feature
(我们暂时忽略--hard
),您就会告诉git:&#34;删除从现在的任何地方标记master
并使其指向与feature
相同的提交,即提交F
。&#34;这不会改变提交图本身,只需移动标签:
C <- D
/ \
A <- B G <- H <- I
\ /
E <- F <-- feature, HEAD=master
通过&#34; reflog&#34;,提交I
仍在那里(保留在存储库中)一段时间(默认为30到90天),因此您可以找到SHA- 1通过reflog提交I
,直到那些reflog条目到期为止,并使用另一个git reset
使你的标签指向它, 1
(&#34;远程分支&#34;标签origin/master
就像您自己的本地分支标签一样,有一个很大的不同: 2 它会在您使用{时更新{1}}或git fetch
从git pull
获取新内容,而不是在本地执行操作。因此,它可以让您在提交图中找到提交,就像您自己的分支一样。&#39;为什么你可以将这些名称与origin
一起使用:git reset
只需要识别你希望当前分支标签指向的提交。)
reset
命令还有一堆模式选项:reset
,--soft
,--mixed
,还有一些更深奥的模式选项。这些会影响其其他作业。除了将分支标签从一个提交移动到另一个提交,--hard
可以更新您的索引,还可以更新您的工作树。 git reset
参数告诉它:&#34;不要更新任何一个!别管他们!&#34;在这种情况下,仅事物--soft
完成的是移动标签。 3
默认值git reset
告诉它:&#34;更新索引,但不要单独使用工作树。&#34;在这种情况下,--mixed
移动标签,和更新索引以匹配您移动到的提交。
使用git reset
,您告诉它:&#34;更新索引,并使工作树匹配。&#34;在这种情况下,它可以擦除正在进行的工作,因为它使工作树匹配它与目标提交匹配的索引。
请注意,如果您说--hard
- 即,您告诉git reset HEAD
将当前分支从现在的任何地方移动到现在的任何位置 - 标签更改实际上根本没有变化。如果您在分支git reset
上,则告诉git删除标签master
,然后将其重新绘制到master
指向的地方,然后再删除它。它最终指向它指向的位置。在这种特殊情况下,唯一真正的效果是您要求的任何索引和/或工作树更改。
您也可以将索引和/或工作树更改限制为特定文件。完全一般,您使用master
。 4 执行此操作。这意味着:&#34;将当前分支移至 git reset branch -- path
,并执行branch
重置了给定的 --mixed
。&#34;如果 path
为branch
,则分支不会移动,但 HEAD
的索引条目会匹配当前的提交。换句话说,您path
编辑的任何新版本都是未完成的。因此git add
告诉git:不要移动到任何地方,但要将索引中的git reset HEAD -- foo.txt
恢复到当前提交,取消暂存foo.txt
。
如果您遗漏 foo.txt
部分,则默认为branch
,这就是为什么HEAD
是如何撤消git reset
的原因1}}。工作树版本仍然存在,但索引条目已重新设置。 (更准确地说,是您命名的文件的索引条目,如果您命名为任何文件,或者是所有文件。)
使用git-add
,它通过重置索引条目并使工作树与它们匹配来消除文件中的更改。并且它仍然默认使用--hard
,这就是为什么HEAD
(没有其他参数)摆脱所有未提交的更改(因此失去了你的工作,所以你真的意味着得到摆脱他们,我们希望......)。
1 实际上,您可以在不使用原始SHA-1的情况下执行此操作:git reset --hard
。 Reflog名称适用于需要提交ID的任何地方。
2 还有一些较小的差异,例如,你不能让git reset HEAD@{1}
命名为&#34;远程分支&#34;。如果你试试,你只需要一个&#34;分离的HEAD&#34;,它本质上是一个没有标签的本地分支。
3 这对于#s; squash commits&#34;非常有用,但是 - 因为那里HEAD
- 不再是其他的了。在过去,您可以使用它来备份一个提交然后进行替换,但现在您可以使用git commit --amend
更轻松地完成此操作。
4 实际上,在我有 --amend
的地方,你可以使用任何引用来解析为commit-ID 。这就是为什么脚注1中的reflog-name工作的原因。