我有一个本地存储库,并试图放弃自上次提交以来的所有更改
git checkout HEAD -- *
Run Code Online (Sandbox Code Playgroud)
命令。一切工作正常,即使更改是在某个子目录中。但是,当我添加一些未跟踪的文件(满足中的掩码.gitignore)时,将“Ignored.txt”添加到存储库的根目录中,上述命令失败并显示消息
error: pathspec 'Ignored.txt' did not match any file(s) known to git
Run Code Online (Sandbox Code Playgroud)
相比之下,
git checkout HEAD -- .
Run Code Online (Sandbox Code Playgroud)
按预期工作。所以我想知道:
.git 中通配符和通配符有什么区别*?
主要区别根本不在于 Git。
\n因为它不在 Git 中,所以是否有任何区别,如果有,区别是什么,取决于您使用的非 Git 命令解释器。
\n在 Unix-ish 系统(包括 Linux)上,它是为您扩展的命令解释器(或“shell”)。*各种 shell,例如bashandzsh和fishandtcsh等等dash(其中大多数名称以 结尾sh),解释*为“当前工作目录中的大多数文件”。这种扩展称为globbing。
这些 shell不会.以任何方式解释和扩展。这意味着:
git xyzzy -- .\nRun Code Online (Sandbox Code Playgroud)\ngit使用三个参数 、xyzzy、--和进行调用.。但:
git xyzzy -- *\nRun Code Online (Sandbox Code Playgroud)\ngit例如,如果当前工作目录中存在名为、、、、和的文件,则使用七个参数进行调用: xyzy、--、、、、 、 。abcdeabcde
Git 主要对存储在存储库中的提交感兴趣。为了构建新的提交,Git 使用其索引,该索引也存储在存储库中。索引实际上以特殊的、仅限 Git 的压缩格式保存文件\xe2\x80\x94,与提交中的内容基本相同。
\n文件的索引副本是可写的,而任何文件的提交副本都是只读的。(从技术上讲,Git 只是将对象保留在其主对象数据库中,索引和提交副本都只是对这些对象的引用。您不能覆盖任何对象,但可以添加新对象并切换索引引用;您不能更改提交\'引用。效果是提交中的文件被冻结,而索引中的文件被解冻/可写。)
\n这种仅限 Git 的内部文件格式对您(用户)和计算机上的大多数程序都没有用。所以这些文件必须被扩展。它们会扩展到您的工作树中,该工作树位于可能包含子目录(子文件夹)的目录(或文件夹)中。您可以将当前工作目录设置为这些工作树目录中的任何一个。然后 shell 将扩展*到工作树中当前目录中找到的文件的名称。
Git 主要使用您当前的工作目录来查找存储库数据库,Git 的真实文件位于其中。工作树副本仅供您随意摆弄。
\n当然,git checkout两者git add都以各种方式使用工作树。但请注意,由于工作树供您使用,因此您可以将存储库本身不存在的文件放入其中。
文件可以位于您的工作树中,但不能位于索引中。(索引实际上位于工作树和存储库“之间”,并为 Git 提供了一个存储将进入下一次提交的文件的位置。)处于此状态的文件\xe2\x80\ x94 在你的工作树中,但不在你的索引\xe2\x80\x94 中,据说是未跟踪的。
\nGit 本质上不知道未跟踪的文件。但它们位于您的工作树中(根据定义),因此如果这也是您当前的工作目录,并且您使用*shell 并将其扩展*为这些文件名,那么您将向 Git 传递一个它不包含的文件名目前还不知道。
如果您使用的命令是git add,您将告诉 Git:将此文件从工作树复制到索引中。 这将在索引中创建该文件,以便它现在将位于您进行的下一次提交中。Git 对此很满意!
但如果您使用的命令是git checkout,您将告诉 Git:将此文件从索引复制到工作树中。 Git 不会在索引中找到该文件,因此它会抱怨。(它不会触及工作树中的文件。)
请注意,未跟踪的文件也可以(但不一定)被忽略(这不是一个很好的术语,但它是 Git 使用的术语)。您可以通过在名为 的文件中列出文件名或名称模式来告诉 Git 不要抱怨未跟踪的文件.gitignore。在这种情况下,git add将警告您忽略未跟踪和忽略的文件:Git 不会将该文件复制到索引中,即使您使用git add *.
.如果使用git add .或git checkout -- .,shell 根本不会扩展。Git 看到.并知道这意味着“当前工作目录”,因此如果它合适,例如 \xe2\x80\x94,对于git add\xe2\x80\x94Git 将读取当前工作目录。它可以将在那里找到的文件与索引中已有的文件进行比较,并知道如何更新它们git add,包括不添加 (1) 未跟踪和 (2) 中列出的文件.gitignore。(根据定义,索引中已经存在的文件不会被忽略,因此这些文件也会从工作树更新到索引中。)
使用git checkout -- .,Git 直接查看索引,并且根本看不到未跟踪的文件。
上面的情况相当简单,但有几个特殊情况使它变得复杂:
\n大多数 shell在扩展 时不匹配点文件(例如.profile或) 。因此,如果您在当前目录中有文件和,并且使用,您可能不会将这些文件的索引版本复制到工作树中。.gitignore*.gitattributes.gitignoregit checkout -- *
如果当前目录中根本没有文件,或者没有与 glob 模式(如 )匹配的文件*.asdf,则某些 shell 会抱怨并中止该命令,但其他 shell 只是将模式 \xe2\x80\x94*.asdf甚至*\xe2\x80\x94on传递给您正在运行的程序。
DOS 风格的 CMD.EXE 不扩展*。
对于最后两种情况,Git 本身确实看到了*. 现在,Git有机会进行全局扩展,在 Git 的情况下,Git确实会匹配和.之类的文件。因此,如果当前工作目录没有non-dot-files,但有and ,并且您运行:.gitattributes.gitignore.gitattributes.gitignore
git checkout -- *\nRun Code Online (Sandbox Code Playgroud)\n那么在这种特殊情况下,Git 会将.gitattributes和.gitignore从索引复制到工作树。
| 归档时间: |
|
| 查看次数: |
2326 次 |
| 最近记录: |