git操作撤销

有被自己蠢到,吓半死

  • git 误操作导致丢文件
  • 通过 reflog 以及 checkout 新建临时分支恢复文件

起因

一时兴起,GitHub 上开了个 repo,打算把本地的 git repo 同步上去,但是本地分支 checkout 过去的时候好像有问题。
今天晚上才发现丢了一整周的 commit,从 18 号直接跳到 25 号,手边又没有任何近期的备份,给我吓半死。

解决

  • 因为 branch 丢失之后没有 commit 的 log,一开始尝试通过 diskgenius 恢复本地文件,ssd trim 掉了/覆盖了,无果

人麻了,以为要重写了,忽然想到还有 git,遂一顿搜。
嘿,还有救。 因为 git 还没 gc,所以我们可以从reflog入手,新建一个分支恢复,以下给出一个例子。

分支情况
1
2
3
iy88@DESKTOP:~/test (main)$ git branch
* main
test

在 main 分支里有一个文件a.txt

a.txt
1
2
iy88@DESKTOP-BL3O7B2:~/test (main)$ cat a.txt
hello

现在让我们来切换到test分支

切换分支
1
2
iy88@DESKTOP-BL3O7B2:~/test (main)$ git checkout test
Switched to branch 'test'

其中有 a.txtb.txt 同时我们能看到 git log 中的提交记录

branch test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
iy88@DESKTOP-BL3O7B2:~/test (test)$ ls
a.txt b.txt
iy88@DESKTOP-BL3O7B2:~/test (test)$ git log
commit 362e71dbc4fad7231ba8ac956f4ef64e6ace5c0b (HEAD -> test)
Author: iy88 <xxxxxxxxxxx>
Date: Mon Nov 25 23:39:27 2024 +0800

commit on branch test

commit 96655ee5229924b5cafe94b23a0f113516d828a4 (main)
Author: iy88 <xxxxxxxxxxx>
Date: Mon Nov 25 23:38:47 2024 +0800

first commit

现在让我们来删除这个分支复现场景

删除分支
1
2
3
4
iy88@DESKTOP-BL3O7B2:~/test (test)$ git checkout main
Switched to branch 'main'
iy88@DESKTOP-BL3O7B2:~/test (main)$ git branch -D test
Deleted branch test (was 362e71d).

现在我们看不到这个分支,也不可能在 main 中看到 test 分支的提交了

分支与提交
1
2
3
4
5
6
7
8
iy88@DESKTOP-BL3O7B2:~/test (main)$ git branch
* main
iy88@DESKTOP-BL3O7B2:~/test (main)$ git log
commit 96655ee5229924b5cafe94b23a0f113516d828a4 (HEAD -> main)
Author: iy88 <xxxxxxxxxxx>
Date: Mon Nov 25 23:38:47 2024 +0800

first commit

但是此时我们可以通过 reflog 查看

reflog
1
2
3
4
5
iy88@DESKTOP-BL3O7B2:~/test (main)$ git reflog
96655ee (HEAD -> main) HEAD@{0}: checkout: moving from test to main
362e71d HEAD@{1}: commit: commit on branch test
96655ee (HEAD -> main) HEAD@{2}: checkout: moving from main to test
96655ee (HEAD -> main) HEAD@{3}: commit (initial): first commit

注意到,362e71d 这个 commit 是我们切换回 main 前的最后一个提交记录,也就是我们需要恢复的状态,于是我们创建一个临时分支 restore

git
1
2
iy88@DESKTOP-BL3O7B2:~/test (main)$ git checkout -b restore 362e71d
Switched to a new branch 'restore'

此时我们查看 restore 分支

restore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
iy88@DESKTOP-BL3O7B2:~/test (restore)$ git log
commit 362e71dbc4fad7231ba8ac956f4ef64e6ace5c0b (HEAD -> restore)
Author: iy88 <xxxxxxxxxxx>
Date: Mon Nov 25 23:39:27 2024 +0800

commit on branch test

commit 96655ee5229924b5cafe94b23a0f113516d828a4 (main)
Author: iy88 <xxxxxxxxxxx>
Date: Mon Nov 25 23:38:47 2024 +0800

first commit
iy88@DESKTOP-BL3O7B2:~/test ((restore))$ ls
a.txt b.txt

这时我们已经能看到删除分支里的文件了,这个方法同样适用于你在 branch 里没有 add 并 commit 的情况。
此时可以选择合并分支或者直接复制文件过去恢复了。


git 还是要好好学,VCS 关键时刻救狗命啊 :)