关于程序员:Git进阶系列-8-用Reflog恢复丢失的提交

30次阅读

共计 3147 个字符,预计需要花费 8 分钟才能阅读完成。

Git 是最风行的代码版本控制系统,这一系列文章介绍了一些 Git 的高阶应用形式,从而帮忙咱们能够更好的利用 Git 的能力。本系列一共 8 篇文章,这是最初一篇。原文:Using the Reflog to Restore Lost Commits[1]

“Reflog”是 Git 不太为人所知的个性之一,但可能十分有用。有些人把它称为“安全网”,而我喜爱把它看作 Git 的“日记”,因为 Git 用它来记录 HEAD 指针的每次挪动(例如,每次提交、合并、rebase、cherry-pick、reset 等)。Git 会将操作记录在 Reflog 中,使它成为一个有价值的日志,当呈现问题时,这是一个很好的终点。

在“Git 进阶”系列的最初一部分,我将解释 git loggit reflog之间的区别,并展现如何应用 reflog 来复原已删除的提交和已删除的分支。

Git 进阶系列:

  1. 创立完满的提交
  2. Git 中的分支策略
  3. 基于 Pull Request 实现更好的合作
  4. 合并抵触
  5. Rebase vs Merge
  6. 交互式 Rebase
  7. Git 中的 Cherry-pick 提交
  8. 用 Reflog 复原失落的提交(本文)

git loggit reflog 有什么区别?

在之前的文章中,我倡议应用 git log 命令查看事件并查看提交历史,这正是它的工作。它能够显示以后的 HEAD 及其先人,即父提交,下一个父提交,等等。git log通过递归打印每个提交的父节点来回溯提交历史,这是代码库的一部分,这意味着在 push、fetch、pull 之后这些信息都会被复制。

另一方面,git reflog是一个公有的、与工作空间相干的记录。它不遍历先人列表。相同,它显示一个有序列表,蕴含 HEAD 过来所指向的所有提交。这就是为什么能够把它看作某种“撤销历史(undo history)”,就像在文字处理器、文本编辑器等中看到的那样。

技术上来说,这个本地记录不是代码库的一部分,它与提交离开存储。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 中的提交历史:

咱们想要删除两个提交,并将“Change headlines for about and imprint”提交 (ID: 2b504bee) 作为 master 分支上的最初一个批改。咱们须要做的就是将哈希 ID 复制到剪贴板,而后在命令行中应用 git reset 并输出哈希:

$ git reset --hard 2b504bee

瞧。提交曾经隐没。当初,咱们假如这是一个谬误,并查看 Reflog 来复原失落的数据。在终端中输出 git reflog 查看日志:

有没有留神到所有条目都是按工夫顺序排列的,这意味着顶部是最近的(也就是最新的)提交。如果认真看,会留神到几分钟前致命的 git reset 操作就在顶部。

日记仿佛起作用了,这是个好消息。因而,咱们用它来撤销最初一个操作,并在执行 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/loginmaster的切换。咱们尝试返回到之前的状态,将哈希 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,能够简略的按下 CMD+Z 来撤销最初一个操作,就像文本编辑器或文字处理器一样。

放弃沉着,保障记录

Git 的 Reflog 能够成为真正的救星!如你所见,很容易将失落的提交甚至整个分支从坟墓中带回来,只须要在 reflog 中找到正确的哈希 ID,其余都是小菜一碟。

如果想更深刻理解高级 Git 工具,能够收费查看“Advanced Git Kit[3]”: 这是对于分支策略、交互式 Rebase、Reflog、子模块等主题的短视频汇合。

本文是“Git 进阶”系列的最初一部分,心愿你喜爱这些文章。编码高兴!

References: \
[1] Using the Reflog to Restore Lost Commits: https://css-tricks.com/using-the-reflog-to-restore-lost-commits/

你好,我是俞凡,在 Motorola 做过研发,当初在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓重的趣味,平时喜爱浏览、思考,置信继续学习、一生成长,欢送一起交流学习。\
微信公众号:DeepNoMind

本文由 mdnice 多平台公布

正文完
 0