【发布时间】:2013-07-25 07:53:15
【问题描述】:
手册页说 log 显示提交日志,而 reflog 管理 reflog 信息。 reflog 信息到底是什么,日志没有什么?日志似乎要详细得多。
【问题讨论】:
标签: git git-log git-reflog
手册页说 log 显示提交日志,而 reflog 管理 reflog 信息。 reflog 信息到底是什么,日志没有什么?日志似乎要详细得多。
【问题讨论】:
标签: git git-log git-reflog
git log 显示当前的 HEAD 及其祖先。也就是说,它会打印 HEAD 指向的提交,然后打印其父级、父级等。它通过递归查找每个提交的父级来遍历 repo 的祖先。
(实际上,一些提交有多个父级。要查看更具代表性的日志,请使用git log --oneline --graph --decorate 之类的命令。)
git reflog 根本没有遍历 HEAD 的祖先。 reflog 是 HEAD 指向的提交的有序列表:它是您的 repo 的撤消历史记录。 reflog 不是 repo 本身的一部分(它与提交本身分开存储)并且不包含在推送、获取或克隆中;这纯粹是本地的。
除此之外:理解 reflog 意味着一旦提交,您就不会真正丢失 repo 中的数据。如果您不小心重置为较旧的提交,或错误地重新设置基准,或任何其他在视觉上“删除”提交的操作,您可以使用 reflog 查看您之前的位置,然后git reset --hard 回到该 ref 以恢复您之前的状态。请记住,refs 不仅意味着提交,还意味着它背后的整个历史。
【讨论】:
.git/logs/refs/<branch> 条目的格式为 <old_rev> <new_rev> [...] <timestamp> [...]。您可以尝试按时间戳连接和排序。但是,某些行的new_rev 可能与下一行的old_rev 不匹配,在这种情况下,我怀疑引用日志将无效。然后,您可以尝试插入虚假条目来“修复”序列,但这对我来说似乎太麻烦了。
git log 显示可从 refs(heads、tags、remote)访问的提交日志git reflog 是您的存储库中随时引用或曾经引用的所有提交的记录。这就是为什么在您执行“破坏性”操作(如删除分支)时使用git reflog(默认情况下在 90 天后修剪的 本地 记录),以便获得返回该分支引用的 SHA1。
见git config:
gc.reflogexpire
gc.<pattern>.reflogexpire
git reflogexpire 删除早于这个时间的 reflog 条目;默认为 90 天。
在中间使用“<pattern>”(例如“refs/stash”)时,该设置仅适用于与<pattern>匹配的引用。
git reflog 通常被称为“your safety net”
如果遇到麻烦,一般建议是:当 git log 没有显示您要查找的内容时:
同样,reflog 是您的 SHA1 的本地记录。
与git log 不同:如果你将你的repo 推送到upstream repo,你会看到相同的git log,但不一定是相同的git reflog。
【讨论】:
这是explanation of reflog from the Pro Git book:
Git 在您工作时在后台做的一件事是保留一个 reflog — 记录您的 HEAD 和分支引用在过去几个月中的位置。
你可以使用
git reflog查看你的reflog:$ git reflog 734713b... HEAD@{0}: commit: fixed refs handling, added gc auto, updated d921970... HEAD@{1}: merge phedders/rdocs: Merge made by recursive. 1c002dd... HEAD@{2}: commit: added some blame and merge stuff 1c36188... HEAD@{3}: rebase -i (squash): updating HEAD 95df984... HEAD@{4}: commit: # This is a combination of two commits. 1c36188... HEAD@{5}: rebase -i (squash): updating HEAD 7e05da5... HEAD@{6}: rebase -i (pick): updating HEAD每当您的分支提示因任何原因而更新时,Git 都会在此临时历史记录中为您存储该信息。您也可以使用此数据指定较旧的提交。
reflog 命令也可用于从 reflog 中删除太旧的条目或使条目过期。来自official Linux Kernel Git documentation for reflog:
子命令
expire用于修剪旧的 reflog 条目。要从 reflog 中删除单个条目,请使用子命令
delete并指定确切的条目(例如git reflog delete master@{2})。
【讨论】:
git log 不是为您提供相同的信息吗?抱歉,如果这看起来很明显,我对 GIT 很陌生,想在我的第一个 OMG 之前获得一些基础知识。
HEAD 指针)的记录,以及它们已经提交的指着。那有意义吗?附带说明一下,log 也可以向您显示 reflog 信息,但您必须将一个特殊的选项标志作为参数传递给它,--walk-reflogs。
我也很好奇这个,只是想详细说明和总结一下:
git log 显示您所在分支的所有提交的历史记录。签出一个不同的分支,你会看到不同的提交历史。如果您想查看所有分支的提交历史记录,请输入 git log --all。
git reflog 显示您的参考记录,正如 Cupcake 所说。每次提交或签出时都会有一个条目。尝试使用git checkout 在两个分支之间来回切换几次,并在每次结帐后运行git reflog。您会看到每次更新的顶部条目作为“结帐”条目。您在 git log 中看不到这些类型的条目。
参考资料: http://www.lornajane.net/posts/2014/git-log-all-branches
【讨论】:
我喜欢将 git log 和 reflog 之间的区别视为私人记录和公共记录之间的区别。
使用 git reflog,它可以跟踪您在本地所做的一切。你答应了吗? Reflog 跟踪它。你做了硬重置吗? Reflog 跟踪它。你amend a commit了吗? Reflog 跟踪它。您在本地完成的所有操作,在 reflog 中都有相应的条目。
这不适用于日志。如果你修改了一个提交,日志只显示新的提交。如果您进行重置并跳过历史记录中的一些提交,那么您跳过的那些提交将不会显示在日志中。当您将更改推送给其他开发人员或GitHub 或类似的东西时,只会显示日志中跟踪的内容。对另一位开发人员来说,重置似乎从未发生过,或者修改从未发生过。
是的,我喜欢“私人与公共”的类比。或者也许更好的log vs reflog 类比是“抛光与宝石”。 reflog 显示了您所有的试验和错误。该日志仅显示您的工作历史的干净和完善的版本。
看一下这张图片以强调这一点。自存储库初始化以来,已经发生了许多修改和重置。 reflog 显示了所有这些。然而,日志命令使它看起来好像只有一次针对 repo 的提交:
此外,由于 reflog 会跟踪您修改的内容并提交您reset,它允许您返回并找到这些提交,因为它会为您提供提交 ID。假设您的存储库尚未清除旧提交,这允许您恢复日志中不再可见的项目。这就是当某人需要找回他们认为无意中丢失的东西时,reflog 有时最终会挽救他们的皮肤的方式。
【讨论】:
git log将从当前HEAD开始,即指向某个分支(如master)或直接提交对象(sha代码),并实际扫描.git/objects 目录中的对象文件在提交后使用每个提交对象中存在的 parent 字段提交。
实验:将 HEAD 直接指向某个提交:git checkout a721d(创建新的 repo 并用提交和分支填充它。用你的一些提交代码替换 a721d)并删除分支 rm .git/refs/heads/*
现在git log --oneline 将只显示 HEAD 及其提交祖先。
另一方面,git reflog 使用的是在 .git/logs
中创建的直接日志实验:rm -rf .git/logs 和 git reflog 为空。
无论如何,即使您丢失了日志文件夹中的所有标签、所有分支和所有日志,提交对象也在 .git/objects 目录中,因此如果您发现所有悬空提交,您可以重建树:git fsck
【讨论】:
其实reflog是一个别名
git log -g --abbrev-commit --pretty=oneline
所以答案应该是:这是一个特定的案例。
【讨论】:
git log 中,-g 是--walk-reflogs 的缩写形式。所以,这并不能解释什么。