Git add 不能处理 .png 文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2899875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 04:18:40  来源:igfitidea点击:

Git add not working with .png files?

git

提问by DLaw

I have a dirty working tree, dirty because I made changes to source files and touched up some images. I was trying to add just the images to the index, so I ran this command:

我有一个脏的工作树,脏是因为我对源文件进行了更改并修改了一些图像。我试图只将图像添加到索引中,所以我运行了这个命令:

git add *.png

But, this doesn't add the files. There were a few newimage files that were added, but none of the ones that were modified/pre-existing were added.

但是,这不会添加文件。添加了一些新的图像文件,但没有添加任何修改/预先存在的图像文件。

What gives?

是什么赋予了?

Edit: Here is some relevant terminal output

编辑:这是一些相关的终端输出

$ git status
# On branch master
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   src/main/java/net/plugins/analysis/FormMatcher.java
#   modified:   src/main/resources/icons/doctor_edit_male.png
#   modified:   src/main/resources/icons/doctor_female.png
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   src/main/resources/icons/arrow_up.png
#   src/main/resources/icons/bullet_arrow_down.png
#   src/main/resources/icons/bullet_arrow_up.png
no changes added to commit (use "git add" and/or "git commit -a")

Then executed "git add *.png" (no output after command)

然后执行“git add *.png”(命令后无输出)

Then:

然后:

$ git status
# On branch master
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   src/main/resources/icons/arrow_up.png
#   new file:   src/main/resources/icons/bullet_arrow_down.png
#   new file:   src/main/resources/icons/bullet_arrow_up.png
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   src/main/java/net/plugins/analysis/FormMatcher.java
#   modified:   src/main/resources/icons/doctor_edit_female.png
#   modified:   src/main/resources/icons/doctor_edit_male.png

回答by Cascabel

Michael Mrozek's comment is essentially the answer. *.pngmatches files of that name in the current directory, not in subdirectories. If you want to add ones in a subdirectory, do so:

Michael Mrozek 的评论基本上就是答案。*.png匹配当前目录中该名称的文件,而不是子目录中的文件。如果要在子目录中添加,请执行以下操作:

git add src/main/resources/icons/*.png

Or, depending on your shell, you may be able to do:

或者,根据您的外壳,您可以执行以下操作:

git add **/*.png

The point is that it's the shell that does the globbing (expands *.png into a list of filenames). Git has nothing to do with that; it just takes the arguments the shell gives it.

关键是它是执行 globbing 的 shell(将 *.png 扩展为文件名列表)。Git 与此无关;它只需要 shell 给它的参数。

Edit: Since this managed to get accepted, I should go ahead and point out as others did that some git commands do support globbing internally (via fnmatch), so if you quote a glob pattern, it'll be passed unmodified by the shell to git, where the globbing expansion will take place.

编辑:由于这设法被接受,我应该继续指出一些 git 命令确实在内部支持通配符(通过 fnmatch),所以如果你引用一个通配符模式,它会被 shell 未经修改地传递给git,全局扩展将发生的地方。

回答by Chris Johnsen

Some of Git's commands (including git add) can handle filename patterns themselves. But first you have to make sure the pattern gets to Git.

Git 的一些命令(包括git add)可以自己处理文件名模式。但首先你必须确保模式进入 Git。

In general, unquoted patterns may not make it to the invoked command. As a special case, if the pattern matches no files (in the current directory if there is no slash in the pattern), bashwill pass the unexpanded pattern to the command (unless the nullgloboption is set, in which case the pattern argument will be dropped from the arguments passed to the command). But the behavior varies among shells. By default, zshissues an error like “no matches found” unless the nomatchoption is unset (passes the unexpanded pattern as an argument) or the null_globoption is set (drops the pattern from the list of arguments).

通常,未引用的模式可能无法进入调用的命令。作为一种特殊情况,如果模式不匹配任何文件(如果模式中没有斜杠,则在当前目录中),bash会将未扩展的模式传递给命令(除非nullglob设置了该选项,在这种情况下,模式参数将是从传递给命令的参数中删除)。但行为因壳而异。默认情况下,zsh 会发出类似“未找到匹配项”的错误,除非nomatch选项未设置(将未扩展的模式作为参数传递)或null_glob选项已设置(从参数列表中删除模式)。

So using unquoted patterns and expecting them to get to the underlying command is only reliable if you know the behavior of your shell and you know the contents of any directories specified in the pattern (usually just the current directory for patterns without a slash).

因此,仅当您知道 shell 的行为并且知道模式中指定的任何目录的内容(对于没有斜线的模式通常只是当前目录)的内容时,使用不带引号的模式并期望它们到达底层命令才是可靠的。

So, for maximum reliability, if you want git addto get the literal string *.pngas an argument, then you should quote it.

