【Git】Git 骚操作:`rebase`, `cherry-pick` 和 `reflog` 让你成为团队高手

【Git】Git 骚操作:rebase, cherry-pickreflog 让你成为团队高手

所属专栏: 《前端小技巧集合:让你的代码更优雅高效》
上一篇: 【工程化】包管理也内卷?pnpm, npm, yarn 的小技巧与最佳实践
作者: 码力无边


引言:你的 Git 历史,是一本“天书”,还是一部“史诗”?

嘿,各位在代码时间线中穿梭的道友们,我是码力无边

在我们的前端开发江湖中,Git 就像是我们每个人都必须掌握的“时空穿梭机”。git add, git commit, git push, git pull 这“四件套”,是我们每天都在念诵的“基础咒语”,它们能带我们完成最基本的代码同步和版本记录。

但是,当团队协作变得复杂,当项目的历史开始交错,你的“时空之旅”是否也曾陷入混乱?

  • 你的 git log 是不是充满了各种 Merge branch 'develop' into feature/xxx 这样的“噪音”,让代码的演进历史变得难以追溯?
  • 你是否曾想过,只把另一个分支上的某一个“神之一手”的提交,精准地“移植”到当前分支,却只能无奈地手动复制粘贴代码?
  • 你是否曾因为一次错误的 reset --hardrebase 操作,眼睁睁看着自己辛辛苦苦写的代码消失在“时间的虚空”中,然后抱着头不知所措?

如果这些场景让你感同身受,那说明你的“时空穿梭机”还停留在“手动挡”模式。是时候升级你的驾驶技巧,学习几招能让你“操控时间线”的“骚操作”了。

今天,码力无边就要传授你三招 Git 的上乘心法,它们分别是:

  • git rebase: 变基——让你的提交历史变得像一条直线一样清晰的“整容术”。
  • git cherry-pick: 摘樱桃——精准“采摘”任意提交的“隔空取物”神技。
  • git reflog: 引用日志——你的 Git “后悔药”,能带你找回几乎所有“丢失”的提交。

掌握它们,你将从一个只会“保存进度”的 Git 使用者,蜕变成一个能够精心雕琢提交历史、从容应对各种复杂协作场景的 Git 高手。你的 Git 历史,将不再是一本无人能懂的“天书”,而是一部清晰、优雅、可歌可泣的“开发史诗”。

一、git rebase:让你的提交历史“整洁如新”

rebase(变基)和 merge 是合并分支的两种不同方式。它们的目的相同,但实现的过程和最终形成的历史记录却截然不同。

git merge:忠实的历史记录员
merge 会创建一个新的“合并提交”(merge commit),它有两个父节点,分别指向被合并的两个分支的末端。它忠实地记录了“在某个时间点,我们把 B 分支合入了 A 分支”这个事实。
git merge
优点:保留了最真实、最完整的历史信息。
缺点:当团队频繁地合并功能分支时,提交历史会变得像一张复杂的蜘蛛网,充满了分叉和合并节点,难以阅读。

git rebase:优雅的历史小说家
rebase 则会“重写历史”。它的核心思想是:找到两个分支的共同祖先,然后把你当前分支上独有的提交,像“嫁接”一样,一个个地“重新播放”到目标分支的最新提交之后。

场景: 你从 develop 分支切出了一个 feature/login 分支进行开发。在你开发期间,develop 分支上又有了新的提交。现在你想把 develop 的最新进展同步到你的功能分支。

使用 merge 的操作:

git checkout feature/login
git merge develop # 会产生一个合并提交 "Merge branch 'develop' into feature/login"

历史线图会多一个分叉和合并点。

使用 rebase 的操作:

git checkout feature/login
git rebase develop # 见证奇迹的时刻

发生了什么?
rebase 会:

  1. 暂时“收起”你在 feature/login 上的所有提交(比如 C4, C5)。
  2. feature/login 分支的指针移动到 develop 分支的最新提交(C3)上。
  3. 然后,把你刚才“收起”的提交(C4, C5),以全新的提交 ID(C4’, C5’),依次应用在新的基点(C3)之后。

最终,你的 feature/login 分支看起来就像是直接从最新的 develop 分支上拉出来的一样,整个提交历史变成了一条干净的直线!

交互式变基:git rebase -i

rebase 最强大的地方在于它的交互模式 rebase -i (interactive)。它能让你在“重新播放”提交之前,对这些提交进行精细的“编辑”。

# 假设你想整理你最近的 3 个提交
git rebase -i HEAD~3

执行后,Git 会打开一个编辑器,列出这 3 个提交,每个提交前都有一个 pick 关键字。你可以修改这个关键字来执行不同的操作:

  • pick: 保留该提交(默认)。
  • reword (或 r): 保留该提交,但修改提交信息。
  • edit (或 e): 保留该提交,但 rebase 会在该提交处暂停,让你有机会修改代码内容。
  • squash (或 s): 将该提交合并到它的前一个提交中,并让你重新编辑合并后的提交信息。
  • fixup (或 f): 同 squash,但直接丢弃该提交的提交信息。
  • drop (或 d): 直接删除该提交。
    你还可以拖动行的顺序来调整提交的顺序!

黄金法则:永远不要在已经推送到远程的公共分支(如 main, develop)上执行 rebase
因为 rebase 会重写历史,改变提交 ID。如果你在一个多人协作的分支上这么做,会给其他已经拉取了旧历史的团队成员造成巨大的混乱。rebase 主要用于整理你自己的、还未推送或只影响你个人的功能分支。

