1. Git三棵树

语法
commit模式
1
| git reset (<branch_name>|HEAD|<tree-ish>|<tag_name>) [--mixed | --soft | --hard | --merge | --keep]
|
file模式
1
| git reset (<branch_name>|HEAD|<tree-ish>|<tag_name>) [--] <file_path>
|
2. 正向流程
git的核心工作就是管理这三棵树。git add
就是把你工作目录(Working Directory)的修改提交到暂存区(Index),git commit
就是把暂存区的内容同步到仓库里作为一个快照,并移动HEAD
指向新快照;
三棵树从右向左看 ⬅️
提交历史从左到右看➡️

2.1. git init
- 让我们来可视化这个过程:假设进入到一个新目录,其中有一个文件,称其为该文件的 v1 版本,将它标记为蓝色,现在运行 git init,这会创建一个 Git 仓库,其中的 HEAD 引用指向未创建的 master 分支。

2.2. git add
- 此时,只有工作目录有内容。现在想要提交这个文件,所以用 git add 来获取工作目录中的内容,并将其复制到索引中。

2.3. git commit
- 接着运行 git commit,它会取得索引中的内容并将它保存为一个永久的快照,然后创建一个指向该快照的提交对象,最后更新 master 来指向本次提交。

2.4. edit file
- 此时如果我们运行 git status,会发现没有任何改动,因为现在三棵树完全相同。现在想要对文件进行修改然后提交它,将会经历同样的过程;首先在工作目录中修改文件,称其为该文件的 v2 版本,并将它标记为红色:

2.5. git add
- 如果现在运行 git status,将会看到文件显示在 “Changes not staged for commit” 下面并被标记为红色,这是因为该条目在索引与工作目录之间存在不同。接着运行 git add 来将它暂存到索引中:

2.6. git commit
- 此时,由于索引和 HEAD 不同,若运行 git status 的话就会看到 “Changes to be committed” 下的该文件变为绿色,也就是说,现在预期的下一次提交与上一次提交不同。最后,运行 git commit 来完成提交:

3. 逆向流程
3.1. 精简理解
显然,git reset
就是对上述行为的反向操作。
reset
的本质其实有2个动作:
- 移动
HEAD
指针指向某一个快照。 - 通过指定参数(3选1,不写则默认mixed),来递进的控制,在哪几颗树上进行覆盖。
--soft
——如图示中序号1所示情况,只改变指针指向的快照,即只覆盖本地版本库中的文件--mixed
——如图示中序号2所示情况,覆盖本地版本库中的文件的同时,也把快照内容同步到暂存区;--hard
——如图示中序号3所示情况,HEAD、Index改变的同时,本地工作区也被覆盖。三棵树全同步为指针指向的快照;
可以结合命令git diff
、git diff --cached
、git ls-files -s
、git show
或者git cat-file -p
进行验证理解
git diff
请见Git进阶--13、Git比对各区差异-git diff
三棵树从左向右 ➡️
提交历史从右向左⬅️

- 假设再次修改了 file.txt 文件并第三次提交它,现在的历史看起来是这样的:

- 跟着 reset 看看它都做了什么,它以一种简单可预见的方式直接操纵这三棵树。
3.2. 深入解析
3.2.1. 移动 HEAD(–soft)
- reset 做的第一件事是移动 HEAD 的指向,这与改变 HEAD 自身不同(checkout 所做的);reset 移动 HEAD 指向的分支。这意味着如果 HEAD 设置为 master 分支(例如正在 master 分支上),运行 git reset 9e5e6a4 将会使 master 指向 9e5e6a4:

- 无论调用了何种形式的带有一个提交的 reset,它首先都会尝试这样做,使用 reset –soft,它将仅仅停在那儿。
- 现在看一眼上图,理解一下发生的事情:它本质上是撤销了上一次 git commit 命令。当在运行 git commit 时,Git 会创建一个新的提交,并移动 HEAD 所指向的分支来使其指向该提交;当将它 reset 回 HEAD~(HEAD 的父结点)时,其实就是把该分支移动回原来的位置,而不会改变索引和工作目录。现在可以更新索引(或者只更新提交备注信息)之后再次运行 git commit。这与 Git进阶 — 5、Git-后悔药-重写历史-git commit--amend 所要做的事情是等同的。
3.2.2. 更新索引(–mixed)
- 注意,如果现在运行 git status 的话,就会看到新的 HEAD 和以绿色标出的它和索引之间的区别。接下来,reset 会用 HEAD 指向的当前快照的内容来更新索引:

