您现在的位置是:首页 >技术教程 >git reflog网站首页技术教程
git reflog
git reflog
每次 git 的 reference 更新的时候,git 就会将其记录下来,这也是 reflog 名字的来源——reference log,同样,使用 git reflog
就可以查看这些记录。
需要注意的事情就是,reflog 只会保存本地的变化,其次,所有的记录最多保持 90 天(可配置),90 后这些记录就会“退休”,无法被回溯。
依旧先看一下 logs 下面有什么:
❯ ls .git/logs
HEAD refs
❯ cat .git/logs/HEAD
0000000000000000000000000000000000000000 662f1ed1067847b920db2f21454c426fb285a979 GA <XXX@yyy.zzz> 1682446660 -0400 clone: from https://github.com/reduxjs/redux.git
662f1ed1067847b920db2f21454c426fb285a979 1d92031be5cec9b36b931da2055f61ac006d31a3 GA <XXX@yyy.zzz> 1682447178 -0400 checkout: moving from master to v4.2.0-alpha.0
1d92031be5cec9b36b931da2055f61ac006d31a3 662f1ed1067847b920db2f21454c426fb285a979 GA <XXX@yyy.zzz> 1682448046 -0400 checkout: moving from 1d92031be5cec9b36b931da2055f61ac006d31a3 to master
662f1ed1067847b920db2f21454c426fb285a979 11d94c7a0fb7ef4fdcefb6e701674c2449804abd GA <XXX@yyy.zzz> 1682448166 -0400 commit: add text to readme
❯ ls .git/logs/refs
heads remotes
reflog 总共有 4 个子命令:show(默认)、expire、delete 和 exists,这里主要就讲一下 git ref log show
这个子命令,因为其他两个,git 官方文档都说不常用,最后一个 exists 用于查看当前是否有 log。一般来说都是保存的本地分支,如果有分支,并且在设定的 log 过期时间内有活动的话,就会返回 true……大概主要也是供内部使用吧,作为 end user,一旦我切换到当前分支就肯定会产生 log,不切换单独获取 ref id……使用场景确实比较少。
使用 reflog show 查看的内容如下:
❯ git reflog show HEAD
49d04ce8 (HEAD -> master, new-branch) HEAD@{0}: checkout: moving from master to master
49d04ce8 (HEAD -> master, new-branch) HEAD@{1}: checkout: moving from b05e43256ec2bed86e1180be978b41313cf6529d to master
b05e4325 (tag: v5.0.0-alpha.5) HEAD@{2}: checkout: moving from new-branch to b05e4325
49d04ce8 (HEAD -> master, new-branch) HEAD@{3}: checkout: moving from master to new-branch
49d04ce8 (HEAD -> master, new-branch) HEAD@{4}: checkout: moving from new-branch to master
49d04ce8 (HEAD -> master, new-branch) HEAD@{5}: checkout: moving from master to new-branch
49d04ce8 (HEAD -> master, new-branch) HEAD@{6}: commit: add new message
11d94c7a HEAD@{7}: commit: add text to readme
662f1ed1 HEAD@{8}: checkout: moving from 1d92031be5cec9b36b931da2055f61ac006d31a3 to master
1d92031b (tag: v4.2.0-alpha.0) HEAD@{9}: checkout: moving from master to v4.2.0-alpha.0
662f1ed1 HEAD@{10}: clone: from https://github.com/reduxjs/redux.git
(END)
可以看到就是 .git/logs
中的内容,不过更加精简一些,另外就是 HEAD@{0}
,这个代表的是 reflog 的 entry。HEAD~2
指的是当前 HEAD 上前两个 commit,HEAD@{0}
指的是 reflog 中的操作,比如说切换分支。
reflog 还有一些更佳 fancy 的语法,比如 master@{one.week.ago}
,官方文档上的说明为 “where master used to point to one week ago in this local repository”,即查看一周前,本地上的 master 分支指向的 ref。鉴于每一次 checkout、commit、reset 等都会在 reflog 上留下印记(只要还在过期时间内),那么如果不小心搞砸了什么,也可以在 reflog 中找到对应的记录,并且说不定能够救一下。
比如说我知道 2 天前当前 master 分支还是工作的:
❯ git reflog show master@{2.days.ago}
49d04ce8 (HEAD -> master, new-branch) master@{Tue Apr 25 14:47:25 2023 -0400}: commit: add new message
11d94c7a master@{Tue Apr 25 14:42:46 2023 -0400}: commit: add text to readme
662f1ed1 master@{Tue Apr 25 14:17:40 2023 -0400}: clone: from https://github.com/reduxjs/redux.git
这样我就可以对比当前分支和两天前的分支,然后进行修正。
reflog 案例
# rebase
❯ git log --oneline
47e1a77 (HEAD -> main) commit 5
ad3a810 commit 4
8429daa commit 3
208eec5 commit 2
❯ git rebase -i HEAD~3
[detached HEAD 432f1e9] commit 3
Date: Fri Apr 28 08:03:11 2023 -0400
1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/main.
❯ git log --oneline
d2fa52a (HEAD -> main) commit 3
208eec5 commit 2
使用 reflog 查看并回溯:
❯ git reflog show
d2fa52a (HEAD -> main) HEAD@{0}: rebase (finish): returning to refs/heads/main
d2fa52a (HEAD -> main) HEAD@{1}: rebase (fixup): commit 3
3d5e67e HEAD@{2}: rebase (fixup): # This is a combination of 2 commits.
432f1e9 HEAD@{3}: rebase (reword): commit 3
8429daa HEAD@{4}: rebase: fast-forward
208eec5 HEAD@{5}: rebase (start): checkout HEAD~3
47e1a77 HEAD@{6}: commit: commit 5
ad3a810 HEAD@{7}: commit: commit 4
8429daa HEAD@{8}: commit: commit 3
208eec5 HEAD@{9}: commit (initial): commit 2
(END)
❯ git reset --hard 47e1a77
HEAD is now at 47e1a77 commit 5
❯ git log --oneline
47e1a77 (HEAD -> main) commit 5
ad3a810 commit 4
8429daa commit 3
208eec5 commit 2
(END)
这样就算是 undo 了一下 rebase……如果 rebase 的文件比较大,然后不小心出错的话,大概可以这样拯救一下,但是如果分支已经推到 remote 上的话,还是用 merge 比较保险吧。