git rebase -i 并不可怕

Lobsters Hottest 工具

摘要

解释 git 中的交互式变基命令,揭示其功能并强调通过中止和 reflog 的安全性。

<p><a href="https://lobste.rs/s/uawqly/git_rebase_i_is_not_scary">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/07/24 19:05

# git rebase -i 没那么可怕 — akrm al-hakimi Source: https://cachebag.sh/journal/interactive-rebasing/ 我早期作为初级开发人员遇到的最令人震惊的事情之一,就是对 `git rebase -i` 的恐惧。 即使在我的一些同事中(他们在很多方面都比我聪明得多),许多开发人员似乎也都害怕这个命令。 ## 它实际上做了什么 当你运行: ``` git rebase -i HEAD~4 ``` git 做了一件令人愉快的平凡事:它打开一个文本文件。如果你在终端中工作,并且没有摆弄过你的 git 设置,`git config --global core.editor "_YOUR-EDITOR_"` 是一个消除你对征服 vim 的恐惧的好方法。(https://www.justfuckinguseneovim.com/) ``` pick a1b2c3d Add user model pick e4f5g6h Fix typo in user model pick i7j8k9l Add login endpoint pick m0n1o2p WIP debugging login # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # s, squash = use commit, but meld into previous commit # f, fixup = like "squash" but discard this commit's message # d, drop = remove commit ``` 对于新手 rebase 来说,有一点值得注意:这是一个 *计划*,而不是一个动作。技术上还没有发生任何事情,只不过 rebase 已经开始。如果你改变主意,只需运行 `git rebase --abort`,然后重新开始或放弃(理想情况下是前者)。 每一行都是一个指令,其中会开始重放你针对的提交。你可以根据自己的喜好转混合搭配这些指令。 ``` r a1b2c3d Add user model pick e4f5g6h Fix typo in user model pick i7j8k9l Add login endpoint d m0n1o2p WIP debugging login # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # s, squash = use commit, but meld into previous commit # f, fixup = like "squash" but discard this commit's message # d, drop = remove commit ``` 这里发生了什么: 1. 在这个例子中,git 会在第一个提交上'暂停',允许你重新编辑它的消息。 2. `d` 或 `drop` 完全删除 WIP 调试提交。也可以通过直接删除整行来达到相同效果。 中间的两个提交没有受到影响,尽管我们修改了周围的提交。最终结果是 3 个提交而不是 4 个。 老实说,就这样。这没什么大不了的。如果你能内化这个例子所做的,交互式变基就会成为一个让你的生活更轻松、而不是更困难工具。 还有一种常见的人,喜欢贬低交互式变基的目的。不深入那些争论,我只想公开说:在我看来,如果你不关心清晰的分支历史(变基提供的一小部分改进),那么我更倾向于怀疑你对软件重视程度。 ## "但如果我搞砸了怎么办?" 实际上很难丢失工作,有三个原因。 **你可以随时退出。** 如上所述,使用 `git rebase --abort`,你的分支会瞬间回到开始之前的状态。 **变基不会销毁提交——它会创建新的提交。** 这是关键的心智模型。变基不会编辑你的旧提交;它会创建新的提交,只是将你的分支指针移动到它们上面。旧提交仍然存在于 git 的对象数据库中,未被引用但完好无损(https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery#_git_gc),在垃圾回收之前会保存一段时间。 **引用日志会记住一切。** 这对我来说尤其重要,在我第一次实习时擦了一个同事的分支历史,我以为他们想删除之前所做的提交。git 会记录你的分支指向过的所有位置: ``` git reflog ``` 找到变基之前的条目并恢复: ``` git reset --hard HEAD@{4} ``` 整个变基操作被撤销。这个安全网始终存在,这意味着一次失败变基的最坏现实结果是花几分钟翻阅引用日志。 即使引用日志也令人生畏(尽管如果你已经看到了我的这篇文章,我希望你有足够的能力处理它),当然,还有低技术保险策略: ``` git branch backup-before-rebase ``` 现在变基前的状态有了一个名字。如果出了问题,`git reset --hard backup-before-rebase`,你就安全了。 ## 冲突 有时重放的提交会与较早的更改冲突(通常在重新排序,或变基到更新的主分支时)。git 停止并直接打印指令:像解决合并冲突一样解决冲突,`git add` 文件,然后 `git rebase --continue`。 我认为这可能最让人烦恼。但冲突对 git 来说并不是新概念。事实上,我认为在交互式变基的上下文中,冲突实际上比合并更容易解决。这是因为你一次只处理一个提交,而不是整个分支。 ## 必要的警告 就像软件中的任何事情一样,你应该非常小心并努力理解你在做什么,尤其是像变基这样具有破坏性的事情。是的,工作可以恢复,但这并不能成为你草率的借口。 我遵循的一个很好的一般经验法则是,在审查之前或期间,允许自己自由地变基自己的特性分支。使用 `git push --force-with-lease` 将结果推送到你自己的远程分支是正常且良好的(`--force-with-lease` 如果在此期间有人推送了其他内容,则拒绝推送,始终优先于简单的 `--force`)。 ## 结论 我个人认为,任何称职的开发人员至少应该能够完成一个非常简单的交互式变基。这篇文章并不是关于何时或为什么应该使用它(尽管我相信应该广泛使用),它主要是为了揭开这个过程的神秘面纱,并鼓励你尝试一下。*特别是如果你是一名初级/新手开发者。*

相似文章

Git history 命令值得更多关注

Hacker News Top

文章重点介绍了新的 `git history` 命令及其 `fixup`、`reword` 和 `split` 子命令,这些命令提供了原子化且感知分支的提交历史编辑功能,带来了类似 jj 的益处,而无需切换版本控制系统。

接受混乱的 git 历史

Lobsters Hottest

一篇博客文章,讨论两种 git 工作流理念——频繁提交与谨慎变基——并解释为何在大型团队中,鉴于团队的韧性,混乱的历史是可以接受的,文中还提到了 GitHub 的新堆叠 PR 功能。

@laogui: 经过几天使用,我可以毫不夸张地说:Rebased 就是目前最强的 Git 图形化客户端。 用过 JetBrains 系列 IDE 的朋友都知道,它的 Git 功能体验非常好——尤其是 Diff 功能。但这几年 JetBrains 在 AI…

X AI KOLs Timeline

Rebased 是一款基于 JetBrains IntelliJ 社区版构建的开源 Git 图形化客户端,砍掉了所有语言相关功能,只保留并优化了 Git 工具,提供了顶级的 Diff、Review、交互式 Rebase 和冲突解决体验,免费使用且零学习成本。

快速重写Git仓库历史

Hacker News Top

git-filter-repo 是一个用于重写 Git 仓库历史的多功能工具,被 Git 项目推荐为比 git filter-branch 更快、功能更强大的替代方案。