- 如果指定 –mixed 选项,reset 将会在暂存区Index这里停止,这也是默认行为,所以如果没有指定任何选项(例子中只是 git reset HEAD~),这就是命令将会停止的地方。
- 现在再看一眼上图,理解一下发生的事情:它依然会撤销一上次提交,但还会取消暂存所有的东西,于是,我们回滚到了所有 git add 和 git commit 的命令执行之前。
3.2.3. 更新工作目录(–hard)
reset 要做的的第三件事情就是让工作目录看起来像索引。如果使用 –hard 选项,它将会继续这一步:

现在来回想一下刚才发生的事情:撤销了最后的提交、git add 和 git commit 命令以及工作目录中的所有工作。
必须注意,–hard 标记是 reset 命令唯一的危险用法,它也是 Git 会真正地销毁数据的仅有的几个操作之一。其他任何形式的 reset 调用都可以轻松撤消,但是 –hard 选项不能,因为它强制覆盖了工作目录中的文件。在这种特殊情况下,Git 数据库中的一个提交内还留有该文件的 v3 版本,可以通过 reflog 来找回它,但是若该文件还未提交,Git 仍会覆盖它从而导致无法轻松恢复。若想恢复则需要其他命令,请见Git进阶 — 6、Git找回丢失代码 git fsck --lost-found
WD不安全操作,请见Git进阶--8、Git-后悔药-回退撤销-大总结
reset 命令会以特定的顺序重写这三棵树,在指定以下选项时停止:
- 移动 HEAD 分支的指向 (若指定了 –soft,则到此停止);
- 使索引看起来像 HEAD (若未指定 –hard,则到此停止);
3.2.3.1. 演示示例
📢 由于引用的是网络动图,所以演示示例跟动图中的SHA-1值不一致,请注意辨别理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| cd ~
rm -rf recovery
mkdir recovery;cd recovery
git init .
echo "hello v1" > file.txt
git status
git add .
git commit -m "v1"
echo "hello v2" >> file.txt
git add .
git commit -m "v2"
echo "hello v3" >> file.txt
git add .
git commit -m "v3"
git log
|
git reflog
查看引用历史
1 2 3 4 5 6 7
| d4e752c (HEAD -> master) HEAD@{0}: commit: v3
e32d991 HEAD@{1}: commit: v2
c3daf0c HEAD@{2}: commit (initial): v1
(END)
|
git log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| commit d4e752c4d65dddd8a45962c7bb1937256534cd48 (HEAD -> master)
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 12:39:51 2022 +0800
v3
commit e32d991ec050e7b8d5183c1c9c02206d5b59982f
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 12:39:51 2022 +0800
v2
commit c3daf0c0af95d50ec25af70f48741bb1e3ff27ca
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 12:39:51 2022 +0800
v1
(END)
|
使用–soft回到v2 commit之后,git log如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| commit e32d991ec050e7b8d5183c1c9c02206d5b59982f (HEAD -> master)
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 12:39:51 2022 +0800
v2
commit c3daf0c0af95d50ec25af70f48741bb1e3ff27ca
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 12:39:51 2022 +0800
v1
(END)
|
git reflog
如下:
1 2 3 4 5 6 7 8 9
| e32d991 (HEAD -> master) HEAD@{0}: reset: moving to e32d
d4e752c HEAD@{1}: commit: v3
e32d991 (HEAD -> master) HEAD@{2}: commit: v2
c3daf0c HEAD@{3}: commit (initial): v1
(END)
|
git status
如下:
1 2 3 4 5 6 7 8 9
| ➜ recovery git:(master) ✗ git status
位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
修改: file.txt
|
我们可以看到–soft只是回退了commit到本地版本库的操作,文件为绿色,表示已经add到了暂存区
mixed和hard,不做演示
3.3. 通过路径来重置
理清了 reset 基本形式的行为,不过我们还可以给它提供一个作用路径:若指定了一个路径,reset 将会跳过第① 步(移动 HEAD),即只要加了路径,HEAD是不动的,并且将它的作用范围限定为指定的文件或文件集合。
这样做自然有它的道理,因为 HEAD 只是一个指针,无法让它同时指向两个提交中各自的一部分,不过索引和工作目录可以部分更新,所以重置可以继续进行第 ②步(更新索引) 和第 ③ 步(更新工作目录)。
📢 值得注意的是,加了路径就不能再加–soft或者–hard
因为git规定加了路径,HEAD就不会动,所以加–soft也不会起作用
硬重置的话,有git checkout HEAD –path,所以为了简化reset和减少错误发生的目的,–hard也是不允许的,否则会报 fatal: 不能带路径进行软性/硬性重置
3.3.1. 不加分支名或commit的SHA-1
3.3.1.1. 作用原理
- 现在,假如运行 git reset file.txt (这其实是 git reset –mixed HEAD file.txt 的简写形式,因为既没有指定一个提交的 SHA-1 或分支,也没有指定 –soft 或 –hard),它会:
- 移动 HEAD 分支的指向 (已跳过),使用当前HEAD指向的commit;
- 让索引看起来像 HEAD (到此处停止),拿HEAD中的覆盖Index索引区;
- 所以它本质上只是将 file.txt 从 HEAD 覆盖到索引中。即保留工作区成果,回退add和commit

