资讯动态

Git误操作急救指南:用reflog找回reset/rebase丢失的代码

发布时间:2026/10/16 3:53:00 来源:尧图企业网站定制
Git 误操作这事几乎每个人都经历过手一抖reset了分支rebase到一半发现冲突一大堆或者刚commit完就发现漏了个文件。最要命的是那一瞬间的心慌——代码好像没了连怎么恢复都不知道。其实 Git 的底层对象模型给了我们极强的保险机制大多数误操作并不是真正删除数据只是把引用指针移开了数据仍然躺在对象库里。也就是说“被删掉”的提交、分支、甚至 stash大概率能在很短的时间内救回来。这篇内容就把我这些年实际用到的急救命令和思路完整整理出来适合刚接触 Git 的初学者也适合那些对reflog还不太熟的团队骨干。从最常见的提交改错到分支被删、rebase 翻车、stash 丢失我把每个场景的完整抢救流程都写清楚你可以直接照做。1. 急救前必须建立的三个保命认知1.1 理解 reflogGit 的自救日记很多人不知道git reflog到底有什么用它可以说是 Git 误操作救援里最重要的工具没有之一。简单来说reflog记录的是 HEAD 指针和各个分支引用在过去一段时间内的每一次移动历史。你在本地执行过的commit、reset、checkout、merge、rebase、cherry-pick等操作只要让分支引用或 HEAD 发生了变化都会被记录在案。这个设计其实很像一个“操作日志”或者“后悔药清单”。默认情况下reflog 记录会保留 90 天左右也就是说只要你误操作发生在 90 天内基本都能通过 reflog 找到操作之前的那个 commit 哈希值然后用reset或checkout把分支指回去。我抢救过不少同事的代码几乎无一例外都是先用git reflog定位“出事前的位置”再恢复。核心原理在于Git 的提交对象一经创建就不可变分支指针和 HEAD 指针只是“贴在提交对象上的标签”。你执行git reset --hard把分支退到旧提交旧提交并不会从对象库消失只是“没有任何引用指向它”而已。而 reflog 恰好记录了“它曾经被引用过”这个事实所以就能顺藤摸瓜找到它。$ git reflog a1b2c3d HEAD{0}: reset: moving to a1b2c3d e4f5g6h HEAD{1}: commit: 修复登录逻辑 i6j7k8l HEAD{2}: checkout: moving from feature/login to masterHEAD{1}这种写法就是“当前 HEAD 之前第 1 次移动时的位置”。如果误操作后你发现自己把分支退回了旧版本第一步永远是git reflog而不是慌着重新写代码。$ git reflog | head -20如果平时你连 reflog 都很少看那我强烈建议从现在开始每次误操作后的第一反应就是打开它。它是你能在 30 秒内恢复代码的最大底气。1.2 三个区块的底层状态工作区、暂存区、提交历史想理解各种急救命令为什么要这么用必须先搞清楚 Git 的三个区域工作区、暂存区index和提交历史HEAD。工作区就是你本地能看到的文件内容暂存区是git add之后、git commit之前的中间缓冲区提交历史则是已经用commit固化下来的版本节点。常见的三类重置命令git reset有不同的模式对应影响不同区域命令影响工作区影响暂存区提交历史典型用途git reset --soft否否是仅移动指针撤销 commit 但保留所有改动git reset --mixed默认否是是撤销 commit 和暂存状态但保留工作区改动git reset --hard是是是完全回到目标提交的状态工作区也会被覆盖这个表格非常关键。很多人误以为reset --hard会把代码“删光”其实它只是把工作区、暂存区和分支指针全部强制移动到某个历史提交。如果那个历史提交里没有包含后来新写的代码看起来就像“代码蒸发了”。但实际上那个“蒸发”的提交还存在于对象库里reflog 里有它的记录。所以只要 not panic第一步永远是查看 reflog而不是急着git pull或者重新创建文件。理解了这三个区域很多命令就不需要死记。比如git restore --staged是把暂存区恢复到与 HEAD 一致但不动工作区git checkout -- file是把工作区文件恢复到暂存区或 HEAD 的版本git reset --soft HEAD~1只是撤销最后一次 commit改动全部留在暂存区里。每一个命令的差异本质都是“你希望让哪个区域回到哪个状态”。1.3 急救第一步永远是备份现场而不是赶着执行命令我见过很多人在误操作后情绪激动直接敲一个reset --hard试图“滚回去”结果反而把原本还有可能恢复的东西彻底弄丢。这里我有一个铁律任何急救操作之前先花 10 秒备份现场。备份现场的具体做法很简单先不要关闭当前终端把自己的当前分支名、当前 reflog 的最后几条记录复制到一个临时文件里。如果是编辑过的文件立刻cp一份到/tmp或者项目外目录。如果正在 rebase 或 merge 途中先git status看处于什么状态别急着abort。例如你刚执行了git reset --hard想撤销又意识到这不是自己想要的提交。这时如果马上再执行一次reset --hard 别的提交虽然大概率也能找回但中间那几步的 reflog 链条会显得更乱。如果你在误操作后第一时间记录下 reflog 的最初位置后面恢复就只是“把指针指回去”的事了。备份不是浪费时间而是为了降低“二次误操作”带来的风险。执行急救命令前先问自己一句我现在知道我要回到哪个提交吗如果答不上来就先去查 reflog。2. 高频场景三连提交写错、文件没了、分支被 reset2.1 提交后想改用 amend 把上一次提交“重做”场景描述你刚执行git commit -m fix: 修正登录逻辑结果发现漏了一个文件或者提交信息打错了一个字。这种误操作非常常见而且完全不必慌张。如果这个提交还没有推送到远程也没被别人拉取过最优雅的处理方式是git commit --amend。它的作用是用一个新的提交来替换当前分支的 HEAD 提交新提交会继承旧提交的所有改动同时可以补充新的暂存内容或修改提交信息。具体操作分两种# 场景一只修改提交信息 $ git commit --amend -m fix: 修正登录逻辑与验证码校验 # 场景二漏了文件先补充到暂存区再合并进上次提交 $ git add forgot-file.js $ git commit --amend --no-edit--no-edit表示保留原有提交信息不额外打开编辑器。--amend的本质并不是“修改”旧提交而是“创建一个新提交替换旧提交”reflog 里还是会保留旧提交的记录。因此即使你对 amend 后的结果不满意依然能从 reflog 找回 amend 之前的那个提交。有一点必须强调amend只适合“尚未推送到远程”的提交。如果这个提交已经push到了团队共享分支再用 amend 就会造成本地历史与远程历史分叉其他人 pull 时会遇到麻烦。团队协作中的处理原则很简单——已推送的提交请走revert见后面章节未推送的提交才能用 amend 或 reset。2.2 文件被 rm 或改乱了用 restore 和 checkout 快速还原误删文件或者把文件改得一团糟也是高频事故。如果你还没有执行git commit或者git add那么工作区里的文件变动是可以直接丢弃并恢复到 HEAD 版本的。最直接的命令是# 用 HEAD 版本覆盖工作区文件 $ git restore --sourceHEAD --worktree src/App.js # 等价的老命令 $ git checkout -- src/App.js如果你只想撤销暂存区里的“已 add 状态”但不想动工作区的内容可以用$ git restore --staged src/App.js这个命令相当于把git add撤销文件会重新变成“未暂存”状态但本地内容不会变。老版本 Git 里对应的是git reset HEAD src/App.js。这里需要特别注意的是一旦你对文件执行过git add然后又继续编辑并意外保存git restore --sourceHEAD --worktree会把 HEAD 版本覆盖到工作区这意味着你最后的未暂存编辑会被覆盖。遇到这种情况如果那部分编辑很重要应该先cp备份文件再执行还原操作或考虑从编辑器/IDE 的本地历史里找回。为什么不建议轻易用checkout .或reset --hard直接覆盖全部文件因为一旦项目里同时有多个文件变更你可能只想恢复其中一个。恢复动作越精确越好把影响范围控制到单文件级别可以避免误伤其他正常改动。2.3 分支被 reset 退了十几个提交用 reflog 一步找回来这是事故率最高的场景之一。你本来在feature/login分支上做了 8 次提交结果手滑执行了git reset --hard HEAD~8或者误 reset 到了origin/develop发现自己这 8 个提交的代码全部“不见了”。遇到这种情况千万别急着重新写代码。先执行$ git reflog你会看到类似这样的输出9f8e7d6 HEAD{0}: reset: moving to 3c4d5e6 a1b2c3d HEAD{1}: commit: 重构登录模块 e4f5g6h HEAD{2}: commit: 增加记住我功能 i6j7k8l HEAD{3}: commit: 修复 token 刷新逻辑 ...HEAD{1}或更早的位置就是reset之前分支指向的提交。这个提交就是那 8 次提交里最新的一个也就是你想要恢复的目标。接下来只要把分支指针切回它$ git reset --hard a1b2c3d这样你的feature/login分支就重新指向了那个包含 8 次提交的节点全部代码恢复reflog 里会新增一条reset: moving to a1b2c3d的记录。有个细节要注意如果你在误操作后又执行了很多其他操作reflog 里的HEAD{1}可能不再是你想要的位置。这时候不要只看相对位置要直接认哈希值。看到2e4f6a8这种 commit id在那个提交是你需要的节点上直接reset过去就行。$ git reset --hard 2e4f6a8这个过程基本可以在 30 秒内完成。关键在于reset只是移动了引用对象库里的提交对象一直还在不存在“真正删除”这件事。除非你手动执行了git gc --prunenow或者 reflog 记录已被清除否则绝大多数情况都能救回。2.4 只想撤销 commit 但保留改动优先使用 --soft有些时候你并不是想彻底丢掉一次提交而是想把这次提交“拆开重新整理”。比如提交信息写错了或者提交内容里混入了不该提交的调试代码。这种场景不要用--hard用--soft或--mixed更安全。git reset --soft HEAD~1的含义是“把分支指针回退到上一次提交但工作区和暂存区都保持不变”。执行之后原本这次提交包含的所有改动依然在暂存区内你可以重新git add或重新git commit。$ git reset --soft HEAD~1 $ git status这时你会看到所有改动都处于“Changes to be committed”状态。如果你希望把其中一部分文件移出暂存区再执行git restore --staged即可。--soft比--hard安全得多因为它不会触碰工作区文件内容不存在真正覆盖数据的风险。我在实战中总是建议如果你不确定后果先尝试--soft再根据git status的结果决定下一步。--mixed默认模式会额外清除暂存状态但同样不动工作区文件也比较安全。只有在确实需要“让整个分支回到某个过去的状态彻底丢弃后续改动”时才考虑--hard。3. 中等灾难分支被删、rebase 翻车、远程推错3.1 分支被删了怎么找回来分支被git branch -D删掉的时候很多人以为整个分支所有提交都没了。其实和 reset 一样分支删除只是删除了一个指向提交对象的“引用”所有提交对象本身仍然保留在对象库里。所以你只要找到该分支最后一次指向的 commit就能重建分支。# 先确认要恢复分支最后一个 commit $ git reflog # 找到类似这样的记录deleted branch feature/payment (was 8a7b6c5) # 或者通过 reflog 里最近的 checkout 记录如果git log里没看到这个分支的提交你还可以用git fsck找到悬空提交$ git fsck --unreachable --no-reflogs | grep commit输出中每一行都是一个还没有被任何分支引用的提交对象。你可以逐个用git show 哈希查看提交信息找到属于被删分支的那个然后$ git checkout -b feature/payment 8a7b6c5这样分支就回来了所有提交也都完整保留。如果你记得分支被删前最后提交的大致时间和消息git reflog会更快如果你连 reflog 都看不到那条记录再用git fsck兜底。这里要注意git fsck找到的悬空提交可能很多尤其是项目历史较长、操作频繁时避免在输出中大海捞针。可以用git show --stat 哈希快速判断这个提交里改了哪些文件和你要找的分支内容是否一致。3.2 rebase 翻车中止、跳过、完成后的后悔药git rebase的翻车概率非常高。常见情况有rebase 执行到一半发现冲突太复杂不想玩了或者 rebase 完成了但发现整个提交顺序被搞乱气得想拍桌子。先说“进行到一半想反悔”的情况。Git 提供了一个很舒服的命令$ git rebase --abort这个命令会放弃整个 rebase 过程把当前分支恢复到 rebase 开始之前的状态。它比手动撤销冲突文件要可靠得多因为 rebase 过程中你处于一个临时 detached HEAD 状态手动 reset 容易搞错方向。如果 rebase 中出现了冲突但你想保留已处理的部分继续往下走就用# 解决冲突后 $ git add 已解决的冲突文件 $ git rebase --continue # 或者跳过当前提交 $ git rebase --skip--skip的作用是放弃当前正在处理的这个提交通常只在确定这个提交不再需要时才使用谨慎一点为妙。最麻烦的是 rebase 已经完成并且你发现 rebase 后的结果完全不对。这时第一反应还是 reflog。rebase 的本质是把一系列提交在另一个基点上一一重放每次重放都会生成新的提交对象所以原来的提交对象仍然存在。你可以在 reflog 里找到 rebase 开始前的那个分支指针位置直接git reset --hard回去。$ git reflog # 找到类似feature/x HEAD{2}: rebase finished: refs/heads/feature/x onto 8d2f3a1 $ git reset --hard HEAD{2}HEAD{2}的位置要根据你的实际 reflog 来判断不一定就是 2。建议先git reflog后看哪一条是 rebase 开始前的记录认准哈希值再 reset不要凭感觉数数。3.3 远程 push 错了revert 比 reset 稳得多本地误操作的后悔药很足但远程分支是另一个世界。如果错误提交已经git push到了团队的共享分支这时候不建议用 reset 再强推因为会影响所有协作者。更稳妥的做法是用git revert。git revert会生成一个新的提交这个提交的内容是“把某个提交的改动反向撤销”但历史记录里保留了这个被撤销提交的存在。这样做的好处是不会重写公共历史其他人pull时不会遇到历史分叉问题。# 撤销最近一次已推送的提交 $ git revert HEAD # 或撤销指定的某个提交 $ git revert 4f6a8c1如果你需要撤销的是一个合并提交merge commit普通 revert 可能不够通常得加-m参数指定保留哪一侧主线$ git revert -m 1 合并提交的哈希-m 1表示保留当前分支侧的历史撤销另一侧分支的改动。这个命令的效果是生成一个新提交把合并引入的改动全部撤销同时保留两条分支的合并关系。那如果已经用了git reset --hard回退了本地分支怎么办如果这个错误提交还没有 push或者只在你的本地出现reset 后正常 force push 即可。如果已经 push 了强烈建议放弃 reset 远程的念头改用 revert。只有当错误提交存在于一个刚建的临时分支、或所有协作者都明确同意强推时才考虑 reset 强推。3.4 force push 必须用 --force-with-lease有时候你确实需要强推比如本地 reset 了未推送的提交或者覆盖了一个临时分支。这时不要裸用git push --force因为它会无脑覆盖远程引用可能把同事刚推上去的新提交直接“冲掉”。正确的姿势是$ git push --force-with-lease--force-with-lease的含义是只有当远程分支的当前状态与你上一次获取fetch到的状态一致时才允许强推。如果远程已经有别人推送了新提交它会拒绝强推并提示你重新 fetch。这个机制相当于给强推加了一道安全带避免你用本地陈旧状态覆盖远程的新内容。我强烈建议在团队协作里把这条命令设为默认肌肉记忆只有在极端情况下才用全裸的--force而且用之前一定要在群里或者当面确认所有人的状态。就算你确定自己的操作没毛病也要用--force-with-lease因为远程引用变了这件事本身就是一个强信号说明有人在你不知情的情况下推送过代码。3.5 误合并之后怎么办git merge到一半发现问题可以执行git merge --abort直接取消合并回到 merge 开始前的状态。但是如果“merge 已经提交完成”再想撤销就得区分情况了。如果合并提交还没有 push最舒服的方式是 reset 回合并之前$ git reset --hard HEAD~1如果合并提交已经 push并且这个合并本身就是错误操作建议用git revert -m 1 合并提交哈希。注意-m 1和-m 2的区别合并提交有两个父提交-m 1表示保留合并发起分支的变更主线-m 2表示保留被合并分支的主线。一般撤销整个 merge 用-m 1就是回到发起合并前的状态但这条命令和普通 revert 不同它会产生一次“反向合并”后续如果再次合并这条分支Git 可能会因为“已经 revert 过”而误判需要额外处理。这个坑比较深我的经验是如果不太确定先把合并提交的哈希、两个父提交的哈希都记下来再用 revert。4. 隐藏刺客stash丢失、错误分支提交、悬空对象4.1 stash list 空了但改动还在用 fsck 找悬空对象git stash也是误操作重灾区。常见情况是你git stash保存了一堆临时改动然后过几天一看git stash list居然是空的。可能的原因是你执行了git stash clear或者git stash drop。这种情况下不要慌。git stash的实现本质是创建两个或多个提交对象一个保存暂存区状态另一个保存工作区状态并且会生成一个 stash 引用指向这些提交。当你执行stash drop或stash clear时只是删除了 stash 引用提交对象仍然残留在对象库中成为悬空提交。使用git fsck找回来$ git fsck --unreachable --no-reflogs | grep commit输出类似unreachable commit 3d2f0a1e5f6a... unreachable commit 9a8b7c6d5e4f...逐个git show查看提交内容看看哪个包含你 stash 过的文件。找到后你可以直接用那个提交创建一个新分支或者恢复成一个新的 stash# 将找到的悬空提交恢复为 stash $ git stash apply 3d2f0a1e5f6a # 或者基于它创建分支 $ git checkout -b recover-stash 3d2f0a1e5f6agit stash apply 哈希可以直接把那个提交里的改动应用到当前工作区效果和恢复一个普通 stash 一样。搜改动用git show --stat 哈希判断它包含哪些文件这样能快速定位。如果git fsck输出很多你可以结合时间判断也可以先把输出存到文件里慢慢筛。总之 stash 的丢失大多数都能救回来但要趁早别等久了对象被git gc清理。4.2 切换分支后改动“消失”了先别重建文件有一种很常见的“误以为丢失”的情况你在分支 A 上改了一堆代码没提交然后直接git checkout到分支 B。这时 Git 要么拒绝切换提示覆盖冲突要么带着未提交改动一起到了分支 B。如果你在分支 B 上执行了提交那些改动就进入了分支 B 的提交里而分支 A 反而没有。遇到“改动怎么不见了”的情况先不要重新写代码。第一步是git status看工作区里文件是否处于已修改状态第二步是git reflog看你刚才执行过哪些切换操作第三步是排查git stash list看有没有不小心把改动塞进 stash 里。如果你的改动只是被另一个分支的提交“吞并”了可以用git log -p在另一个分支上搜索特定代码片段或文件名。也可以使用git log --all --oneline -- 某个文件名来全局搜索哪个提交涉及该文件然后把它切回去。这个操作在大型项目里特别实用因为改动往往不是真的没了而是跑到了错误的分支或提交里。4.3 提交到了错误分支cherry-pick 迁移如果改动已经 commit 了但提交到了错误的分支上不要急着撤销。正确姿势是用git cherry-pick把这一个提交迁移到目标分支。假设你在feature/ticket-101分支上误把属于feature/ticket-102的改动提交了哈希是4f6a8c1。现在你需要# 在错误分支上记录当前状态确认是当前分支多了一个提交 # 切到目标分支 $ git checkout feature/ticket-102 # 把目标提交摘过来 $ git cherry-pick 4f6a8c1cherry-pick会把那个提交的改动在当前分支上重放一遍生成一个全新的提交。完成之后回到错误分支把误提交的改动移出$ git checkout feature/ticket-101 # 如果这个分支刚才的提交还没 push $ git reset --hard HEAD~1如果误提交的那次 commit 之后你在错误分支上又提交了新内容就不能简单地reset HEAD~1而是要精确定位到误提交的哈希用git revert 4f6a8c1撤销它或者用git rebase -i在交互式 rebase 里把那个提交删除。交互式 rebase 的操作要点是进入编辑器后把误提交所在行从pick改为drop然后保存退出Git 就会在重放其他提交时跳过这个提交。4.4 悬空对象兜底git fsck 与 git show 组合拳前面几个场景都提到了git fsck这里集中讲一下它的定位和用法。git fsck是一个用于检查对象库完整性的底层工具它会列出所有不可达对象这些对象大部分是因为各种操作遗留下来的“孤儿”。$ git fsck --lost-found带上--lost-found会把悬空对象按类型导出到.git/lost-found/目录里通常主要是 commit 对象。你可以直接查看这些 commit 的内容或者用git log对比。组合拳的完整思路是git reflog优先找最近几十次操作记录如果 reflog 里没有线索执行git fsck --unreachable --no-reflogs | grep commit用git show 哈希逐个查看悬空提交的改动内容找到目标后用git branch 恢复名 哈希或git cherry-pick 哈希恢复。这套组合拳能解决九成以上的“代码凭空消失”类问题。核心心法就是Git 的对象库是非常保守的存储系统只要不是手动清理或 gc 过期几乎不会真正删除提交对象。4.5 急救加速器常用 alias 和配置建议急救命令虽然不难但真的慌起来手速慢会加剧焦虑。我建议给自己的 Git 配几个顺手别名把常用操作缩到最短。下面是我用了多年的配置$ git config --global alias.lg log --oneline --graph --all --decorate $ git config --global alias.unstage restore --staged $ git config --global alias.last log -1 HEAD --stat $ git config --global alias.undo reset --soft HEAD~1 $ git config --global alias.co checkout配置之后git lg可以清晰查看所有分支的图形化提交历史git undo可以快速撤销上一次提交但保留改动git unstage可以快速取消暂存。还有一个我特别推荐的配置是开启 reflog 的可视化对照$ git config --global alias.myreflog reflog --daterelative --format%h %gd %gs这样在查看 reflog 时每条记录会显示相对时间和完整操作说明定位速度明显提升。5. 长期避坑习惯把后悔药前置到工作流里5.1 提交粒度越小急救越容易很多“灾难”其实是可以从源头上减少的。提交粒度越细每次提交只包含一个逻辑变更那么需要撤销或恢复的范围就越小。比如“修复登录 bug”“更新接口文档”“重构用户模块”分开提交比塞进一个“乱七八糟”的大提交好处理得多。如果一次大提交里混了多个改动你想撤销其中一部分就得用到git revert 手动修改或者git rebase -i拆分复杂度成倍增加。我建议养成“写完一个功能点就 commit”的习惯。哪怕同一个上午提交三次也比晚上一次性提交一个巨型 commit 好。误操作后悔药的前提是你有足够细的 checkpoint而提交就是 Git 世界里的 checkpoint。5.2 大型重构前先打 tag 或建备份分支涉及到大规模重命名、移动目录、修改数据表结构之类的高风险操作时不要只依赖 reflog。reflog 虽好用但如果你一个月后又来翻记录可能已经因为频繁操作被冲掉。更可靠的方式是在动手前打个 tag或者建一个备份分支。# 操作前 $ git tag backup/feature-login-20240601 # 或者 $ git branch backup/feature-login-20240601这两行命令的成本几乎为零但价值极高。tag 和普通分支一样是一个指向提交对象的固定引用除非你手动删除否则它不会消失。有了这样一个标记无论后续发生什么操作你都有一个“绝对安全点”可以随时回退。这个习惯特别适合那种需要改写大量文件的操作比如代码格式化工具批量处理、目录结构调整等。5.3 强推之前先确认三件事团队协作中最严重的 Git 事故大都来自强推。在按下 enter 之前我要求自己必须确认三件事这条分支是否只属于我个人如果是共享分支强推会直接冲击其他人的本地状态我是否用了--force-with-lease这个参数能否兜住“远程比我新”的情况如果强推出错我是否有本地备份分支或完整记录能否在 5 分钟内恢复到强推前只要任何一项答案是否定的就不要强推。宁可多花几分钟沟通也不要让团队所有人陷入“本地历史被改写”的泥潭。远程代码一旦被覆盖虽然远端也有 reflog但普通开发者通常没有权限直接操作远程仓库的引用恢复难度会大很多。5.4 每日结束前看一眼 reflog 和 status这个习惯听起来很土但非常有效。每天下班前花 30 秒看一眼git status和git reflog | head -5能让你清楚地知道今天做了哪些操作、当前处于什么状态、哪些东西还没提交。真发现哪个提交位置不对劲趁记忆新鲜赶紧处理成本最低。如果你是在团队里带新人也可以把这个建议分享出去减少很多不必要的救火时间。5.5 一条实用的本地备份脚本思路如果你经常处理重要分支可以考虑写一个简单的 shell 脚本自动给所有分支打备份 tag。这里提供一个我实践过的基础版本#!/bin/bash # 备份全部本地分支的当前快照 branchs$(git branch --format%(refname:short)) for b in $branchs; do tagbackup/$b-$(date %Y%m%d-%H%M%S) git tag $tag $b echo 已备份 $b - $tag done脚本会为每个本地分支创建一个带日期的备份 tag。当然生产环境用可能还需要考虑 tag 太多的问题建议定期清理一个月前的旧备份。这个方案的优点是不改变任何现有分支状态不干扰工作流程只额外增加一些安全的“存档点”。6. 一些我踩过坑后总结出的实战心得说了这么多命令最后补充几个不太写进文档里的经验吧。第一reflog是本地命令只在你的本地仓库里有效。如果你换了电脑、重装了系统或者 clone 了一份新仓库reflog 是空的。所以不要把 reflog 当成唯一保险重要分支定期 push 或打 tag 才是硬道理。第二当你用git fsck找到一个悬空提交后想恢复的提交如果是一个合并提交直接用git branch重建分支通常没问题但如果你想把它cherry-pick到别的分支要小心只捡了第一父提交的改动。第三如果你手头同时打开了多个终端窗口误操作概率会大幅上升。我在一个终端里reset另一个终端里直接继续写代码然后发现工作区被覆盖的情况发生过不止一次。所以开始任何 git 操作前先看一眼当前分支名最好让git status里的分支信息保持在可见范围内。还有一个小技巧如果你做了大量不熟悉的高级操作比如filter-branch、subtree、replace这类会改写历史的命令强烈建议先在一个 clone 出来的临时仓库里演练一遍确认无误后再对正式仓库动手。Git 的急救能力再强也最好别天天用。把后路前置到工作流里比每次事故后“拆弹”更让人安心。整套思路总结下来就一句话任何时候别慌先备份现场再查 reflog最后再做决定。希望这篇内容能帮你省下一次通宵抢救代码的经历。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