本文是“高级 Git”系列的一部分。请务必关注我们的 Twitter 或注册我们的新闻通讯,以便了解未来的文章!
Git 的“Reflog”功能鲜为人知,但却非常实用。有些人称之为“安全网”,而我更喜欢将其视为 Git 的“日记”。这是因为 Git 使用它来记录 HEAD 指针的每一次移动(即每次提交、合并、变基、挑选、重置等)。Git 会将您的操作记录在 Reflog 中,这使其成为宝贵的日志簿,也是出现问题时的良好起点。
在本“高级 Git”系列的最后一部分,我将解释 git log
和 git reflog
之间的区别,并向您展示如何使用 Reflog 恢复已删除的提交和已删除的分支。
git log
或 git reflog
:有什么区别?在之前的文章中,我建议您使用 git log
命令检查之前的事件并查看您的提交历史记录,这就是它的确切作用。它显示当前 HEAD 及其祖先,即其父级、下一父级等等。日志通过递归打印每个提交的父级一直追溯到提交历史记录的开头。它是存储库的一部分,这意味着在您推送、获取或拉取后它会被复制。
另一方面,git reflog
是私有的与工作区相关的记录。它不会遍历祖先列表。相反,它显示 HEAD 在过去指向的所有提交的有序列表。这就是为什么您可以将其视为某种“撤消历史记录”,就像您在文字处理器、文本编辑器等中看到的那样。
此本地记录在技术上不是存储库的一部分,它与提交分开存储。Reflog 是 .git/logs/refs/heads/
中的一个文件,它跟踪每个分支的本地提交。Git 的日记通常会在 90 天后被清理(这是默认设置),但您可以轻松调整 Reflog 的过期日期。要将天数更改为 180,只需键入以下命令:
$ git config gc.reflogExpire 180.days.ago
或者,您可以决定您的 Reflog 永不过期:
$ git config gc.reflogExpire never
提示:请记住,Git 区分存储库的配置文件(.git/config
)、全局用户配置($HOME/.gitconfig
)和系统范围设置(/etc/gitconfig
)。要调整用户或系统的 Reflog 过期日期,请向上面显示的命令添加 --system
或 --global
参数。
足够的理论背景——让我向您展示如何使用 git reflog
来纠正错误。
想象一下以下场景:查看提交历史记录后,您决定删除最后两次提交。您勇敢地执行了 git reset
,两次提交从提交历史记录中消失了……一段时间后,您注意到这是一个错误。您刚刚丢失了宝贵的更改并开始恐慌!
您真的必须从头开始吗?不必。换句话说:保持冷静并使用 git reflog
!
因此,让我们弄乱事情并在现实生活中犯这个错误。下一张图片显示了我们在 Tower(一个图形化 Git 客户端)中的原始提交历史记录:
我们想删除两次提交,并将“更改关于和印记的标题”提交(ID:2b504bee)设为我们 master 分支上的最后一次修订。我们只需将哈希 ID 复制到剪贴板,然后在命令行中使用 git reset
并输入该哈希值:
$ git reset --hard 2b504bee
瞧!提交消失了。现在,让我们假设这是一个错误,并查看 Reflog 以恢复丢失的数据。键入 git reflog
以在您的终端中查看日记:
您会注意到所有条目都是按时间顺序排列的。这意味着:最新的提交位于顶部。而且,如果您仔细观察,您会注意到几分钟前最顶部的致命 git reset
操作。
日记似乎有效——这是个好消息。因此,让我们使用它来撤消最后一次操作并恢复重置命令之前的状态。像以前一样,将哈希 ID(在此特定示例中为 e5b19e4)复制到剪贴板。您可以再次使用 git reset
,这完全有效。但在这种情况下,我将基于旧状态创建一个新分支:
$ git branch happy-ending e5b19e4
让我们再次看看我们的图形化 Git 客户端:
如您所见,已创建名为 happy-ending 的新分支,其中包含我们之前删除的提交——太棒了,什么都没丢失!
让我们看另一个例子,并使用 Reflog 来恢复整个分支。
下一个示例类似于我们的第一个场景:我们将删除某些内容——这次是整个分支。也许您的客户或团队负责人告诉您要删除一个功能分支,也许这是您自己清理的想法。更糟糕的是,一个提交(图片中的 C3)不包含在任何其他分支中,因此您肯定要丢失数据:
让我们实际执行此操作,然后稍后恢复分支:
在您可以删除 feature/login
分支之前,您需要离开它。(如屏幕截图所示,它是当前 HEAD 分支,您不能在 Git 中删除 HEAD 分支。)因此,我们将切换分支(到 master),然后我们将删除 feature/login
:
好的……现在让我们假设我们的客户或团队负责人改变了主意。毕竟需要 feature/login
分支(包括其提交)。我们该怎么办?
让我们看看 Git 的日记:
$ git reflog 776f8ca (HEAD -> master) HEAD@{0}: checkout: moving from feature/login to master b1c249b (feature/login) HEAD@{1}: checkout: moving from master to feature/login [...]
事实证明我们再次幸运。最后一条条目显示了我们从 feature/login
切换到 master 的情况。让我们尝试返回到之前的状态,并将哈希 ID b1c249b 复制到剪贴板。接下来,我们将基于所需状态创建一个名为 feature/login
的分支:
$ git branch feature/login b1c249b $ git branch -vv feature/login b1c249b Change Imprint page title * master 776f8ca Change about title and delete error page
太好了——分支从死亡中恢复过来,还包括我们认为丢失的宝贵提交:
如果您在像 Tower 这样的桌面 GUI 中使用 Git,您可以像文本编辑器或文字处理器在您输入错误时一样,只需按 CMD Z 即可撤消您的最后一次操作。
Git 的 Reflog 可以成为真正的救星!如您所见,从坟墓中取出丢失的提交甚至整个分支非常容易。您需要做的就是在 Reflog 中找到正确的哈希 ID——其余部分是小菜一碟。
如果您想深入了解高级 Git 工具,请随时查看我的(免费!)“高级 Git 工具包”:它是一系列关于分支策略、交互式变基、Reflog、子模块等等主题的简短视频的集合。
这是我们在 CSS-Tricks 上的“高级 Git”系列的最后一部分。我希望您喜欢这些文章。快乐黑客!
以上是使用倒圈恢复丢失的投入的详细内容。更多信息请关注PHP中文网其他相关文章!