它会显示来自本地仓库、暂存仓库、远程仓库还是其他地方的文件?
我一直看到一个文件,它在git ls-files
中存在。
该文件已从远程仓库中删除。
之后,我尝试执行git pull
。
然而,该文件仍然出现在这个命令列表中。
它不应该出现在这里,因为它在远程仓库中也不存在。
它会显示来自本地仓库、暂存仓库、远程仓库还是其他地方的文件?
我一直看到一个文件,它在git ls-files
中存在。
该文件已从远程仓库中删除。
之后,我尝试执行git pull
。
然而,该文件仍然出现在这个命令列表中。
它不应该出现在这里,因为它在远程仓库中也不存在。
你需要理解Git存储每个文件的至少三个活动副本,有时多达五个:一个在当前提交中,一个(或两个或三个!)在索引中,以及一个——你唯一可以看到和使用的——在你的工作树中。 git ls-files
命令查看这些副本,然后根据您提供给git ls-files
的标志告诉您其中一些内容。
如果没有这个每个文件三到五个副本的概念,Git中的许多事情将永远不会有任何意义。(好吧,即使有了这个概念,有些事情仍然很棘手,但那是另一个完全不同的问题。)
我认为这里有两个问题。一个需要一些术语,然后另一个就应该落到位了:
git ls-files
是否显示本地版本库中的文件?
有点类似,但:
暂存区,
Git没有暂存区。每个版本库都有一些在不同的Git文档中称为索引或暂存区的东西。 (在Git词汇表中还有一个已过时的第三个名称,缓存。)
绝对不需要任何远程仓库,即其他具有自己仓库的Git,如果有的话,只有远程版本库。
git fetch
和git push
会让您的Git调用他们的Git并与他们交换数据。 (好吧,git ls-remote
执行git fetch
的第一小部分,git pull
运行git fetch
,因此这两个也会与远程交换数据。 但是,git ls-files
不会。)
是的,有点像。这让我们回到了第一部分。因此,让我们将这三个术语片段视为Git词汇表中定义的内容。以下斜体(包括粗斜体)文本直接来自链接的文档:或者来自其他地方?
仓库(repository)
一组引用(refs)以及一个包含所有从refs引用可达到的对象的对象数据库,可能还伴随着来自一个或多个porcelain的元数据。仓库可以通过alternates机制与其他仓库共享对象数据库。
当然,这里充满了更多术语。为了尝试将其解释清楚一些,他们在这里表明,仓库本身不包括索引和工作树:它大多由提交(及其内容)组成。当然,这需要我们定义“索引”和“工作树”,因此让我们继续阅读:
索引(index)
一个带有stat信息的文件集合,其内容存储为对象。索引是您的working tree的存储版本。老实说,它还可以包含第二个甚至第三个工作树版本,这些版本在merging时使用。
工作树(working tree) (我通常称之为work-tree):
实际检出文件的树。工作树通常包含HEAD提交树的内容,以及您尚未提交的任何本地更改。
当您运行git commit
时,Git会对所有文件进行快照 - 好吧,至少是所有跟踪的文件 - 并将其存储在一个提交中,同时还包括一些元数据,如您的姓名和电子邮件地址。这个提交基本上是永久性的 - 您可以通过费力地删除它们来摆脱提交,但出于方便起见,请将它们视为永久性的 - 并且完全、彻底、100%只读。这是有意为之的只读模式,因为这允许其他提交共享相同的文件副本,因此,如果您提交同一个文件一次、十次或甚至一百万次,仓库中实际上只有一个该文件的副本。只有当您将文件更改为新版本时,Git才必须提交一个新的、单独的副本。
提交记录是编号的,但不是按照漂亮简单的连续编号系统。也就是说,我们可能会将它们绘制成一系列简单的编号或字母形式:
... <-C4 <-C5 <-C6 ...
git merge
、git revert
或git cherry-pick
还是任何其他使用合并引擎的Git命令,如果操作不顺利,Git会将每个文件的所有三个输入放入索引中,这样您就可以获得三个file.ext
的副本,而非只有一个。但只要您不处于合并过程中,索引中就只有一个副本。HEAD
冻结副本或工作树副本匹配,或两者都匹配。例如,在新的git checkout
之后,所有三个副本都匹配。然后您在工作树中修改了file.ext
:现在提交和索引匹配,但它们与工作树副本不同。然后您执行git add file.ext
,现在索引和工作树匹配,但它们与冻结副本不同。然后您git commit
以创建一个新的提交,该提交成为当前提交,所有三个副本再次匹配。vim file.ext
然后将更新后的内容复制到索引中:
git add file.ext
然后再次编辑它:
vim file.ext
git rm --cached file.ext
删除索引副本。当然,它无法触及当前提交的冻结副本,但是如果现在创建一个新的提交,则新的提交将根本不包含file.ext
。(先前的提交仍然包含,当然。)
任何当前位于工作树中且当前未在索引中的文件都是未跟踪的文件。它的未跟踪性源于它不在您的索引中。将该文件放入索引中,它就被跟踪了,无论您如何将其放入索引中。从索引中删除它,它就是未跟踪的,无论您如何将其从索引中移出。因此,这是索引的最后一个角色:确定哪些文件是已跟踪的,并因此将在下一次提交中。
git ls-files
的作用git ls-files
的作用是读取所有内容:提交、索引和工作树。根据您提供给git ls-files
的参数,它会打印出索引和/或工作树中某些或所有文件的名称:
git ls-files --stage
列出索引/暂存区中的文件以及它们的暂存槽编号。 (它不涉及HEAD
提交和工作树中的副本。)或:
git ls-files --others
列出工作区中存在但不在索引中的文件名。这并不涉及HEAD
提交中的副本。
git ls-files --modified
列出索引中与其在HEAD
提交中的副本不同(或根本不在HEAD
提交中)的文件(名称)。没有选项:
git ls-files
列出索引中的文件名称,不考虑HEAD
提交或工作树中有哪些文件。
index
是否保存了文件的副本,相反,index
保存了“名称(40个字符长的sha1)”,该名称可以在.git/objects
文件夹中找到。100644 802992c4220de19a90767f3000a79a31b98d0df7 0 README.md
上面这行是从index
中提取出来的,而不是文件README.md
的副本。这只是工作树中文件的名称,哈希值是key
,git
用它来查找objects
文件夹中的blob
。 - Ivan Ruskigit ls-files
会显示 Git 索引中的文件(如果有的话)。如果你运行了 git clone -n
(不检出),那么索引将为空,因此这将不显示任何内容。否则,它们将是 Git 在检出期间推入其索引中的文件,这些文件将是与您的工作树中出现的文件集相同的文件集。请注意,在检出之后,您可以删除一些或所有这些工作树文件,而不会影响索引副本。Git 会抱怨一下,但您仍然可以创建包含所有文件的新提交! - torekHEAD
可能是对不存在分支名称的符号引用)。通过HEAD
读取提交哈希ID,然后检查相应的树对象。从shell中,您可以使用git ls-tree -r HEAD
来执行此操作。Git可以创建符号链接,但通常不会创建空目录;空目录情况仅适用于gitlinks(子模块部分)。 - torek我想分享一下:
参考已接受的答案https://dev59.com/N1MI5IYBdhLWcg3wcK_K#56242906以及与https://stackoverflow.com/users/1256452/torek的讨论:
如果问题是,如果我检出了一个特殊的提交,如何找出哪些文件/对象应该在那里,另一个答案可能是:
git ls-tree -r -l HEAD
git ls-tree -r -l commit-hash
100755 blob fd16d5168d671b8f9a8a8a6a140d3f7b5dacdccd git-flow
100644 blob 55198ad82cbfe7249951aa75f1373a476997d33a git-flow-feature
100644 blob ba485f6fe4b7d9c35bc01d2a6bd4ae201bccc9bd git-flow-hotfix
100644 blob 5b4e7e807423279d5983c28b16307e40dfdb51d7 git-flow-init
100644 blob cb95bd486deb7089939362705d78b2197893f578 git-flow-release
100644 blob cdbfc717c0f1eb9e653a4d10d7c4df261ed40eab git-flow-support
100644 blob 8c314996c0ac31f1396c48af5c6511124002dab7 git-flow-version
100644 blob 33274053347f4eec2f27dd8bceca967b89ae02d5 gitflow-common
120000 blob 7b736c183c7f6400b20ea613183d74a55ead78b5 gitflow-shFlags
160000 commit 2fb06af13de884e9680f14a00c82e52a67c867f1 shFlags
我的理解:
哈希似乎是“blob校验和”(不是提交哈希)。如果一个提交中有多个文件,则相同的校验和可能会出现多次。例如,100644的最后三个尼布尔看起来像是Linux文件访问属性(rw-r--r--)。如果对象不是常规文件,则前三个尼布尔不是100。在实际生活中,gitflow-shFlags是一个符号链接,shflags是一个子模块目录。
编辑: 刚刚偶然发现https://github.com/git/git/blob/master/Documentation/technical/index-format.txt(GOOGLE:git --index-info,STACKOVERFLOW:git索引到底包含什么?)
32-bit mode, split into (high to low bits)
4-bit object type
valid values in binary are 1000 (regular file), 1010 (symbolic link)
and 1110 (gitlink)
3-bit unused
9-bit unix permission. Only 0755 and 0644 are valid for regular files.
Symbolic links and gitlinks have value 0 in this field.
git ls-files
工作正常。由于你的git status
显示X文件已从工作目录中删除,这意味着该文件仍存在于索引中。这就是为什么git ls-files
会显示X,因为该命令显示了索引内容。
现在,你需要从索引中删除该文件,只需运行:
git rm --cached <pathToXFile>
git ls-files
" 学会了 "--sparse
" 选项,以帮助调试。git sparse checkout
命令后 一起使用。derrickstolee
)提交)。gitster
--合并于提交 3c0e417,2022年1月10日)
ls-files
: 添加 --sparse 选项签名作者:Derrick Stolee
现有的 'git ls-files
(man)' 调用者期望的是文件名,而不是目录。在这种情况下,最好展开稀疏索引以显示其中包含的所有文件。
然而,专家用户可能希望检查索引本身的内容,包括哪些目录是稀疏的。
添加 --sparse
选项以允许用户请求此信息。
在测试过程中,我注意到像 --modified
这样的选项并不影响那些在稀疏检出定义之外的文件的输出。
git ls-files
现在在其手册页面中包括以下内容:
--sparse
如果索引是稀疏的,则显示稀疏目录而不扩展到包含的文件。
稀疏目录将显示为带有尾随斜杠的形式,例如对于稀疏目录"x
",将显示为"x/
"。
git rm --cached
或者如果您还希望它从工作树中消失,只需使用git rm
。你会发现在其他情况下,Git处理正在进行的工作的方式避免了无用的繁琐操作。重要的是,这就是Git处理正在进行的工作的方式:它会一直停留在索引中,直到你决定如何处理它。只要你不告诉Git放置其他东西,Git就会默默地携带你添加的内容。
git status
显示了什么? - Nghia Buigit help ls-files
says - jthill