git reflog expire and git fsck --unreachable

a 夏天 提交于 2019-11-28 23:15:53

This behavior comes from an interaction between the reflog design philosophy and the requirements of garbage collection.

For a commit to be safely deleted by the garbage collector, all references to that commit must be deleted—including references in reflog entries. Despite the appearance of reflog show, each reflog entry actually contains two SHA1 identifiers: the value of the ref before the change and the value of the ref after the change. To ensure safe garbage collection, reflog expire simply deletes any entry where one of the two SHA1s identifies an unreachable commit.

In your case, the pre-change value of the most recent reflog entry refers to an unreachable commit. Even though the commit identified by the post-change value is still reachable, reflog expire deletes the entry.

This design is simple to implement and results in an incomplete but accurate log.

the --rewrite option

Unfortunately, deleting an entry that refers to a still-reachable commit has a couple of problems:

  • a gap is left in the log
  • useful information related to still-reachable commits is lost

The --rewrite option addresses these problems by changing the behavior in the following way:

  • As before, entries where the commit identified by the post-change SHA1 is unreachable are deleted.
  • Entries where the pre-change commit is unreachable are modified to bridge the gap left by the deleted entry (the pre-change SHA1 is set to the value of the previous entry's post-change SHA1).

Unfortunately, modifying the entry results in a log that no longer accurately reflects the history of the ref. For example, the change reason may no longer make sense after the rewrite. This is why --rewrite is not the default.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!