我有一个repo,有四个commit:
$ git log --oneline --decorate
6c35831 (HEAD, master) C4
974073b C3
e27b22c C2
9f2d694 C1
我将reset -- soft
提交到C2
,现在我有一个像这样的repo:
$ git reset e27b22c --soft
$ git log --oneline --decorate
e27b22c (HEAD, master) C2
9f2d694 C1
现在我添加了一个额外的提交,所以日志看起来像这样:
$ git log --oneline --decorate
545fa99 (HEAD, master) C5
e27b22c C2
9f2d694 C1
提交C3
和C4
发生了什么?我没有删除它们,所以我假设它们仍然存在,C3
的父节点仍然是C2
。
4条答案
按热度按时间pn9klfpd1#
简短回答:提交
C3
和C4
将保留在Git对象数据库中,直到它们被垃圾收集。长回答:垃圾收集将通过不同的Git porcelain命令或显式垃圾收集时自动发生。有许多场景可以触发自动垃圾收集;看一下
gc.*
配置设置就能了解情况。您可以使用git gc
builtin command显式地进行gabage收集。让我们看一个例子,看看会发生什么。首先,让我们设置我们的环境(我使用的是Linux;根据您的环境进行必要的更改),因此我们希望在不同的Git存储库中获得相同的对象散列。
由于提交对象哈希是使用这些信息生成的,如果我们使用相同的作者和提交者值,我们现在应该都得到相同的哈希。
现在让我们初始化一个函数,使用
git log
、git reflog
、git count-objects
、git rev-list
和git fsck
记录对象信息。现在让我们初始化一个Git仓库。
对我来说,它输出:
正如预期的那样,我们有一个初始化的存储库,其中没有对象。让我们做一些提交并看看对象。
这将给出以下输出:
现在我们在仓库中有六个对象:五个提交和一个空树。我们可以看到Git对所有五个提交对象都有分支、标签和/或reflog引用。只要Git引用了一个对象,这个对象就不会被垃圾回收。显式运行gabage收集将不会从存储库中删除任何对象。(我将把验证这一点作为一个练习留给您完成。)
现在让我们删除Git对
C3
、C4
和C5
提交的引用。其输出:
现在我们看到只有两个提交被Git引用。但是,所有六个对象仍在存储库中。它们将保留在存储库中,直到被自动或显式地进行垃圾收集。例如,你甚至可以用
git cherry-pick
恢复一个未引用的提交,或者用git show
查看它。现在,让我们显式地对未引用的对象进行垃圾收集,看看Git在幕后做了什么。这将输出一点信息。
最后,让我们看看这些物体。
其输出:
现在我们看到只有三个对象:两个提交和一个空树。
6vl6ewon2#
例如,运行
git show 6c35831
以查看C4仍然存在。运行git reflog master
查看master
used 引用的内容(很多)。其中一个条目(master^{1}
最有可能,但如果您还做了其他更改,可能是一个更老的条目)应该对应于6c35831
,而git show master^{1}
(或任何条目)应该显示我提到的第一个git show
命令的输出。hrysbysz3#
孤立提交会一直呆在那里,直到它们被显式运行
git gc
进行垃圾收集。nqwrtyyt4#
伟大的问题和答案的帖子。这里只是提醒一下精确的术语。
OP所描述的实际上被称为unreachable/danglingcommits。参见官方词汇表中的相应条目:悬挂对象和不可达对象。
而orphan,在Git的上下文中,修改由
git init
或git checkout --orphan
创建的 * 分支 *,因为这些分支上的第一次提交没有父级。