The major区别根本不在于 Git。
因为它不在 Git 中,所以是否有什么区别,如果有的话,what差异取决于您使用的非 Git 命令解释器。
Shell 与 Git
在 Unix-ish 系统(包括 Linux)上,它是命令解释器(或“壳”)可扩展*
为你。各种外壳,例如bash
and zsh
and fish
and tcsh
and dash
等等(其中大多数的名字以sh
), 解释*
意思是“当前工作目录中的大多数文件”。这种扩展称为globbing https://en.wikipedia.org/wiki/Glob_(programming).
这些贝壳do not解释和扩展.
以任何方式。这意味着:
git xyzzy -- .
invokes git
具有三个参数,xyzzy
, --
, and .
. But:
git xyzzy -- *
invokes git
例如,有七个参数:xyzy
, --
, a
, b
, c
, d
, e
,如果有名为a
, b
, c
, d
, and e
在当前工作目录中。
Git 不太使用工作目录
Git 主要感兴趣的是commits,存储在存储库中。建造new提交,Git 使用它的index,也存储在存储库中。索引实际上以一种特殊的、仅限 Git 的压缩格式保存文件——与提交中的内容基本相同。
文件的索引副本是可写的,而任何文件的提交副本都是只读的。 (从技术上讲,Git 只是保留objects在其主对象数据库中,索引和提交副本都只是对这些对象的引用。您不能覆盖任何对象,但可以添加一个new对象并切换索引引用;您无法更改提交的引用。效果是提交中的文件被冻结,而索引中的文件被解冻/可写。)
这种仅限 Git 的内部文件格式对您(用户)和计算机上的大多数程序都没有用。所以这些文件have待扩大。它们会扩展到您的工作树,它位于可能具有子目录(子文件夹)的目录(或文件夹)中。您可以设置您的当前工作目录到任何这些工作树目录。然后外壳会膨胀*
到工作树中当前目录中找到的文件的名称。
Git 主要使用您当前的工作目录来查找存储库数据库,Git 的真实文件位于其中。工作树副本仅供您随意摆弄。
一些 Git 命令确实使用工作树
当然,git checkout
and git add
两者都以各种方式使用工作树。但请注意,由于工作树是用于your使用,您可以将文件放入其中不存在在存储库本身中。
文件可以位于您的工作树中,但不能位于索引中。 (实际上,索引位于工作树和存储库“之间”,并为 Git 提供了一个存储将进入工作树的文件的位置。next提交。)处于这种状态的文件(在您的工作树中,但不在索引中)被认为是未追踪的.
Git 本质上不知道未跟踪的文件。但它们位于您的工作树中(根据定义),因此如果这也是您当前的工作目录,并且您使用*
并让 shell 展开*
对于这些文件名,您将向 Git 传递一个它当前不知道的文件名。
如果您使用的命令是git add
,你会告诉 Git:将此文件从工作树复制到索引中。这将在索引中创建该文件,以便它现在将位于您进行的下一次提交中。 Git 对此很满意!
但如果你使用的命令是git checkout
,你会告诉 Git:将此文件从索引复制到工作树中。Git 不会在索引中找到该文件,因此它会抱怨。 (它不会触及工作树中的文件。)
请注意,未跟踪的文件也可以(但不一定)ignored(这不是一个很好的术语,但它是 Git 使用的术语)。您可以通过在名为 的文件中列出文件名或名称模式来告诉 Git 不要抱怨未跟踪的文件.gitignore
。在这种情况下,git add
会警告您忽略未跟踪和忽略的文件:Git 不会将该文件复制到索引中,即使您使用git add *
.
Git does知道关于.
如果你使用git add .
or git checkout -- .
,外壳根本不膨胀。 Git 看到.
并知道这意味着“当前工作目录”,因此如果合适的话,例如,对于git add
—Git 将读取当前工作目录。它可以将在那里找到的文件与索引中已有的文件进行比较,并知道如何更新它们git add
,包括not添加 (1) 未跟踪和 (2) 中列出的文件.gitignore
。 (文件是已经在根据定义,索引不会被忽略,因此它们也会从工作树更新到索引中。)
With git checkout -- .
,Git 直接查看索引,根本看不到未跟踪的文件。
特殊情况:“点文件”、根本没有文件和 CMD.EXE
上面的情况相当简单,但有几个特殊情况使它变得复杂:
-
大多数贝壳do not匹配点文件(例如.profile
or .gitignore
) 展开时*
。所以,如果你有文件.gitattributes
and .gitignore
在当前目录中,并使用git checkout -- *
,您可能不会将这些文件的索引版本复制到工作树中。
-
如果当前目录中根本没有文件,或者没有与 glob 模式匹配的文件,例如*.asdf
,一些 shell 抱怨并中止命令,但其他 shell 只是传递模式 -*.asdf
甚至*
—转到您正在运行的程序。
-
DOS 风格的 CMD.EXE 不扩展*
.
对于后两种情况,Git 本身does看到*
. Now Git有机会进行全局扩展,对于 Git 来说,Gitdoes match .
- 像这样的文件.gitattributes
and .gitignore
。所以如果当前工作目录有没有非点文件,但确实有.gitattributes
and .gitignore
,然后你运行:
git checkout -- *
那么在这种特殊情况下,Git 将复制.gitattributes
and .gitignore
从索引到工作树。