为什么git有些commit记录,只有git reflog可以看到,git log看不到?

文章目录

      • 原因分析
        • [1. `git log` 只能显示 **可达的** 提交](#1. git log 只能显示 可达的 提交)
        • [2. `git reflog` 记录所有引用的变更](#2. git reflog 记录所有引用的变更)
      • [常见导致 `git log` 看不到提交的原因](#常见导致 git log 看不到提交的原因)
        • [1. `git reset` 操作](#1. git reset 操作)
        • [2. `git rebase` 操作](#2. git rebase 操作)
        • [3. 分支删除](#3. 分支删除)
        • [4. `git commit --amend`](#4. git commit --amend)
        • [5. 垃圾回收(GC)*](#5. 垃圾回收(GC)*)
      • [如何恢复 `git log` 看不到的提交?](#如何恢复 git log 看不到的提交?)
      • 总结

在 Git 中,有些提交记录只能通过 git reflog 查看,而 git log 无法显示。这种情况通常是因为提交历史已经发生了某种形式的"变更",导致这些提交不再是当前分支或其他引用(如标签、远程分支)的可达提交。

原因分析

1. git log 只能显示 可达的 提交

git log 的工作机制是基于 可达性 (reachability)原则。它只会显示从当前分支 HEAD 或其他引用(如标签、远程分支)可达的提交。所谓"可达",指的是从某个提交开始,通过提交的父子关系可以沿链条一直追溯到该提交。

  • 如果一个提交从当前分支的链条上"消失"了(例如通过 git resetgit rebase 等操作导致提交链被重写或分支被删除),那么这些提交将不再被视为"可达"。
  • git log 不会显示这些提交,因为它只展示当前分支上的提交历史。
2. git reflog 记录所有引用的变更

git reflog 不同,它记录的是 本地引用(HEAD、分支等)的所有变化 ,无论提交是否可达。因此,git reflog 可以看到很多"隐藏"的提交,包括被 git resetgit rebase 覆盖掉的提交、误操作后丢失的提交,甚至是分支被删除后的提交。

只要你在本地进行过操作,git reflog 会记录:

  • 提交、合并、拉取等操作。
  • 分支的切换(checkout)。
  • 重置(reset)或变基(rebase)。
  • HEAD 指针的移动。

即便你删除了一个分支或者重置了当前分支,git reflog 依然能显示这些操作的历史。

常见导致 git log 看不到提交的原因

1. git reset 操作

git reset 是一种常用的操作,用于回滚分支到某个特定的提交。它有三种模式:--soft--mixed--hard。其中,git reset --hard 不仅会回滚分支指针,还会重置工作目录。

如果你使用了 git reset --hard 回退到某个较早的提交,那么中间的提交将不再被当前分支所引用,也就是说,这些提交就 不可达 了。在 git log 中你将看不到这些提交,但 git reflog 依然记录了它们。

示例:

bash 复制代码
git reset --hard HEAD~3  # 回滚到3个提交之前

在执行这个操作后,最近的 3 次提交虽然丢失了,但可以通过 git reflog 找回。

2. git rebase 操作

git rebase 是一个用于重写提交历史的操作,它会将提交重新应用到新的基点上。过程中,原有的提交会被替换为新的提交,这样就导致了原来的提交从分支历史中"消失"。

即使 git log 不再显示这些被替换的提交,它们仍然会保留在 git reflog 中,直到这些提交被垃圾回收(GC)。

3. 分支删除

当你删除一个分支时,该分支上最后的提交不再被任何引用指向,导致这些提交成为"悬空"提交(dangling commit)。这些提交虽然无法在 git log 中看到,但在 git reflog 中,分支的删除和之前的提交历史仍然可以被追踪。

示例:

bash 复制代码
git branch -d feature_branch

删除 feature_branch 后,你不能再通过 git log 看到该分支的提交记录,但 git reflog 仍然会记录你删除该分支的操作。

4. git commit --amend

使用 git commit --amend 修改最近一次提交时,实际上会创建一个新的提交,原来的提交被替换掉。git log 只能显示修改后的提交,而 git reflog 可以看到原始提交及修改过程。

5. 垃圾回收(GC)*

Git 的垃圾回收机制(git gc)会清理那些没有被引用且过期的对象。当一个提交没有任何分支、标签等引用指向它时,经过一段时间后,这些提交可能会被垃圾回收从 Git 数据库中删除。不过在被 GC 删除之前,git reflog 仍然能看到这些提交。

如何恢复 git log 看不到的提交?

如果你在 git log 中看不到某个提交,但它在 git reflog 中依然存在,你可以通过以下方法恢复这些提交:

  1. 使用 git reset 恢复到某个提交

    • git reflog 中找到想要恢复的提交哈希值。
    • 然后使用 git resetgit checkout 恢复。

    例如:

    bash 复制代码
    git reflog
    # 找到需要恢复的提交,假设是 abc1234
    git reset --hard abc1234
  2. 创建一个新的分支指向该提交

    如果你不想影响当前的分支,可以创建一个新的分支指向丢失的提交:

    bash 复制代码
    git branch recovered-branch abc1234

    这样你就能在新的分支上查看并操作该提交的历史。

总结

  • git log 只显示当前分支上的 可达提交,即有分支或标签引用的提交。
  • git reflog 记录了所有本地引用(如 HEAD)的变化,能够显示 git log 看不到的提交,尤其是那些通过 resetrebase、分支删除等操作被"丢失"的提交。
  • 可以通过 git reflog 找到丢失的提交,并通过 git reset 或创建新分支来恢复这些提交。

git reflog 是一个非常有用的工具,特别是在你需要恢复意外丢失的提交时。


结束语

Flutter是一个由Google开发的开源UI工具包,它可以让您在不同平台上创建高质量、美观的应用程序,而无需编写大量平台特定的代码。我将学习和深入研究Flutter的方方面面。从基础知识到高级技巧,从UI设计到性能优化,欢饮关注一起讨论学习,共同进入Flutter的精彩世界!

相关推荐
weixin-a153003083161 小时前
git常用命令
git
前端小干将3 小时前
开发过程中,git常用命令
git
西柚啊4 小时前
Git常用命令总结
前端·git
云梦谭5 小时前
Git 配置 GPG 提交签名
git·gpg
李艺为8 小时前
Ubuntu下展锐刷机工具spd_dump使用说明
android·linux·git·ubuntu
掘根14 小时前
Git分支管理
git
极小狐14 小时前
极狐GitLab 项目 API 的速率限制如何设置?
大数据·运维·git·elasticsearch·gitlab
残月只会敲键盘15 小时前
Git 命令速查手册
大数据·git·elasticsearch
掘金沸点顶流16 小时前
同一台电脑配置多个 git 账户(github, gitee, gitlab等)
git
苦逼IT运维20 小时前
Git LFS 学习笔记:原理、配置、实践与心路历程
笔记·git·学习