获取所有Git提交的列表,包括“丢失”的提交。

268
假设我有一个像这样的图表:
A---B---C---D (master)
     \
      \-E---F (HEAD)

如果我运行git log --all --oneline命令,我将得到我所有的六个提交记录。
但是如果图形是:
A---B---C---D (master, HEAD)
     \
      \-E---F

我将不会看见 E 和 F。我能让 Git 告诉我所有的提交记录,包括那些没有命名的分支吗?

12个回答

287

试试:

git log --reflog

该命令通过假装所有由reflogs (git reflog)提到的对象在命令行中被列为<commit>,以列出所有的 git 提交。


1
这就是我一直在寻找的——--reflog参数的功能。 - Anomaly
4
顺便提一下,gitk也支持这个功能:gitk --reflog . - ald.li
24
退出 Git 日志,请输入“q”。 - Nuryagdy Mustapayev
这个也显示了本地提交“丢失”的情况,例如执行 git reset origin/branch 时,并不是真正无法访问,只是在日志中不再显示。 - Sami Kuhmonen
意外地执行了 git checkout -B my/branch 命令,意味着意外地
切换并重置了分支。
使用这个日志列表,我找到了之前的 HEAD 提交记录,谢谢。
- Codesleuth

78

挽救了我的生命的是以下命令:

git reflog

在这里,您会找到一个显示git提交历史记录的屏幕,就像这样:

enter image description here

此时,您只需要找到所需的HEAD@{X},创建一个临时分支并移动到它,如下所示:

git checkout -b temp_branch HEAD@{X}

这样,您将拥有一个临时分支,其中包含您丢失的提交,而无需重新设置基础或使您的git存储库更加混乱。

希望这有所帮助...


把这个天使的脸颊捏一下的冲动 - Rodrigo Damasceno

74

如果你已经丢失了指向分支末端的指针,那么它就像在草堆里找针一样不容易。你可以找到所有似乎不再被引用的提交-git fsck --unreachable可以为您完成此操作-但其中将包括您在git commit --amend之后放弃的提交,以及在分支上重新设置等等的旧提交。所以一次看到所有这些提交很可能是太多信息需要浏览。

因此,轻率的回答是,不要失去对你感兴趣的事物的追踪。更严肃地说,引用日志将保存默认情况下过去60天左右使用的所有提交的参考。更重要的是,它们将提供关于这些提交“是什么”的一些上下文信息。


9
使用 "commit --amend" 或 "rebase" 故意孤立提交记录和在分离 HEAD 的状态下意外孤立提交记录之间没有任何区别。 - Cascabel
3
确实。从那种情况中恢复最简单的方法可能是查看HEAD本身的reflog记录。 - araqnid
@Jefromi:关于git commit --amend等命令留下死胡同、丢失提交的问题,你指出了一个很好的观点。我进行了一些变基操作,最终得到了一些无法从任何分支访问的提交,感觉在代码库中留下它们有点不妥。现在,这个想法不再那么令人不安了。 :) - Emil Lundberg
2
@araqnid,我陷入了与原帖作者相同的困境,你建议查看reflog正是应该做的事情。 - Ignazio
18
我同意这个答案,但是在某些情况下,有人确实需要查看所有提交记录,包括无主提交记录,无论是故意还是意外的,而 git fsck --unreachable 并不能提供这样的信息。我刚刚尝试过了。更好的方法是使用 git log--reflog 选项,就像 kenorb 回答 的那样。特别棒的是,结合 --graph 使用,你可以获得易于解析的视觉上下文,就像原始问题中所示的那样。比如,尝试一下:git log --graph --all --oneline --reflog - Inigo
显示剩余5条评论

73

当我处理这个问题时,我使用以下命令:

git reflog |  awk '{ print $1 }' | xargs gitk

这让我可以可视化最近的提交,这些提交已经变得无头了。

我将其包装在一个名为~/bin/git-reflog-gitk的脚本助手中。

编辑:- 我的git-reflog-gitk包装器是多余的 - 因为现在你可以直接调用gitk --reflog


2
这简直救了我的大忙...谢谢! - Bret Royster
太棒了!谢谢你!它真正地将树的重要部分可视化了出来。 - Mladen B.
只是一个提示:这仅适用于您本地工作,因为reflog记录了“分支和其他引用的提示何时在本地存储库中更新”。如果您想对非本地引用更改执行此操作,可以使用git log --reflog - Krishna Gupta
这里更新一下 - 如其他答案/评论所述 - 我的解决方案已经过时了 - 现在你可以直接使用 'gitk --reflog'。 - Kieran
这将打开gitk GUI,而不显示任何提交哈希。 - alper

