记一次git reset事故

原文 : 与佳期的个人博客(gonghonglou.com)

因为一次 git reset 操作回滚提交差点丢掉近一周的代码,而且还是明天就要提测的紧急项目,慌得一匹。。。

事故过程:

1、从 branchA 分支的 commitA1 节点牵出一个 branchB 分支
2、branchA 分支的 commitA1、commitA2 ... commitAn 提交记录
3、branchB 分支的 commitB1、commitB2 ... commitBn 提交记录
4、branchB 分支开发完成后,打算将 branchA 分支合并到 branchB 分支上
5、合并之后发现有冲突,并且解决起来太麻烦,所以打算取消合并,暂时只提测 branchB 分支的代码,然后执行了回滚操作

因为 branchB 分支只有我一个人在工作,且合并代码的那次提交记录是无用的,所以执行了 git reset 操作,且加了 --hard(抛弃合并那次的提交) ,并强推到了远程:

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git reset --hard 1f88a09e3d359aa2213a0750e32d08f2ff4086e0
HEAD is now at 1f88a09e update

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git push -f
Total 0 (delta 0), reused 0 (delta 0)
remote: 
remote: To create a merge request for feature/917, visit:
remote:   http://git.xxxxxxxx.com/ios/TDFMemberPod/merge_requests/new?merge_request%5Bsource_branch%5D=feature%2F917
remote: 
To git.xxxxxxxx.com:ios/TDFMemberPod.git
 + 7ff865d7...1f88a09e feature/917 -> feature/917 (forced update)

理想其况下执行上述操作是没问题的,但当时因为 commitAn 的提交信息和 commitBn 的提交信息是一样的,没有仔细查看节点信息,commit 的 hash 值写错了,实际执行的操作是:

git reset --hard commitAn
git push -f

但正确的执行的操作应该是:

git reset --hard commitBn
git push -f

然后发现 branchB 分支上的代码只有 branchA 分支的代码,而原来 branchB 分支的代码被删除了,而且已经推送到了远程,前边说过了 branchB 分支只有我一个人在工作,这下本地和远程都丢失了代码。。。慌得一匹。。。

解决过程:

虽然慌得一匹,但总感觉 git 应该有应对这样操作失误的方法,打电话给师兄求助,解决流程如下。

执行 git reset 操作后,再执行 git log 是看不到回滚的那部分提交的,能看到只是现在分支上存在的提交,只剩下 branchA 分支上的提交:

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git log
commit 1f88a09e3d359aa2213a0750e32d08f2ff4086e0 (HEAD -> feature/917, origin/release/0.7.20, origin/feature/917, release/0.7.20)
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 18:36:14 2018 +0800

    update

commit 4ae03f23a72955290f0daffa2ae3696c69067776
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 15:56:46 2018 +0800

    update:账单页面 ui修改

commit ef7140f36c99ca3940b95a51a7cda3a88c8efca2
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 14:08:59 2018 +0800

    服务端下发

commit 38c67dcf627a3e2c7342dc5ca12c68b2b71a6c7e
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 14:07:03 2018 +0800

......

这时候只有执行 git reflog 命令,可以看到 git reset 回滚的提交:

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git reflog
1f88a09e (HEAD -> feature/917, origin/release/0.7.20, origin/feature/917, release/0.7.20) HEAD@{0}: reset: moving to HEAD
1f88a09e (HEAD -> feature/917, origin/release/0.7.20, origin/feature/917, release/0.7.20) HEAD@{1}: reset: moving to 1f88a09e3d359aa2213a0750e32d08f2ff4086e0
7ff865d7 HEAD@{2}: checkout: moving from release/0.7.20 to feature/917
1f88a09e (HEAD -> feature/917, origin/release/0.7.20, origin/feature/917, release/0.7.20) HEAD@{3}: reset: moving to HEAD
1f88a09e (HEAD -> feature/917, origin/release/0.7.20, origin/feature/917, release/0.7.20) HEAD@{4}: checkout: moving from feature/917 to release/0.7.20
7ff865d7 HEAD@{5}: commit (merge): Merge branch 'release/0.7.20' into feature/917
7d5f5fc3 HEAD@{6}: reset: moving to HEAD
7d5f5fc3 HEAD@{7}: checkout: moving from release/0.7.20 to feature/917
1f88a09e (HEAD -> feature/917, origin/release/0.7.20, origin/feature/917, release/0.7.20) HEAD@{8}: pull origin release/0.7.20: Fast-forward
555bc18b HEAD@{9}: checkout: moving from feature/917 to release/0.7.20
7d5f5fc3 HEAD@{10}: commit: update
65ed2c95 HEAD@{11}: commit: 跳转url
5bcc6ce4 HEAD@{12}: commit: update json/js from setting_model
a519a43a HEAD@{13}: commit: update json/js from setting_model
5562d3a3 HEAD@{14}: commit: 修改报名及预览
52915778 HEAD@{15}: commit: update json/js from setting_model
53f49fe1 HEAD@{16}: commit: 917json拷贝

......

找到 branchB 分支上的 commitBn 提交的 hash 值,再执行 git reset commitBn,回到合并前的正确的提交节点上:

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git reset 7d5f5fc3
Unstaged changes after reset:
M   Classes/AccurateMarking/Assets/directPreview.js
D   Classes/Assets/917_coupons.js
D   Classes/Assets/917_coupons.json
D   Classes/Assets/917_register.js
D   Classes/Assets/917_register.json
M   Classes/Assets/member_base_info.js
M   Classes/Assets/member_base_info.json
M   Classes/Assets/member_card_detail.js

