手册页说log显示提交日志,reflog管理reflog信息。究竟什么是reflog信息,它有什么日志没有的?日志似乎更详细。


当前回答

Git日志显示了从refs(头,标签,远程)访问的提交日志。 Git reflog记录了任何时候在你的repo中被引用或被引用的所有提交。

这就是为什么当你执行“破坏性”操作(比如删除一个分支)时使用git reflog(默认90天后修剪的本地记录),以获得该分支引用的SHA1。 参见git配置:

gc.reflogexpire
gc.<pattern>.reflogexpire

Git reflog expire删除比这个时间更老的reflog条目;默认为90天。 “<模式>”(例如:"refs/stash"),该设置只适用于匹配<pattern>的引用。

Git reflog通常被称为“您的安全网”

以防万一,一般的建议,当git日志没有显示你要找的东西时,是:

“保持冷静,使用git reflog”

同样,reflog是SHA1的本地记录。 与git日志相反:如果你将你的回购推到上游的回购,你会看到相同的git日志,但不一定是相同的git reflog。

其他回答

我喜欢把git log和reflog之间的区别看作是私有记录和公共记录之间的区别。

私人vs公共

使用git reflog,它会跟踪您在本地所做的所有事情。你答应了吗?Reflog跟踪它。你硬复位了吗?Reflog跟踪它。你修改commit了吗?Reflog跟踪它。你在本地做的所有事情,在reflog中都有一个条目。

这对对数来说不成立。如果修改了提交,日志只显示新的提交。如果您执行重置并回跳历史记录中的一些提交,那么您跳过的那些提交将不会显示在日志中。当您将更改推送给另一个开发人员或GitHub或类似的东西时,只会显示日志中跟踪的内容。对于另一个开发人员来说,这看起来就像从未发生过重置或修正。

圆木经过打磨。这是一种宝石。

所以,是的,我喜欢“私人vs公共”的类比。或者一个更好的原木vs reflog类比是“抛光vs宝石”。reflog显示了你所有的尝试和错误。日志只是展示了你工作历史的一个干净的版本。

看看这张图片来强调这一点。自存储库初始化以来,发生了许多修改和重置。这一切都体现在重新发行上。然而,log命令使它看起来好像只有一次针对repo的提交:

回到“安全网”的概念

此外,由于reflog会跟踪你修改过的东西并提交你重置的东西,它允许你返回并找到那些提交,因为它会给你提交id。假设您的存储库没有清除旧提交,这允许您复活日志中不再可见的项。这就是为什么当人们需要拿回他们认为自己无意中丢失的东西时,reflog有时会拯救他们的皮肤。

git日志显示当前HEAD和它的祖先。也就是说,它打印HEAD指向的提交对象,然后是它的父对象,它的父对象,等等。它通过递归查找每个提交的父节点,遍历回购的祖先节点。

(在实践中,一些提交有多个父文件。要查看更有代表性的日志,可以使用git log——oneline——graph——decoration这样的命令。)

git reflog根本不遍历HEAD的祖先。reflog是HEAD所指向的一个有序的提交列表:它是你的repo的撤销历史。reflog不是repo本身的一部分(它被单独存储到提交本身),并且不包括在push、fetch或clone中;这纯粹是本地的。

另外:理解reflog意味着一旦repo被提交,就不会真正丢失数据。如果你不小心重置到旧的提交,或者错误地重设基准,或者任何其他视觉上“删除”提交的操作,你可以使用reflog来查看之前的位置,然后git重置——硬回到那个引用来恢复之前的状态。记住,引用不仅意味着提交,还意味着它背后的整个历史。

Git日志显示了从refs(头,标签,远程)访问的提交日志。 Git reflog记录了任何时候在你的repo中被引用或被引用的所有提交。

这就是为什么当你执行“破坏性”操作(比如删除一个分支)时使用git reflog(默认90天后修剪的本地记录),以获得该分支引用的SHA1。 参见git配置:

gc.reflogexpire
gc.<pattern>.reflogexpire

Git reflog expire删除比这个时间更老的reflog条目;默认为90天。 “<模式>”(例如:"refs/stash"),该设置只适用于匹配<pattern>的引用。

Git reflog通常被称为“您的安全网”

以防万一,一般的建议,当git日志没有显示你要找的东西时,是:

“保持冷静,使用git reflog”

同样,reflog是SHA1的本地记录。 与git日志相反:如果你将你的回购推到上游的回购,你会看到相同的git日志,但不一定是相同的git reflog。

实际上,reflog是

 git log -g --abbrev-commit --pretty=oneline

所以答案应该是:这是一个具体的情况。

git日志将从当前HEAD开始,即指向某个分支(如master)或直接指向提交对象(sha代码),并在提交后使用每个提交对象中的父字段实际扫描.git/objects目录中的对象文件。

实验:将HEAD直接指向一些commit: git checkout a721d(创建新的repo并用提交和分支填充它。用一些提交代码替换a721d)并删除rm .git/refs/heads/*分支 现在git log——oneline将只显示HEAD及其提交的祖先。

另一方面,Git reflog使用在.git/logs中创建的直接日志

实验:rm -rf .git/logs, git reflog为空。

不管怎样,即使你丢失了所有标签、所有分支和logs文件夹中的所有日志,提交对象仍然在.git/objects目录中,所以如果你发现所有悬挂的提交,你可以重建树:git fsck