是否可以在 git 中命名不同批次的暂存文件?
Is it possible to name different batches of staged files in git?
例如,我对分支中的几个文件进行了更改。
然后我使用 git add
.
对它们进行分阶段
然后我还有其他的额外改动。
我使用 git add
.
再次上演它们
是否可以为每个阶段命名?
谢谢。
简短的回答是否定的。
长答案是 是的,但甚至不要尝试这样做,你只会让自己发疯。
要了解原因,让我们看看“暂存区”的实际工作原理。
Git 是关于提交
Git 总的来说,都是关于提交的。尽管提交存储文件,但它与文件无关;这与分支无关,尽管我们将提交组织成我们称之为分支的东西,并且我们使用分支 names(我们也称之为“分支”,尽管它们完全不同——见 Haddock's Eyes 了解更多关于事物、名称和名称名称之间的混淆)...我在哪里?啊是的,我们使用分支名称来 find 提交,因为每个提交的 true 名称是唯一的,但是又大又丑,random-looking, too-difficult-for-humans-to-use 哈希 ID 或 对象 ID (OID).
所以每个 Git 提交都有编号,有一个唯一的编号,表示为一个丑陋的大 hexadecimal string. Git stores every commit—plus a bunch of supporting objects, which also get OIDs—in a big database of "all Git objects". Using the OIDs (hash IDs) as keys, Git can look up the objects nearly instantly in this key-value store,这很棒,除了一些问题:
- 数据库中没有存储任何内容永远无法更改。
- 一次提交存储每个文件的完整快照(及时冻结,永远)。这些文件 de-duplicated 跨(甚至在)提交以保存 space,这完全可以,因为它们一直被冻结。
- 每个提交还存储一些元数据,我们将忽略此特定答案。
所以每次提交就像每个文件的永久存档(tar 或 zip 或其他)。但是这些文件以特殊的read-only、Git-only、压缩和de-duplicated形式存储。只有 Git 可以 读取 它们,而且您计算机上的任何内容,甚至 Git 本身都不能覆盖它们。1
这意味着您实际上不能使用提交的文件!这可能会让您想知道它们有什么用。
虽然这个问题的解决方案很简单:当您使用 git switch
或 git checkout
到 select 提交时,Git 读取 文件的冻结副本(Git 可以 做,即使别无他法)并使用它来写入 可用 版本的文件。这些可用版本作为普通的日常文件进入您的工作树。如果这就是 Git 所做的一切,那么事情会非常简单,您一开始就不会问这个问题,但这还不是 Git 所做的全部。
1如果 设法覆盖一个,结果是一个损坏的 Git 数据库:你不能再提取使用该覆盖文件的任何提交。所以 Git 不会那样做; Git 试图阻止其他程序这样做;没有别的应该首先尝试。
Git 的索引又名暂存区
棘手的一点是,当 Git 提取一个提交时,您可以使用它——无论是阅读它,还是稍后构建一个新的提交——Git 复制所有冻结的文件从deep-freeze到Git调用它的索引或暂存区。 (Git 对这个东西有第三个名字,称它为 cache,虽然现在这个名字用处不大:它主要显示为标志名,比如git rm --cached
.)
从技术上讲,暂存区中的内容是文件的 名称和模式 ,加上 对 冻结 de-duplicated 的引用复制。然而,你可以认为它 就好像 它持有冻结副本的可重写版本,因为 Git 如何使用它:当你 运行 git add
, Git:
- 读取文件的工作树副本;
- 将它压缩成冻结的形式,但还没有完全冻结它;2
- 检查是否重复;和
- 用冻结的形式更新索引,re-using现有的副本,或者不是,视情况而定。
如果您为此时不在索引中的文件添加 新名称,Git 添加新名称和 frozen-format 内容到索引。使用 git rm
或 git rm --cached
也会 删除 适当的名称和引用。
所以结果是,当您第一次签出 某个提交时,索引包含该提交的完整副本3。当您 运行 git add
时,索引副本会更新。实际上,索引始终包含您的建议的下一次提交。
当您实际上 运行 git commit
进行新提交时,Git 获取 frozen-format 索引内容并将其真正冻结为真正的提交。该新提交获得一个新的唯一哈希 ID,并且 Git 更新当前的 分支名称 以将新提交记住为最新提交(Git 安排新的commit 的 metadata 以记住前一个 branch-tip 提交哈希 ID)。
现在,关于索引的事情是这样的:只有一个索引。4 所以没有办法说“这个是 X 点的索引”,然后是“这是 Y 点的索引”:只有一个索引,git add
覆盖了 point-X 索引,当你使 point-Y 存在时.
所有这一切的最终结果是,因为只有一个索引,所以只有一个暂存 ara。没法命名,因为是the index.
2从技术上讲,Git 确实 添加了一个 frozen-format blob 对象 如有必要,立即到对象数据库。但是,如果它从未被使用过,它最终会被丢弃。所以它好像它从来没有被添加到这里,这就是为什么它比“冰冻”更“泥泞”。
3因为索引里的是de-duplicated,commit出来的文件肯定已经在数据库里了,所以这个copy不需要space。索引条目本身确实占用了一点 space——大致上每个文件大约 100 字节——但是文件内容都是 de-duplicated.
之前的
4这在技术上是错误的,原因有二:
- 最重要的是,每个工作树有一个可区分的索引。使用
git worktree add
你可以创建一个新的工作树,并带有一个新的索引。
- 为了 Git 自己的内部目的,可以创建并填充一个 临时 索引。这样做非常棘手,但是当您使用
git commit --only
或 git commit --include
时 git commit
需要这样做。实际上,对于git commit --only
,Git需要创建两个个临时索引文件。使用临时索引文件 而不是 索引的能力已导出:您可以使用脚本自己完成。但是如果这样做,您必须格外小心,因为 the 索引——这个特定工作树的区别索引——必须 保持正确的关系使用当前的提交和工作树。如果不小心维护关系,next git commit
会提交错误的文件。
因此,虽然可以有多个索引文件处于活动状态,但您不想长时间(例如几秒钟)执行此操作。当 git commit
命令创建其临时索引副本时,它们只会持续到提交本身完成。
例如,我对分支中的几个文件进行了更改。
然后我使用 git add
.
然后我还有其他的额外改动。
我使用 git add
.
是否可以为每个阶段命名? 谢谢。
简短的回答是否定的。
长答案是 是的,但甚至不要尝试这样做,你只会让自己发疯。
要了解原因,让我们看看“暂存区”的实际工作原理。
Git 是关于提交
Git 总的来说,都是关于提交的。尽管提交存储文件,但它与文件无关;这与分支无关,尽管我们将提交组织成我们称之为分支的东西,并且我们使用分支 names(我们也称之为“分支”,尽管它们完全不同——见 Haddock's Eyes 了解更多关于事物、名称和名称名称之间的混淆)...我在哪里?啊是的,我们使用分支名称来 find 提交,因为每个提交的 true 名称是唯一的,但是又大又丑,random-looking, too-difficult-for-humans-to-use 哈希 ID 或 对象 ID (OID).
所以每个 Git 提交都有编号,有一个唯一的编号,表示为一个丑陋的大 hexadecimal string. Git stores every commit—plus a bunch of supporting objects, which also get OIDs—in a big database of "all Git objects". Using the OIDs (hash IDs) as keys, Git can look up the objects nearly instantly in this key-value store,这很棒,除了一些问题:
- 数据库中没有存储任何内容永远无法更改。
- 一次提交存储每个文件的完整快照(及时冻结,永远)。这些文件 de-duplicated 跨(甚至在)提交以保存 space,这完全可以,因为它们一直被冻结。
- 每个提交还存储一些元数据,我们将忽略此特定答案。
所以每次提交就像每个文件的永久存档(tar 或 zip 或其他)。但是这些文件以特殊的read-only、Git-only、压缩和de-duplicated形式存储。只有 Git 可以 读取 它们,而且您计算机上的任何内容,甚至 Git 本身都不能覆盖它们。1
这意味着您实际上不能使用提交的文件!这可能会让您想知道它们有什么用。
虽然这个问题的解决方案很简单:当您使用 git switch
或 git checkout
到 select 提交时,Git 读取 文件的冻结副本(Git 可以 做,即使别无他法)并使用它来写入 可用 版本的文件。这些可用版本作为普通的日常文件进入您的工作树。如果这就是 Git 所做的一切,那么事情会非常简单,您一开始就不会问这个问题,但这还不是 Git 所做的全部。
1如果 设法覆盖一个,结果是一个损坏的 Git 数据库:你不能再提取使用该覆盖文件的任何提交。所以 Git 不会那样做; Git 试图阻止其他程序这样做;没有别的应该首先尝试。
Git 的索引又名暂存区
棘手的一点是,当 Git 提取一个提交时,您可以使用它——无论是阅读它,还是稍后构建一个新的提交——Git 复制所有冻结的文件从deep-freeze到Git调用它的索引或暂存区。 (Git 对这个东西有第三个名字,称它为 cache,虽然现在这个名字用处不大:它主要显示为标志名,比如git rm --cached
.)
从技术上讲,暂存区中的内容是文件的 名称和模式 ,加上 对 冻结 de-duplicated 的引用复制。然而,你可以认为它 就好像 它持有冻结副本的可重写版本,因为 Git 如何使用它:当你 运行 git add
, Git:
- 读取文件的工作树副本;
- 将它压缩成冻结的形式,但还没有完全冻结它;2
- 检查是否重复;和
- 用冻结的形式更新索引,re-using现有的副本,或者不是,视情况而定。
如果您为此时不在索引中的文件添加 新名称,Git 添加新名称和 frozen-format 内容到索引。使用 git rm
或 git rm --cached
也会 删除 适当的名称和引用。
所以结果是,当您第一次签出 某个提交时,索引包含该提交的完整副本3。当您 运行 git add
时,索引副本会更新。实际上,索引始终包含您的建议的下一次提交。
当您实际上 运行 git commit
进行新提交时,Git 获取 frozen-format 索引内容并将其真正冻结为真正的提交。该新提交获得一个新的唯一哈希 ID,并且 Git 更新当前的 分支名称 以将新提交记住为最新提交(Git 安排新的commit 的 metadata 以记住前一个 branch-tip 提交哈希 ID)。
现在,关于索引的事情是这样的:只有一个索引。4 所以没有办法说“这个是 X 点的索引”,然后是“这是 Y 点的索引”:只有一个索引,git add
覆盖了 point-X 索引,当你使 point-Y 存在时.
所有这一切的最终结果是,因为只有一个索引,所以只有一个暂存 ara。没法命名,因为是the index.
2从技术上讲,Git 确实 添加了一个 frozen-format blob 对象 如有必要,立即到对象数据库。但是,如果它从未被使用过,它最终会被丢弃。所以它好像它从来没有被添加到这里,这就是为什么它比“冰冻”更“泥泞”。
3因为索引里的是de-duplicated,commit出来的文件肯定已经在数据库里了,所以这个copy不需要space。索引条目本身确实占用了一点 space——大致上每个文件大约 100 字节——但是文件内容都是 de-duplicated.
之前的4这在技术上是错误的,原因有二:
- 最重要的是,每个工作树有一个可区分的索引。使用
git worktree add
你可以创建一个新的工作树,并带有一个新的索引。 - 为了 Git 自己的内部目的,可以创建并填充一个 临时 索引。这样做非常棘手,但是当您使用
git commit --only
或git commit --include
时git commit
需要这样做。实际上,对于git commit --only
,Git需要创建两个个临时索引文件。使用临时索引文件 而不是 索引的能力已导出:您可以使用脚本自己完成。但是如果这样做,您必须格外小心,因为 the 索引——这个特定工作树的区别索引——必须 保持正确的关系使用当前的提交和工作树。如果不小心维护关系,nextgit commit
会提交错误的文件。
因此,虽然可以有多个索引文件处于活动状态,但您不想长时间(例如几秒钟)执行此操作。当 git commit
命令创建其临时索引副本时,它们只会持续到提交本身完成。