因此,为了获得最大的可靠性,如果您想git add将文字字符串*.png作为参数,那么您应该引用它。

git add \*.png
git add "*.png"
git add '*'.png
# etc.


Once you have successfully passed a filename pattern to Git, you will encounter some differences from how shells handles them.

一旦你成功地将文件名模式传递给 Git,你会遇到一些与 shell 处理它们的方式不同的地方。

The primary difference of concern in this question is that matching is done by fnmatch(3)withoutFNM_PATHNAME set. This means that a pattern like *.pngwill match a file foo.pngin the current directory (just like a shell), but it will also match dir/bar.png(because without FNM_PATHNAME the *can match against the slash). Git calls its patterns “pathspecs” to differentiate them from shell “glob” patterns.

这个问题的主要区别在于匹配是由fnmatch(3)完成的,没有设置 FNM_PATHNAME。这意味着模式 like*.png将匹配foo.png当前目录中的文件(就像 shell 一样),但它也会匹配dir/bar.png(因为没有 FNM_PATHNAME*可以匹配斜杠)。Git 将其模式称为“pathspecs”,以将它们与 shell 的“glob”模式区分开来。

Unfortunately, there is an inconsistency in the way that git addhandles pathspecs. It always applies them to untracked files, but it never applies them to tracked files (instead, filename-type arguments like pathspecs are only checked for exact matches against the list of tracked files). This is apparently exactly what the OP actually ran into, as it would add newfiles that match the pathspec, but would fail to update (already) tracked files that match the pathspec.

不幸的是,git add处理路径规范的方式不一致。它总是将它们应用于未跟踪的文件,但从不将它们应用于跟踪的文件(相反,文件名类型参数如 pathspecs 只检查与跟踪文件列表的完全匹配)。这显然正是 OP 实际遇到的问题,因为它会添加与路径规范匹配的文件,但无法更新(已经)与路径规范匹配的跟踪文件。

Jefromi's workaround (git add **/*.png) works as long as your shell supports the **extended pattern (or an equivalent).

git add **/*.png只要您的 shell 支持**扩展模式(或等效模式),Jefromi 的解决方法 ( ) 就可以工作。

You can actually make Git do the work, but using the shell is probably easier (if your shell supports it).

您实际上可以让 Git 来完成这项工作,但使用 shell 可能更容易(如果您的 shell 支持它)。

# update all tracked files matching the Git pathspec *.png
git ls-files --cached -z \*.png | git update-index --add -z --stdin


Smoothing out Git's internal pathspec handling is a “medium term” goal, but not one that anyone with the time, interest, and pertinent experience has stepped forward to fix.

平滑 Git 的内部路径规范处理是一个“中期”目标,但不是任何有时间、兴趣和相关经验的人都可以上前修复的目标。

It was brought up as a project idea for Google Summer of Code 2010(not picked up by anyone), and related issues come up on the mailing list once in a while (In January and again in March 2010 someone reported a symptom much like the OP's, Git's maintainer explained what he would like to see in the long term).

它是作为Google Summer of Code 2010 的一个项目创意提出的(没有被任何人接受),并且相关问题偶尔会出现在邮件列表中(2010 年 1 月和 2010 年 3 月,有人报告了类似OPGit 的维护者解释了他希望看到的长期结果)。

回答by VonC

In doubt, try:

有疑问,请尝试:

git -A -- *.png 

, which might be more comprehensive (git addman page)

,这可能更全面(git add手册页

-A
--all

Like -u, but match <filepattern>against files in the working tree in addition to the index.
That means that it will find new files as well as staging modified content and removing files that are no longer in the working tree.

-u,但<filepattern>除了索引之外还与工作树中的文件匹配。
这意味着它将查找新文件以及暂存修改后的内容并删除不再位于工作树中的文件。

See SO question "Difference of “git add -A” and “git add ."

见SO问题“ git add -A”和“ git add .”的区别

回答by Cameron Lowell Palmer

Case-insensitive file systems like Mac OS X's default setup will also play havoc. If you change 'directory' to 'Directory' you will not get git to recognize it unless you move to another temp folder, commit, move back, and commit again.

不区分大小写的文件系统(如 Mac OS X 的默认设置)也会造成严重破坏。如果您将“目录”更改为“目录”,除非您移动到另一个临时文件夹、提交、移回并再次提交,否则您将无法让 git 识别它。

回答by Ram

git ls-filesis a good way to list everything in your git repo

git ls-files是列出 git repo 中所有内容的好方法

For your case you can do something like

对于您的情况,您可以执行以下操作

git ls-files --modified | grep '\.png$' | xargs git add

List the modified files, filter by extension (.png in this case) and git add the resultant entries

列出修改后的文件,按扩展名过滤(在这种情况下为 .png)并 git 添加结果条目