假设我有一个 git 存储库,在某些分支上工作,并且在某些时候我不想签出任何分支。我可以这样做吗?
换句话说,我可以git clone path-to-repo --no-checkout在现有存储库上获得 , 但的效果吗?
编辑:实际上,如果主分支文件不显示为已删除,那就更好了。因此,理想的答案并不git clone像--no-checkout.
注意:如果您的建议需要最新版本的 git,请说明。
这只是Schwern 答案的扩展,这是正确的\xe2\x80\x94,但您可能需要添加git rm -r所有文件中的 a,也许还需要添加 a git clean。还有一种特殊情况,您根本无法执行任何操作,并且也许您并不真正想要删除文件。
对此有几种可能的答案,具体取决于您真正寻找的内容。让我们从一些背景和定义开始:
\n一个新的、完全空的存储库没有提交。分支名称仅在标识提交时才存在,如果没有提交,则无法标识。所以这个存储库没有分支。奇怪的是,你仍然在树枝上。只是你所在的分支不存在。
\n在这种类型的存储库中,您只有一个选择,那就是位于“孤立分支”上。我们稍后再讨论这一点。
\n否则\xe2\x80\x94当有提交\xe2\x80\x94时,你可以有任意数量的有效的现有分支名称,每个分支名称都必须指向某个现有的有效提交。您可以恰好位于这些分支名称之一,也可以处于分离 HEAD模式,或者可以使用“孤立分支”模式。
\n孤儿分支模式是三种模式中最奇怪的,但我们首先描述它,然后再描述其他两种模式:
\n孤立模式:HEAD包含分支名称。这是当前分支,因此您位于一个分支上。奇怪的是你所在的分支不存在。命令git branch将列出确实存在的分支名称,但不会列出您所在的分支名称,因为它不存在。
普通模式:HEAD包含分支名称。这是当前分支,存储在该分支名称中的提交哈希 ID 就是当前提交。
Detached-HEAD 模式:HEAD包含提交哈希 ID。这是当前的提交;当前没有分支。
Agit clone通常会导致正常模式。成为当前分支的分支名称是您每次选择的名称git clone,您可以-b选择。不过,这个规则也有一些例外:如果你-b命名了一个tag,Git 会检查该标签,将你置于 detached-HEAD 模式。如果您没有指定-b选项,您的 Git 会询问其他 Git 推荐的分支名称,并使用该名称或后备名称;如果该名称或后备名称无法命名分支,您将陷入孤立模式,并以不存在的分支作为当前分支。如果您指定了一个-b选项,则该名称必须命名其他 Git 存储库中的现有分支或标记,否则整个克隆命令将失败。
该-n选项对新克隆的模式没有影响。您处于正常、分离 HEAD 或孤立模式,就像没有它时一样。该选项的唯一作用是它阻止初始. 使用正常模式时,分支名称仍然在本地创建,因此,如果您克隆的存储库中有分支,您将位于其中之一,该分支名称存在于本地并指向与远程跟踪名称。这是一个奇怪的特殊情况,我认为这是一个小错误,因为如果你运行, , 并且不执行 a ,你就会处于孤立模式。(这是创建分支的步骤,当使用除自身之外的命令时,因此跳过它应该会让您处于孤立模式。但事实并非如此。)-ngit checkoutgit initgit remote addgit fetchgit checkoutgit checkoutgit clone
以上是关于HEAD\xe2\x80\x94 其中存储的内容,以及哪个分支和/或提交是当前的(如果有)\xe2\x80\x94 和分支名称。但是,当我们环顾非裸存储库时,我们会看到一堆文件,存储为普通的日常文件。这些文件不是 Git 中的文件。Git 中的内容是分支、标记和其他名称\xe2\x80\x94 作为一种辅助数据库\xe2\x80\x94 以及一系列提交和支持对象,存储在主(通常更大)数据库中。
提交起到档案和历史的作用。每次提交都会存储每个文件的完整快照,就像在 tar、rar 或 zip 存档中一样。每个提交还存储一些元数据,包括进行提交的人的姓名等。这些档案中的所有内容都是严格的、完全只读的:本质上是这样,因为它们都是通过加密强哈希函数生成的数字来寻址的。任何更改任何存储数据的尝试都会导致不正确的哈希值,1会被 Git 检测到,并报告为损坏的存储库。
\n但是,由于无法更改这些文件\xe2\x80\x94,甚至无法查看它们,因此在大多数程序\xe2\x80\x94中,这些存档将毫无用处。因此,Git 会将存档提取到工作树中:您可以在其中查看和使用文件的区域。这是 \xe2\x80\x94 至少最初是 \xe2\x80\x94 您在工作树中拥有的内容:提取某些提交的结果。提取的提交是当前提交。
\n从技术上讲,这就是我们所需要的:作为档案和历史记录的提交以及工作副本。当我们将它们视为“当前提交”和“工作树副本”时,这是两个副本。这些都是一些版本控制系统中的全部内容。但无论出于何种原因,Git 都会在工作树中永久冻结的当前提交副本和可读、可写、有用的版本之间插入每个文件的第三个副本。这使得工作树副本成为第三个副本,可以说:每个文件的第二个副本存在于 Git\ 的索引中。
\nGit 索引中的文件格式与提交中的文件格式相同:它们经过预压缩和预去重。提交档案中的文件都经过重复数据删除,这通常可以节省大量空间。Git 在这里用来加快速度的一个技巧是索引副本是预先去重复的,这样在提交时就不需要做任何工作。这意味着文件的索引副本几乎不占用任何空间。例如,Git 的 Git 项目的扩展文件在我的一台机器上占用了大约 57 MiB,但保存这些相同文件所需的索引只有 368790 字节。(注意:这些数字都不算目录.git。)但原则上,提交有三个副本:HEAD\xe2\x80\x94提交本身\xe2\x80\x94加上索引加上工作树副本。
1除非您可以花费足够的计算时间来产生哈希冲突。请参阅新发现的 SHA-1 冲突如何影响 Git? 请注意,这并不是偶然发生的,对于大多数团体来说,即使是故意这样做也是不切实际的(尽管这不再超出像谷歌这样的大公司或各个民族国家的能力)。
\ngit clone -n当您使用 时git clone -n,您将获得三种模式之一HEAD:孤立分支、分离 HEAD 或正常。但是 Git 不会运行git checkout,它会git checkout填充Git的索引和工作树。所以你有一个名义上为空的索引和工作树。2
因此,如果您希望准确地重现这种情况,您将需要:
\nHEAD确定使用哪种设置;和为了在第 1 部分中简单起见,您可以简单地采用正常模式而不执行任何操作。为了在第 2 部分中简单起见,您可以使用git read-tree --empty,它会删除索引,然后git clean使用各种选项。您可以使用git read-tree --empty -u删除所有索引文件,只在工作树中留下未跟踪的文件。或者您可以选择不理会工作树。
如果您希望重现一个分离的 HEAD(使第 1 部分稍微复杂一些),您有两种选择:
\ngit checkout --detach或git checkout任何不是分支名称的东西,或者git switch --detach使用任何提交说明符运行。指定的提交(或不带参数HEAD使用时的提交git checkout --detach)将成为当前提交,并且您现在处于分离 HEAD 模式。您在此处签出(或使用 切换到git switch)的提交将填充 Git\ 的索引并更新工作树中的文件,除了在当前分支上存在未提交的更改时签出另一个分支中概述的特殊情况外。
要进入孤立模式,请使用git checkout --orphan或git switch --orphan。请注意这种偷偷摸摸的不兼容性:旧的签出方法不会干扰 Git 的索引和工作树。该git switch命令清空索引并清理工作树,就像使用git read-tree --empty -u.
(在所有情况下,未跟踪的文件都不会受到干扰,无论这些未跟踪的文件是否也被忽略。)
\n2空索引是非零长度文件,因为索引具有标头和标尾。它们包含加密哈希值,以便检测磁盘损坏,就像存储库对象数据库一样。为了方便地完成这项工作,Git 将不存在的索引视为“空”,并在内存中创建空索引,并在适当的时候用正确的校验和写入它。
\n工作树的顶层通常包含.git存储库本身的目录,因此“空”工作树永远不会完全空。但是,您可以使用各种选项将存储库和工作树目录分开。
无论您进入哪种模式,请注意,运行git commit现在将像往常一样尝试创建新的提交:
在孤立模式下,这将创建一个没有父级的新提交(一个新的根提交)并创建名称为 的分支HEAD。该分支现在存在,并保存一个根提交,未通过提交图连接到任何其他提交。
(在完成合并时执行此操作可能是一个坏主意。我不知道如果您尝试这样做会发生什么。)
\n在 detached-HEAD 模式下,这将使用通常的父级创建一个提交(当前提交作为父级,加上来自正在进行的合并的任何其他提交)。然后,Git 会将新提交的哈希 ID 存储在 中HEAD,该 ID 继续分离,但现在指向只能通过找到的提交HEAD。
在正常模式下,这将照常创建一个新的提交(包括像往常一样结束合并,就像 detached-HEAD 模式一样),然后将新提交的哈希 ID 存储在HEAD.
新的提交将存储 Git 索引中的任何文件作为其快照。如果清空索引,那就是一棵空树。如果您将文件留在索引中或将文件放入索引中,那么这些文件就是快照中的文件。
\n可能没有真正的理由这样做,但这些不同模式中最安全的可能是具有空索引和空工作树的新孤立分支模式。这样,就没有人会意外地git commit在现有的树枝上长出一棵新的空树。其中最简单的可能是 detached-HEAD 模式;这样,您可以清除索引和工作树,也可以不清除,而不必太担心。