我怎样才能恢复我的引用日志列表,以便整个列表也出现在 "git log" 中?

How can I recover my reflog list so that the entire list appears in "git log" as well?

我是 git 的新手,我试图将一些东西推送到我的远程存储库,但当它不起作用时,我重置了我的 git,现在我可以看到我的代码不是走了,(这是我的代码的最后一个运行良好的版本仍然存在)这是一种解脱。但是当我 运行 "git log" 它只显示最后一次提交。我有点喜欢我的提交历史,因为我在我的项目中向前推进,我希望能够看到我以前所有代码的发展和进步。因此,当我执行 "git reflog" 时,我可以看到它们,但是当我执行 "git log" 时,我只能看到最后一个。

所以,在我的例子中,我没有丢失任何东西,我的最后一次提交在那里,我的代码是最新的到它的最后一个版本,只是我看不到我的提交历史。我想像以前一样查看我的提交历史。而已。

有人可以帮忙吗?

P. S. 请尽快帮助我,因为我已经阅读过 reflog 每 90 天清理一次! :(

干杯,

如果您使用了 git reset,您可能已经移动了分支标签以指向不同的提交(这就是 git reset 所做的,或者更准确地说,是几件事之一 git reset 可以做到1)。也就是说,假设您在名为 xyzbranch 的分支上有一些提交,因此 xyzbranch 指向最尖端的提交,在此处标记为 *。让我们进一步假设有一个 origin/xyzbranch 指向另一个提交,可能是链中较早的提交,或者甚至可能在链的侧分支上;让我们在这里用更大的(大写)O 标记那个:

                         xyzbranch
                             |
                             v

... <- o <- ... <- O <- o <- *

                   ^
                   |
            origin/xyzbranch

此外,假设您当前处于 xyzbranch(因此 git status 表示 on branch xyzbranch)。然后,假设您执行以下操作:

$ git reset --hard origin/xyzbranch

这会指示 git 更改您当前分支指向的提交,以便它指向您刚刚命名的提交。结果如下所示:

               xyzbranch
                   |
                   v

... <- o <- ... <- O <- o <- *

                   ^
                   |
            origin/xyzbranch

请注意,提交 * 仍然在那里,尽管可能很难找到。你是对的:它受 reflog 保护 xyzbranchHEAD。 (不过不是90天,默认是30天。2

诀窍是为提交 * 找到一个名称。它的 "true name" 是 SHA-1 散列,当然它太长太疯狂以至于不能一直输入,比如 19ca3f07...dd5 之类的。但是,如果您能找到该名称,则可以确定您可以通过提供该 SHA-1 来命名提交 *

或者(更简单),您可以使用 git reflog:

查看您的 reflogs
$ git reflog
ca0bf9d HEAD@{0}: reset: moving to HEAD^
0cba526 HEAD@{1}: commit (merge): temp-commit-ugh
ca0bf9d HEAD@{2}: commit: create new file in master
... [snip]
$ git reflog dev
76c1ae2 dev@{0}: commit: create newfile in dev
696077e dev@{1}: commit: modify sub/one
... [snip]

(这些提交消息很糟糕,因为这是我用来测试某些合并案例的临时存储库)。

最左边的部分是哈希的缩写版本,这是一个您可以随时使用的字符串。下一部分,HEAD@{3}dev@{1} 或其他,是一个 relative 索引(到 @ 之前的名称)告诉 git 在那个特定的 reflog 中搜索的深度。每次更新 ref 时——无论是 HEAD(跟踪 "the current branch",无论是什么分支),或者像 xyxbranch 这样的特定分支,或者在我的例子中,分支 devmaster—git 添加一个新的 reflog 条目(或两个,如果 HEAD 像通常那样命名一个分支)。这会将所有其他 reflog 条目向下推一级,因此无论之前在 HEAD@{3} 中,现在都在 HEAD@{4} 中。

如果这是你所做的,并且你希望 xyzbranch 再次指向提交 *,你可以使用 git reflog xyzbranch 查看 xyzbranch 曾经指向的位置,以及什么行动改变了它。在我的例子中,我在 HEAD 上进行了重置(这实际上是 master,所以我也可以在 master 上看到它,但我将只使用默认的 HEAD reflog)。操作 reset: ... 显示了我的 git reset 命令,因此 HEAD 之前指向的任何地方都很有趣。您可以将数字(此处为 0cba526)或索引名称(此处为 HEAD@{1})提供给 git loggit show 以查看它。

找到正确的提交后,您可以使用 git reset 将分支标签移回那里。或者,如果您想将分支标签保留在现在的位置,您可以创建一个指向所需提交的 new 分支。假设我想 0cba526 到一个新分支。有两个命令可以做到这一点:

$ git branch newbr 0cba526

或者,如果您希望 git 在 newbr 上——即首先创建指向提交 0cba526newbr,然后还执行 git checkout newbr:

$ git checkout -b newbr 0cba526

(请注意,这两者都要求您的工作树是干净的,就像在较早的 git reset --hard 之后一样)。让我们画最后一张图,这就是你在 git branch newbr 0cba526 命令之后得到的图,这次也将 HEAD 添加到图片中:

                 HEAD
                   |
                   v
               xyzbranch   newbr
                   |         |
                   v         v

... <- o <- ... <- O <- o <- *

                   ^
                   |
            origin/xyzbranch

(我相信,如果您将 git 的分支标签视为您粘贴到提交 ID 上的黄色小便签,我相信这会有很大帮助。这些便签会脱落并粘贴到不同的提交上,并且这种情况一直发生并且在 git 中完全正常。同时 HEAD 是另一个便签,通常直接粘贴在其中一个分支标签便签的顶部,以便您同时移动两者—但是您可以将它们分开,然后将 HEAD 粘在提交节点上,然后 HEAD 继续在提交节点上漫游,直到您使用 git checkout <branch> 剥离 HEAD关闭提交节点并将其粘贴到 <branch>.)

的黄色便利贴上

1我坚信 git reset 做了 太多 事情,这是难以解释的部分原因.但我们坚持这样做,在 git.

2更准确地说,reflog 条目本身会过期:有些会在 30 天后过期,有些会在 90 天后过期。一旦 reflog 条目本身过期,then 它们保护的提交将不再受到保护。 30 天的期限适用于指向从相应引用可达 的提交的引用日志条目:也就是说,如果这是 master 引用日志,并且 master@{123} 指向提交 faded00master 指向提交 ac0ffee,然后我们决定 master@{123} 现在是否存活,首先做:

git merge-base --is-ancestor faded00 ac0ffee

如果答案是"yes, faded00 is an ancestor of ac0ffee"那么我们选择90天,否则我们选择30天。然后我们检查 master@{123} 的日期戳,如果它太旧,我们将其丢弃,这样 master@{124} 向下移动一个并成为新的 master@{123}.

一旦 reflog 条目被丢弃,它就不再保护提交(在本例中为提交 faded00)。如果 else 仍然保护提交,提交仍然是安全的。但是,如果没有保护它,它可能会被垃圾收集并最终被删除。