二、git cherry-pick:精准的“外科手术”

cherry-pick (摘樱桃) 是一个非常有用的命令,它允许你选择任意分支上的一个或多个提交,并将它们作为新的提交,“复制”到你当前所在的分支上。

场景:

  • Bug 修复:你在 feature/A 分支上修复了一个紧急的 bug(提交 commit-A),但这个 bug 同时也存在于 release 分支上。你不想将整个 feature/A 分支合并到 release,你只需要那个修复 bug 的 commit-A
  • 功能复用:你在 feature/B 分支上写了一个非常通用的工具函数(提交 commit-B),现在 feature/C 分支也需要这个函数,但 B 和 C 的功能完全不相关。

操作方法:

  1. 首先,找到你想要“采摘”的那个提交的 SHA-1 哈希值(可以通过 git log 查看)。
    # 在 feature/A 分支上
    git log
    # commit a1b2c3d4... (这是修复 bug 的提交)
    # Author: 码力无边
    # Date: ...
    #
    # fix: 修复了一个严重的 bug
    
  2. 然后,切换到你的目标分支,执行 cherry-pick
    git checkout release
    git cherry-pick a1b2c3d4
    
    完成!commit-A 的所有代码变更,现在已经被应用到了 release 分支上,并生成了一个新的提交(拥有新的 SHA-1 值)。

你也可以同时“采摘”多个提交:

git cherry-pick commit-A commit-B commit-C

或者一个连续的提交范围:

# 采摘从 commit-A (不含) 到 commit-C (含) 的所有提交
git cherry-pick commit-A..commit-C

cherry-pick 就像一个精准的外科医生,能让你在复杂的分支网络中,精确地提取和复用代码变更,而无需进行笨重的分支合并。

三、git reflog:你的“时光倒流”护身符

reflog (Reference Log,引用日志) 是 Git 的一个“隐藏”机制,但它却是你最重要的安全网。Git 会在本地仓库中,默默地记录下你的 HEAD 指针和分支指针每一次移动的历史。

git log 记录的是项目的提交历史,它是项目的一部分,会被推送到远程。而 git reflog 记录的是你本地的操作历史,它只存在于你自己的电脑上。

场景: 你搞砸了一次 rebase,或者不小心执行了 git reset --hard HEAD~5,删掉了最近 5 个还未推送的提交。你以为你的代码永远消失了,内心一片恐慌。

reflog 来拯救你!
在你的终端里,立刻输入:

git reflog

你会看到一个类似这样的列表:

a1b2c3d HEAD@{0}: reset: moving to HEAD~5
f9e8d7c HEAD@{1}: rebase (finish): returning to refs/heads/my-feature
f9e8d7c HEAD@{2}: rebase (squash): Squashed commit
...
e4d5f6g HEAD@{5}: commit: 添加了新功能
...

这个列表,就是你的“时空穿梭机”的操作记录!它记录了你每一次 commit, rebase, reset, merge, checkout 等操作。

每一行最左边的 a1b2c3d 就是那次操作之后 HEAD 指向的提交 ID。HEAD@{n} 表示 HEADn 次操作前的位置。

如何恢复?

  1. reflog 中找到你误操作之前的那个状态。比如,e4d5f6g HEAD@{5} 是你执行 reset 之前的最后一个正确提交。
  2. 使用 git reset 强制将你的分支指针移回到那个“正确的时空坐标”:
    # 强制将当前分支恢复到 e4d5f6g 这个提交的状态
    git reset --hard e4d5f6g
    
    或者,如果你想更保险一点,可以先创建一个新分支来查看:
    git checkout -b recovered-branch e4d5f6g
    

就是这么简单!reflog 就像是 Git 的“黑匣子”,为你保留了最后的希望。只要提交曾经在你的本地仓库中存在过,reflog 大概率就能帮你找回来(默认会保留 90 天)。

写在最后:工具塑造思维,思维升华工具

rebase, cherry-pick, reflog,这些命令初看起来可能比 mergecommit 要复杂。但它们所代表的,是一种更主动、更精细地管理代码历史的思维方式。

  • rebase 教会我们追求清晰的叙事线,让代码历史服务于未来的读者。
  • cherry-pick 教会我们模块化地思考变更,将每一个提交都视为一个可独立应用的“补丁”。
  • reflog 则给了我们敢于尝试的底气,让我们在探索高级功能时,总有一条安全的退路。

熟练掌握这些“骚操作”,并理解它们背后的设计哲学,将让你在团队协作中游刃有余。你不仅能提交功能,更能贡献出一段清晰、健壮、易于维护的“开发史诗”。而这,正是一位优秀工程师的核心价值所在。


专栏预告与互动:

我们已经掌握了 Git 的高级技巧。接下来,让我们回归到代码本身。在现代前端开发中,TypeScript 已经成为了事实上的标准。它强大的类型系统能帮助我们构建更大型、更可靠的应用。

下一篇,我们将深入 TypeScript 的世界,从最实用的工具类型(Utility Types)开始,看看如何用 Partial, Pick, Omit 等工具,轻松地对现有类型进行“变形”,实现灵活的类型编程!

感觉码力无边的 Git“骚操作”让你大开眼界?别忘了点赞、收藏、关注,你的每一次支持,都是我挖掘更多“独门秘籍”的强大动力!

今日论道: 在你的团队中,是更推崇使用 git merge 还是 git rebase 来合并功能分支?这两种策略分别对团队的工作流和代码审查(Code Review)有什么不同的影响?在评论区分享你团队的实践和见解,我们一起探讨!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码力无边-OEC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值