32

与Kieran的回答类似,但是用于控制台:

git log --oneline --all --graph --decorate $(git reflog | awk '{print $1}')

你需要包含最后一部分:$(git reflog | awk '{print $1}')吗?这是做什么的?在尝试了你的解决方案之后,似乎即使没有最后一部分也会产生相同的输出。 - wmock
如果您移动分支指针并且留下一些没有引用的提交(就像 OP 所做的那样),它们将不再显示在 git log --all 中。一个快速的例子:在 git reset --hard @^ 之后,您的 HEAD@{0} 提交将只存在于 reflog 中,而由于 git reflog 不支持 --graph,您必须将提交传递给 git log --graph 来获得可视化表示。 - Florian Fida
6
你可以使用 --reflog 替换 $(git reflog | awk '{print $1}') - Sild
我将 git log --oneline --all --graph --decorate $(git reflog | awk '{print $1}')git log --oneline --all --graph --decorate --reflog 进行了比较,它们几乎完全相同,只是 --reflog 包含了 WIP 条目等详细信息。 - Script Wolf
1
@FlorianFida,为什么不使用log --reflog而不是reflog呢? - Pacerier

15
git log --reflog

你救了我!当我合并HEAD时,我丢了我的提交记录,无法找到我的最新提交记录!在SourceTree中也没有显示,但是git log --reflog会显示我本地所有的提交记录。


9
我该如何解决这个问题?使用git fsck和日志记录!
首先创建一个文件,其中包含丢失(无法访问)的提交和blob。 (注意:如果您执行了类似于git gc的操作,则它将垃圾回收所有提交,您将无法在此处找到它们!)
$git fsck --lost-found > lost_found.commits

这将给你一个类似这样的文件:
``` dangling commit dec2c5e72a81ef06963397a49c4b068540fc0dc3 dangling blob f8c2579e6cbfe022f08345fa7553feb08d60a975 dangling blob 0eb3e86dc112332ceadf9bc826c49bd371acc194 dangling blob 11cbd8eba79e01f4fd7f496b1750953146a09502 dangling commit 18733e44097d2c7a800650cea442febc5344f9b3 dangling blob 1e53a5cdb3ecdde27081ec6e8b31e4070106ee05 ```
您可以使用喜欢的文本编辑器打开此文件,以从中复制提交/博客哈希。 (*咳嗽* vim宏非常适合这个 *咳嗽*)
现在,您可以使用类似于git log --oneline <commit hash>的命令从此提交记录回滚。或者,gitk、tig或任何其他git查看器都应该可以工作。
在您的情况下,如果找到提交F的哈希值,则日志将显示如下内容:
A---B---E---F

快速简便!现在你可以找到所有那些“悬挂提交”的背景。

附言:是的,我知道,发文有点晚了,但没关系,也许有人会在这里找到它并且发现它很有用。(最有可能再过六个月我再次谷歌搜索时会用到。)


7

通过查看位于.git/logs/HEAD的引用日志,我成功地找回了提交。

然后我不得不向下滚动到文件末尾,并找到了我刚刚丢失的提交。


这是我把东西搞砸时最终所做的事情。尝试提交到主分支,但推送时遇到了问题。我执行了reset --hard命令,然后意识到我的错误。由于提交位于reflog中,因此我检出了它,并从中创建了一个分支,然后推送该分支。最终一切都解决了。 - David

7

实际上,git fsck可以用于查找所有丢失的提交,您只需要选择正确的选项:

git fsck --unreachable --no-reflogs

--unreachable 仅仅通过该命令是不够的,因为一些提交可能仍然被引用于 reflog 中。如果你需要一个相当清晰的整个提交历史视图,你可以创建一个类似下面这样的别名:

git log --all --decorate --oneline --graph $(git fsck --no-reflogs --unreachable | awk '{if ($2 == "commit") print $3}')

说实话,我不确定在这个最后的命令中是否需要--unreachable选项,因为git log默认遍历祖先(除非指定了--no-walk)。我不敢确定,但我认为这不是必要的。


5
我们可能会发现使用git log命令不能获取到所有提交的详细信息,因此我们可以这样查看:

针对Mac系统:进入你的git项目并输入以下命令:

$ nano .git/logs/HEAD

要查看您在其中的所有提交,或者:
$ gedit .git/logs/HEAD

要查看您在其中的所有提交记录,

然后您可以在任何您喜欢的浏览器中进行编辑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接