为什么“Git add*”会让一些文件未保存?

2024-10-02 08:14:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Django项目中初始化了一个新的git回购。所有文件(包括子目录和pipfile中的文件)都是在我运行git add*时暂存的,除了\u atomic-writegxd2tirf文件。为什么这个被排除在外


Tags: 文件项目djangogitaddpipfileatomicwritegxd2tirf
2条回答

现在,您已经通过几个不同的命令(特别是git addecho)体验到了这一点,是时候进行概括了

在类Unix系统(包括Linux、macOS终端windows等)上,或者在windows上使用bash作为命令解释器时,您使用的是一种称为shell的编程语言。有不同的shell编程语言(bash、dash、sh、zsh、fish等等,出于历史原因,大多数都倾向于在名称中使用sh),但它们都倾向于共享某些属性。其中之一是它们如何扩展要传递给命令的命令行参数

$ mkdir t && cd t && touch .a .b c d e
$ ls -A
.a      .b      c       d       e
$ echo *
c d e

在这个临时目录中有五个文件1(除了标准的两个名为...的文件ls -A省略)。但是echo *只扩展到其中三个。这是因为*扩展故意忽略了名称2.开头的任何文件

有些shell有一个选项可以打开或关闭此选项:例如,在bash中,可以设置dotglob选项。(用户可能不应该过多地摆弄这些选项,以免在使用其他人的shell或其他shell时感到意外,但最好知道它们的存在。)

Shell编程语言主要是围绕运行其他程序的思想而构建的。因此,当shell生成一个提示符,如$>或shell的标准提示符,并且您键入一系列空格分隔的单词时,shell会将这些单词拆分,并将其中一个用作命令名,其余部分用作命令的参数,然后运行该命令。因此,输入:

git add *

让shell运行带有参数add*git命令。但是*本身被shell特别处理,扩展为文件名,不包括以点开头的文件名。因此git命令只能看到参数:

add
c
d
e

(每行一个参数)。git的第一个参数是子命令,在本例中是add,其余参数由子命令解释。3

由于*被shell扩展,Git从来没有看到过*,也从来没有机会用*做自己的事情。但是,您可以保护*不受shell的影响:

*

在这里,shell将双引号视为一种保护。这使得shell无法解释*。shell本身解释了双引号,因此echo没有看到双引号。它只看到星号*

$ echo '"*"'
"*"

这次我使用单引号作为外层。它们还告诉shell保护内容,即不要解释双引号星号。所以这次echo看到了双引号和星号

shell的引用规则因shell而异,这可能会变得非常复杂。所有这些都与Git本身无关:不管运行哪个命令,shell都在执行相同的解释

如果您确实设法将文字星号传递给Git,Git将自己解释星号,并且它的解释不同于shell。因此git add '*'的行为不同

如果您使用Windows和CMD.EXE,请注意CMD.EXE本身的可编程性不如shell,并且具有更简单的命令行规则。在某些方面,这使得它的使用更容易和更可预测。这是它的优点,也是它的缺点:典型Unix shell的可编程性使使用它们编写整个系统成为可能


1在Unix世界中,即使是目录(或文件夹,如果您喜欢该术语)也是一种文件。有时人们用file这个词来表示文件和目录,但因为我排除了...,这是目录文件,除了这个脚注,我不需要再提它了

2在类似Unix系统的分层文件系统中,文件不一定只有一个名称。这里,单词name实际上是指在一些包含目录中找到的组件名。例如,Git中的文件名可能是path/to/.file。但是,在Unix文件系统级别,这是一个名为path的目录,其中包含一个名为to的目录,其中包含一个组件名为.file的文件。对于shell,文件名的末尾部分有一个点,因此echo path/to/*将不匹配它

3这种将顶级命令与子命令结合使用的模式最近变得越来越普遍,但只有部分Unix系统是这样工作的。特别是在Python中,您可以使用argparse来模拟这种行为

git add*只处理名称不以“”开头的文件。 另一种方法可以是对所有文件运行git add.,或者对以“”(点)开头的文件名运行git add

相关问题 更多 >

    热门问题