如果文件是在带有 squash 的 rebase 中添加和删除的,git 是否会从索引和历史记录中永久删除文件?
Will git permanently remove files from index and history if the files were added and removed within a rebase with squash?
有人在 develop 分支上添加了一个他们不应该添加到我们的 repo 的目录,我已经删除了这些文件。现在,如果我回去做一个变基并压缩从添加之前到添加之后的提交,是否就像文件从未添加到回购协议中一样,或者它们是否仍然在索引或历史记录中的某个地方?
索引永远不会永久存在。它主要是 临时 数据结构,Git 使用它来构建您所做的 next 提交。您可以随时使用 git add
或 git rm
更改它; git checkout
和类似的命令从提交中填充它。所以这部分问题:
will [files] still be in the index
这不是一个明智的问题。
不过,另一部分更有用:
will [files] still be in ... history somewhere?
Git 中的历史 是 提交;提交 是 历史记录。
任何提交都不能更改,但您可以获得 Git 到 忘记 提交。 Git 通过从分支名称、标签名称和其他此类引用开始查找提交:每个引用都恰好包含一个哈希 ID,属于某个底层 Git 对象——主要是提交对象,偶尔也有标签对象,用于带注释的标签.标记对象持有另一个哈希 ID,通常是提交的哈希 ID;提交对象包含额外的提交哈希 ID,用于标识其前身提交。
因此,"history" 包含一个像 master
这样的名称,其中包含一个哈希 ID:一些大而难看的字母和数字串,但我们就称它为 H
:
... <-H <-- master
提交 H
本身包含另一个丑陋的大哈希 ID;我们称它为 G
:
... <-G <-H <-- master
提交 G
本身包含另一个丑陋的大哈希 ID。我们称这个为 F
:
... <-F <-G <-H <-- master
等等,等等。那是历史!
要在 存储库 中查找历史记录,我们只需从所有终点开始并向后工作:
D--E <-- dev
/
A--B--C
\
F--G--H <-- master
Commit A
是第一个,因此它不会更早地连接到任何东西。提交 A-B-C
在 两个 分支上。提交 E
是 dev
的结尾,提交 H
是 master
的结尾。通过从 E
开始并向后工作,我们访问了五个提交。通过从 H
开始并向后工作,我们访问了六个,其中三个与我们从 dev
访问的相同。所以总共有八个提交:三个共享,两个 dev
独有,三个 master
.
独有
git rebase
所做的是复制(一些)提交新的和改进的。假设我们将 dev
变基为只有 一个 独特但经过改进的新提交。让我们称之为一次提交 I
。我们只是安排 I
的前身——提交 I
中的哈希 ID 让我们 / Git 倒退——成为提交 C
:[=55= 的哈希 ID ]
D--E [abandoned]
/
A--B--C--I <-- dev
\
F--G--H <-- master
现在 dev
上总共有四次提交。
提交 D
和 E
仍然存在 。我们不能改变他们!但是我们也无法 找到 它们,因为我们通过从所有 名称 开始并向后工作来找到提交。没有名字将我们引向 E
;没有名字将我们带到 D
.
Git 保留一些额外的、隐藏的日志条目——在 Git 调用的 reflogs 中——保留一段时间,以防我们的 rebase 出错.虽然存在这些额外的 reflog 条目,但我们可以使用 git reflog dev
或 git reflog HEAD
来查找提交 E
的哈希 ID,也可能直接查找 D
的哈希 ID。因此,reflogs 使提交保持活动状态。
Reflog 条目最终会过期。一旦过期,它们就会被删除。一旦删除,它们就不再保护提交。一旦 所有 保护消失,提交——及其关联的快照——将有资格进行 垃圾收集,或 GC。 reflog 条目到期的默认值为 30 天和 90 天:90 天是 reachable 条目的时间,30 天是 unreachable 条目的时间条目,reachable 的定义基于存储在引用中的当前散列 ID,该引用通过该引用存在。在您的情况下,重新设置 dev
以将所有旧提交折叠为一个新的和改进的替换,旧的被认为无法访问,因此有 30 天的时间。
因为 Git 总是在创建 new 对象,其中一些最终会被引用并保留下来,默认情况下任何未至少存在 14 天的对象都会被保留来自垃圾收集器。垃圾收集器也不会一直 运行:Git 运行s git gc --auto
到 自动 每当看起来像GC 将是有利可图的。
由于 30 天超过 14 天,您的旧提交将在 rebase 后 30 天后的某个时间收集。为了让它更快发生,您可以立即手动使 reflog 过期,并手动 运行 随后 git gc
。但大多数情况下你应该让 Git 去做。
有人在 develop 分支上添加了一个他们不应该添加到我们的 repo 的目录,我已经删除了这些文件。现在,如果我回去做一个变基并压缩从添加之前到添加之后的提交,是否就像文件从未添加到回购协议中一样,或者它们是否仍然在索引或历史记录中的某个地方?
索引永远不会永久存在。它主要是 临时 数据结构,Git 使用它来构建您所做的 next 提交。您可以随时使用 git add
或 git rm
更改它; git checkout
和类似的命令从提交中填充它。所以这部分问题:
will [files] still be in the index
这不是一个明智的问题。
不过,另一部分更有用:
will [files] still be in ... history somewhere?
Git 中的历史 是 提交;提交 是 历史记录。
任何提交都不能更改,但您可以获得 Git 到 忘记 提交。 Git 通过从分支名称、标签名称和其他此类引用开始查找提交:每个引用都恰好包含一个哈希 ID,属于某个底层 Git 对象——主要是提交对象,偶尔也有标签对象,用于带注释的标签.标记对象持有另一个哈希 ID,通常是提交的哈希 ID;提交对象包含额外的提交哈希 ID,用于标识其前身提交。
因此,"history" 包含一个像 master
这样的名称,其中包含一个哈希 ID:一些大而难看的字母和数字串,但我们就称它为 H
:
... <-H <-- master
提交 H
本身包含另一个丑陋的大哈希 ID;我们称它为 G
:
... <-G <-H <-- master
提交 G
本身包含另一个丑陋的大哈希 ID。我们称这个为 F
:
... <-F <-G <-H <-- master
等等,等等。那是历史!
要在 存储库 中查找历史记录,我们只需从所有终点开始并向后工作:
D--E <-- dev
/
A--B--C
\
F--G--H <-- master
Commit A
是第一个,因此它不会更早地连接到任何东西。提交 A-B-C
在 两个 分支上。提交 E
是 dev
的结尾,提交 H
是 master
的结尾。通过从 E
开始并向后工作,我们访问了五个提交。通过从 H
开始并向后工作,我们访问了六个,其中三个与我们从 dev
访问的相同。所以总共有八个提交:三个共享,两个 dev
独有,三个 master
.
git rebase
所做的是复制(一些)提交新的和改进的。假设我们将 dev
变基为只有 一个 独特但经过改进的新提交。让我们称之为一次提交 I
。我们只是安排 I
的前身——提交 I
中的哈希 ID 让我们 / Git 倒退——成为提交 C
:[=55= 的哈希 ID ]
D--E [abandoned]
/
A--B--C--I <-- dev
\
F--G--H <-- master
现在 dev
上总共有四次提交。
提交 D
和 E
仍然存在 。我们不能改变他们!但是我们也无法 找到 它们,因为我们通过从所有 名称 开始并向后工作来找到提交。没有名字将我们引向 E
;没有名字将我们带到 D
.
Git 保留一些额外的、隐藏的日志条目——在 Git 调用的 reflogs 中——保留一段时间,以防我们的 rebase 出错.虽然存在这些额外的 reflog 条目,但我们可以使用 git reflog dev
或 git reflog HEAD
来查找提交 E
的哈希 ID,也可能直接查找 D
的哈希 ID。因此,reflogs 使提交保持活动状态。
Reflog 条目最终会过期。一旦过期,它们就会被删除。一旦删除,它们就不再保护提交。一旦 所有 保护消失,提交——及其关联的快照——将有资格进行 垃圾收集,或 GC。 reflog 条目到期的默认值为 30 天和 90 天:90 天是 reachable 条目的时间,30 天是 unreachable 条目的时间条目,reachable 的定义基于存储在引用中的当前散列 ID,该引用通过该引用存在。在您的情况下,重新设置 dev
以将所有旧提交折叠为一个新的和改进的替换,旧的被认为无法访问,因此有 30 天的时间。
因为 Git 总是在创建 new 对象,其中一些最终会被引用并保留下来,默认情况下任何未至少存在 14 天的对象都会被保留来自垃圾收集器。垃圾收集器也不会一直 运行:Git 运行s git gc --auto
到 自动 每当看起来像GC 将是有利可图的。
由于 30 天超过 14 天,您的旧提交将在 rebase 后 30 天后的某个时间收集。为了让它更快发生,您可以立即手动使 reflog 过期,并手动 运行 随后 git gc
。但大多数情况下你应该让 Git 去做。