共计 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 log
和git reflog
之间的区别,并展现如何应用 reflog 来复原已删除的提交和已删除的分支。
Git 进阶系列:
- 创立完满的提交
- Git 中的分支策略
- 基于 Pull Request 实现更好的合作
- 合并抵触
- Rebase vs Merge
- 交互式 Rebase
- Git 中的 Cherry-pick 提交
- 用 Reflog 复原失落的提交(本文)
git log
和 git 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/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,能够简略的按下 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 多平台公布