......

此时查看 git ststus

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git status
On branch feature/917
Your branch and 'origin/feature/917' have diverged,
and have 19 and 68 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   Classes/AccurateMarking/Assets/directPreview.js
    deleted:    Classes/Assets/917_coupons.js
    deleted:    Classes/Assets/917_coupons.json
    deleted:    Classes/Assets/917_register.js
    deleted:    Classes/Assets/917_register.json
    modified:   Classes/Assets/member_base_info.js
    modified:   Classes/Assets/member_base_info.json

......

modified:   TDFMemberPod/Info.plist
    modified:   TDFMemberPod/ViewController.m
    modified:   fileCopy/config

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    Classes/MarketingPlan/

no changes added to commit (use "git add" and/or "git commit -a")

此时虽然节点回到了正确的地方,但是代码还是包含了 branchA 分支上合过来的代码,而这些代码应该是存在了暂存区,所以执行 git log 能看到到提交记录只有 branchA 分支的:

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git log
commit 7d5f5fc36a4874200dea0b7e255e654c474eaf0e (HEAD -> feature/917)
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 21:31:23 2018 +0800

    update

commit 65ed2c955a53d0864403ac08609a9367cae6d650
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 21:17:59 2018 +0800

    跳转url

commit 5bcc6ce453bdfe94dc5efac39b46d2123caf5de1
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 21:17:28 2018 +0800

    update json/js from setting_model

......

执行 git reset --hard 命令抛弃 branchA 分支合过来的代码,并回到合并前的正确的提交节点上:

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git reset --hard 7d5f5fc3
HEAD is now at 7d5f5fc3 update

执行 git log 能看到现在的提交只包含了 branchB 分支上的提交记录,代码也是正确的:

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git log
commit 7d5f5fc36a4874200dea0b7e255e654c474eaf0e (HEAD -> feature/917)
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 21:31:23 2018 +0800

    update

commit 65ed2c955a53d0864403ac08609a9367cae6d650
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 21:17:59 2018 +0800

    跳转url

commit 5bcc6ce453bdfe94dc5efac39b46d2123caf5de1
Author: xxxxxxxx <xxxxxxxx@xxxx.com>
Date:   Tue Aug 21 21:17:28 2018 +0800

    update json/js from setting_model

......

这时执行 git push -f 强制覆盖远程代码:

yujiaqideMacBook-Pro:TDFMemberPod gonghonglou$ git push -f
Counting objects: 176, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (171/171), done.
Writing objects: 100% (176/176), 35.19 KiB | 2.35 MiB/s, done.
Total 176 (delta 122), reused 5 (delta 5)
remote: Resolving deltas: 100% (122/122), completed with 22 local objects.
remote: 
remote: To create a merge request for feature/917, visit:
remote:   http://git.xxxxxxxx.com/ios/TDFMemberPod/merge_requests/new?merge_request%5Bsource_branch%5D=feature%2F917
remote: 
To git.xxxxxxxx:ios/TDFMemberPod.git
 + 1f88a09e...7d5f5fc3 feature/917 -> feature/917 (forced update)

经验教训

1、git reset --hard 会清除当前节点到回滚节点之间的所有提交,直接回退节点,不留痕迹。

2、执行了 git reset --hard 操作后,是不能直接执行 git push 来推送了,需要加强制命令 git push -f 来覆盖远程代码。

2、即使分支只有一个人在工作,但执行回滚操作是还是应当慎用 git reset,或者可以使用 git revet 来执行回滚。两者比较直观的区别是 git reset 会抛弃当前节点到将要回滚节点之间的提交,直接回退节点,而 git revet 是将之前的提交操作逆向执行一遍,回到将要回滚的节点的状态,并生成一个新的提交,这样所有的操作都在 git 上有记录。

3、即使错误的执行了 git reset 操作,并强推到了远程,要保护好自己本地的工作目录,通过 git reflog 命令查看 git reset 操作,找到之前的节点重新 git reset 一次。

4、如果本地工作目录缺失,只能通过共同工作于该分支的同事的本地记录来尽量挽回损失了,如果有共同工作于该分支的同事的话。

5、git:https://git-scm.com/book/zh/v2

后记

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容

  • 一、电脑本地初始化一个仓库 1. git init: 初始化一个电脑上本地仓库 终端进入项目目录,输入: 该命令将...
    dragon_li阅读 2,910评论 1 4
  • 【专题:雅月集】 词的平仄格式来源于近体诗的声律要求。近体诗要求一句中平声字与仄声字(上、去、入声)交错使用,以使...
    南阳雅月阅读 643评论 4 5
  • 项目一:深蹲 5kg 15*1;12kg 15*1;14kg 15*1,18kg 15*1 项目二:股二头肌 25...
    oppy阅读 96评论 0 0
  • 这两天事情比较多。昨晚听完的课程网络援疆教案设计交流课程,早早就休息了。也许是太累了,晚上电闪雷鸣瓢泼大雨我一点儿...
    吉林付巍巍阅读 396评论 1 1
  • 串行通信和并行通信? 并行通信传输中有多个数据位,同时在两个设备之间传输。发送设备将这些数据位通过对应的数据线传送...
    罗蓁蓁阅读 2,004评论 0 4