Git add not working with .png files?
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 new image files that were added, but none of the ones that were modified/pre-existing were added.
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 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
5 Solutions collect form web for “Git add not working with .png files?”
Michael Mrozek’s comment is essentially the answer.
*.png matches files of that name in the current directory, not in subdirectories. If you want to add ones in a subdirectory, do so:
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.
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.
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.
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), bash will pass the unexpanded pattern to the command (unless the
nullglob option 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, zsh issues an error like “no matches found” unless the
nomatch option is unset (passes the unexpanded pattern as an argument) or the
null_glob option is set (drops the pattern from the list of arguments).
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).
So, for maximum reliability, if you want
git add to get the literal string
*.png as an argument, then you should quote it.
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.
The primary difference of concern in this question is that matching is done by fnmatch(3) without FNM_PATHNAME set. This means that a pattern like
*.png will match a file
foo.png in 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.
Unfortunately, there is an inconsistency in the way that
git add handles 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 new files that match the pathspec, but would fail to update (already) tracked files that match the pathspec.
Jefromi’s workaround (
git add **/*.png) works as long as your shell supports the
** extended pattern (or an equivalent).
You can actually make Git do the work, but using the shell is probably easier (if your shell supports it).
# 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.
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).
In doubt, try:
git -A -- *.png
, which might be more comprehensive (
git add man page)
-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.
See SO question “Difference of “
git add -A” and “
git add .””
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.
git ls-files is a good way to list everything in your 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