实际应用场景
取消暂存文件
如果查看该命令的示意图,然后再想想 git add 所做的事,就会发现它们正好相反。
3.3.1.2. 演示示例
我们做到v2commit之前这一步,然后执行git reset file.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| cd ~
rm -rf recovery
mkdir recovery;cd recovery
git init .
echo "hello v1" > file.txt
git status
git add .
git commit -m "v1"
echo "hello v2" >> file.txt
git add .
|
git status`
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ➜ recovery git:(master) ✗ git status
位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
修改: file.txt
➜ recovery git:(master) ✗ cat file.txt
hello v1
hello v2
➜ recovery git:(master) ✗
|
git reflog
如下:
1
| f7138cf (HEAD -> master) HEAD@{0}: commit (initial): v1
|
git reset file.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| ➜ recovery git:(master) ✗ git reset file.txt
重置后取消暂存的变更:
M file.txt
➜ recovery git:(master) ✗ cat file.txt
hello v1
hello v2
➜ recovery git:(master) ✗ git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: file.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a"
|
我们可以发现,暂存区的文件被清空了,工作区的文件内容没有变化
3.3.2. 加分支名或commit的SHA-1
3.3.2.1. 作用原理
我们可以不让 Git 从 HEAD 拉取数据,而是通过具体指定一个提交来拉取该文件的对应版本,只需运行类似于 git reset eb43bf file.txt 的命令即可:

- 如果现在运行 git commit,它就会记录一条“将该文件恢复到 v1 版本”的更改,尽管我们并未在工作目录中真正地再次拥有它。
- 还有一点同 git add 一样,就是 reset 命令也可以接受一个 –patch 选项来一块一块地取消暂存的内容,这样就可以根据选择来取消暂存或恢复内容。
- 那工作区能不能强制覆盖呢,即
git reset SHA-1 --hard file.txt
,答案是no,会提示
fatal: 不能带路径进行硬性重置。那–soft呢,聪明如你,可以猜到会得到 fatal: 不能带路径进行软性重置。原因前面已经讲过。 - so,带路径带分支名或者commit的只有默认mixed参数,作用可以理解为拿某个文件或路径的某个commit的内容仅仅覆盖暂存区
当检测到文件路径时,git reset
将缓存区同步到你指定的那个提交。比如,下面这个命令会将倒数第二个提交中的foo.py加入到缓存区中,供下一个提交使用。
git reset HEAD~2 foo.py
和提交层面的git reset
一样,通常我们使用HEAD而不是某个特定的提交。运行git reset HEAD foo.py
会将当前的foo.py从缓存区中移除出去,而不会影响工作目录中对foo.py的更改。
–soft、–mixed和–hard对文件层面的git reset
毫无作用,因为缓存区中的文件一定会变化,而工作目录中的文件一定不变。
3.3.2.2. 演示示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| cd ~
rm -rf recovery
mkdir recovery;cd recovery
git init .
echo "hello v1" > file.txt
git status
git add .
git commit -m "v1"
echo "hello v2" >> file.txt
git add .
git commit -m "v2"
echo "hello v3" >> file.txt
git add .
git commit -m "v3"
git log
|
git reflog
如下:
1 2 3 4 5 6 7
| ae08e71 (HEAD -> master) HEAD@{0}: commit: v3
ec6224c HEAD@{1}: commit: v2
1c8edce HEAD@{2}: commit (initial): v1
(END)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ➜ recovery git:(master) git status
位于分支 master
无文件要提交,干净的工作区
➜ recovery git:(master) cat file.txt
hello v1
hello v2
hello v3
➜ recovery git:(master)
|
我们照例用v1的commit进行回退
git reset 1c8e file.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| ➜ recovery git:(master) git reset 1c8e file.txt
重置后取消暂存的变更:
M file.txt
➜ recovery git:(master) ✗ git status
位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
修改: file.txt
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: file.txt
➜ recovery git:(master) ✗ cat file.txt
hello v1
hello v2
hello v3
|
我们可以看到暂存区加入了文件,查看内容,发现暂存区确实变为了v1版本
1 2 3 4 5 6 7 8 9
| ➜ recovery git:(master) ✗ git ls-files -s
100644 d21fe316a0e9578aea75decc8c60e2a899534708 0 file.txt
➜ recovery git:(master) ✗ git show d21f
hello v1
(END)
|
工作区文件为红色,表示被修改,虽然默认是mixed覆盖到暂存区,但工作区相当于做了覆盖,然后又改成了v3版本,所以是红色
1 2 3 4 5 6 7
| ➜ recovery git:(master) ✗ cat file.txt
hello v1
hello v2
hello v3
|
此时我们git commit
一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| ➜ recovery git:(master) ✗ git commit -m "commit after reset"
[master 08d4efd] commit after reset
1 file changed, 2 deletions(-)
➜ recovery git:(master) ✗ git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: file.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
➜ recovery git:(master) ✗ git log
)
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 15:01:53 2022 +0800
commit after reset
commit ae08e7126daa0b323fc8bcf55a273ddd0f18ccb2
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 14:41:03 2022 +0800
v3
commit ec6224cc5549e06ac0b8b65a00dd8472ac30128e
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 14:41:03 2022 +0800
v2
commit 1c8edced86209178b3ff52ed782afbeecfe02420
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 14:41:03 2022 +0800
v1
|
git reflog
1 2 3 4 5 6 7 8 9
| 08d4efd (HEAD -> master) HEAD@{0}: commit: commit after reset
ae08e71 HEAD@{1}: commit: v3
ec6224c HEAD@{2}: commit: v2
1c8edce HEAD@{3}: commit (initial): v1
(END)
|
可以看到多了一次提交, git show 08d4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| commit 08d4efd3c3910ac07b0c19f47f754d797f4c2e98 (HEAD -> master)
Author: luoweile <luoweile2008@126.com>
Date: Thu Sep 15 15:01:53 2022 +0800
commit after reset
diff --git a/file.txt b/file.txt
index 56dc9b1..d21fe31 100644
--- a/file.txt
+++ b/file.txt
@@ -1,3 +1 @@
hello v1
-hello v2
-hello v3
(END)
|
可以看到回退到了v1版本
但此时工作区还是v3的版本,想也回退到v1,可以使用git reset --hard
或者git checkout file.txt
3.4. 压缩提交
3.4.1. 作用原理
假设一系列提交信息中有 “oops.”“WIP” 和 “forgot this file”, 就能使用 reset 来轻松快速地将它们压缩成单个提交。假设有一个项目,第一次提交中有一个文件,第二次提交增加了一个新的文件并修改了第一个文件,第三次提交再次修改了第一个文件,由于第二次提交是一个未完成的工作,因此需要压缩它。

- 那么可以运行 git reset –soft HEAD~2 来将 HEAD 分支移动到一个旧一点的提交上(即想要保留的最近的提交):

- 然后只需再次运行 git commit:

- 现在可以查看可到达的历史,即将会推送的历史,现在看起来有个 v1 版 file-a.txt 的提交,接着第二个提交将 file-a.txt 修改成了 v3 版并增加了 file-b.txt,包含 v2 版本的文件已经不在历史中。
3.4.2. 演示示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| cd ~
rm -rf recovery
mkdir recovery;cd recovery
git init .
echo "init file-a.txt v1" > file-a.txt
git status
git add .
git commit -m "init file-a.txt v1"
echo "update file-a.txt v2" >> file-a.txt
echo "init file-b.txt v1" >> file-b.txt
git add .
git commit -m "update file-a.txt v2"
echo "finish fix file-a.txt v3" >> file-a.txt
git add .
git commit -m "finish fix file-a.txt v3"
git log
|
git log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| commit de9545c70d3005351b1724d6c87e8610db4d0611 (HEAD -> master)
Author: luoweile <luoweile2008@126.com>
Date: Fri Sep 16 14:27:11 2022 +0800
finish fix file-a.txt v3
commit cf4753faaf9cb1ac03eeacebb725e59408420b9a
Author: luoweile <luoweile2008@126.com>
Date: Fri Sep 16 14:27:11 2022 +0800
update file-a.txt v2
commit cfb20be06b826848f1330426b06ae795cd09a9a3
Author: luoweile <luoweile2008@126.com>
Date: Fri Sep 16 14:27:11 2022 +0800
init file-a.txt v1
(END)
|
git reflog
1 2 3 4 5 6 7
| de9545c (HEAD -> master) HEAD@{0}: commit: finish fix file-a.txt v3
cf4753f HEAD@{1}: commit: update file-a.txt v2
cfb20be HEAD@{2}: commit (initial): init file-a.txt v1
(END)
|
git reset --soft HEAD~2
git log
1 2 3 4 5 6 7 8 9 10 11
| commit cfb20be06b826848f1330426b06ae795cd09a9a3 (HEAD -> master)
Author: luoweile <luoweile2008@126.com>
Date: Fri Sep 16 14:27:11 2022 +0800
init file-a.txt v1
(END)
|
git reflog
1 2 3 4 5 6 7 8 9
| cfb20be (HEAD -> master) HEAD@{0}: reset: moving to HEAD~2
de9545c HEAD@{1}: commit: finish fix file-a.txt v3
cf4753f HEAD@{2}: commit: update file-a.txt v2
cfb20be (HEAD -> master) HEAD@{3}: commit (initial): init file-a.txt v1
(END)
|
可以看出来,此时HEAD指向了第一次的commit cfb2,相当于把commit回退了
git status
1 2 3 4 5 6 7 8 9 10 11
| ➜ recovery git:(master) ✗ git status
位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
修改: file-a.txt
新文件: file-b.txt
|
我们再次执行git commit
1 2 3 4 5 6 7
| ➜ recovery git:(master) ✗ git commit -m "compress commit test"
[master 798ae56] compress commit test
2 files changed, 3 insertions(+)
create mode 100644 file-b.txt
|
git log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| commit 798ae5608429362e4390b1eac74746e2fc78bb12 (HEAD -> master)
Author: luoweile <luoweile2008@126.com>
Date: Fri Sep 16 14:32:17 2022 +0800
compress commit test
commit cfb20be06b826848f1330426b06ae795cd09a9a3
Author: luoweile <luoweile2008@126.com>
Date: Fri Sep 16 14:27:11 2022 +0800
init file-a.txt v1
(END)
|
git log 只看到了2次commit信息
git reflog
1 2 3 4 5 6 7 8 9 10 11
| 798ae56 (HEAD -> master) HEAD@{0}: commit: compress commit test
cfb20be HEAD@{1}: reset: moving to HEAD~2
de9545c HEAD@{2}: commit: finish fix file-a.txt v3
cf4753f HEAD@{3}: commit: update file-a.txt v2
cfb20be HEAD@{4}: commit (initial): init file-a.txt v1
(END)
|
不过git reflog还是看得很清楚
4. 对commit历史的影响
命令 | log | reflog |
---|
revert | 新增 | 可跟踪 |
checkout | 无变化 | 无变化 |
reset | 丢失 | 可跟踪 |
restore | 无变化 | 无变化 |
git amend | 改变 | 改变 |
5. 其他后悔药
5.1. revert
Git进阶 — 2、Git-后悔药-回退撤销-revert5.2. checkout
Git进阶 — 3、Git-后悔药-回退撤销-checkout5.3. restore
Git进阶 — 4、Git-后悔药-回退撤销-restore5.4. git commit –amend
Git进阶 — 5、Git-后悔药-重写历史-gitcommit--amend6. 延长保存期限
我们前面说到在Git上做的所有操作都被保存到记录里,一般是从你本地Git库执行clone开始的所有操作都保存了下来,所以不用担心很久之前的一些Commit log找不到,你或许期望去为已删除的提交设置一个更长的保存周期。例如:
$ git config gc.pruneexpire "30 days"
默认2周
意思是一个被删除的提交会在删除30天后,且运行 git gc 以后,被永久丢弃。
你或许还想关掉 git gc 的自动运行:
$ git config gc.auto 0
在这种情况下提交将只在你手工运行 git gc 的情况下才永久删除。
7. 参考
https://bbs.huaweicloud.com/blogs/331355
https://www.jianshu.com/p/8b4c95677ee0
https://static.kancloud.cn/apachecn/git-doc-zh/1945496
https://wikinote.gitbook.io/git-learning/git-ji-ben-ming-ling/ti-jiao-che-xiao-yu-la-qu/git-reset