It's not clear how git ls-files
using wildcards actually functions.
I started with the git ls-files *.*
command which works okay. It shows all the files under version control in all the underlying subdirectories
But now I want to select a set of files. Example : "Device_*.xml"
So I execute git ls-files Device_*.xml
but this gives no result?!
I am aware the command is case sensitive. What is wrong? Below is the list of command's I execute with the output. Git version used : 2.6.1.windows.1
D:\GIT\repo>git clean -xdf
D:\GIT\repo>git reset --hard
HEAD
is now at 7de8f5b
[IP-826-generic-configuration-management-ticket] Merge remote-tracking branch 'origin' into IP-826-generic-configuration-management-ticket
D:\GIT\repo>git status
On branch IP-826-generic-configuration-management-ticket
Your branch is up-to-date with 'origin/IP-826-generic-configuration-management-ticket'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
nothing added to commit but untracked files present (use "git add" to track)
D:\GIT\repo\Imagepipe\SettingsDB\GeneratedDevicesAllPlatforms>dir Device_*.xml /s
<LOT OF DEVICE_*.xml FILES HERE>
12/10/2015 10:46 681 Device_GeneratedDevices_0-0-0_0.xml
1 File(s) 681 bytes
Directory of D:\GIT\repo\Tools\DevTools\SettingsGenerator\SLIB2_GenerateSettings\Test\DB7\GeneratedDevices\D1
12/10/2015 10:46 1,997 Device_D1_0-0-0_0.xml
1 File(s) 1,997 bytes
Directory of D:\GIT\repo\Tools\DevTools\SettingsGenerator\SLIB2_GenerateSettings\Test\DB7\S_NOCHECK
12/10/2015 10:46 1,558 Device_S_NOCHECK_0-0-0_0.xml
1 File(s) 1,558 bytes
Directory of D:\GIT\repo\Tools\DevTools\SettingsGenerator\SLIB2_GenerateSettings\Test\DB7\S_TEST
12/10/2015 10:46 1,536 Device_S_TEST_0-0-0_0.xml
1 File(s) 1,536 bytes
Total Files Listed:
968 File(s) 14,032,982 bytes
0 Dir(s) 18,400,256,000 bytes free
D:\GIT\repo>git ls-files Device_*.xml
D:\GIT\repo>
**No result!**
The problem is that if you use the asterisk (*
) in a non-string environment, the command line interpreter will perform expansion itself: it will look to files in the directory, not necessary under version control and add these as argument. For example, say the directory contains a files:
foo-a.txt
foo-b.txt
and you call git ls-files foo-*.txt
, actually you call the command git ls-files foo-a.txt foo-b.txt
. Now it is possible thatfoo-c.txt
is under version control, but was once removed, and that foo-a.txt
and foo-b.txt
are not, resulting in the fact hat no file is listed.
If you however use the asterisk in a string environment, like git ls-files "foo-*.txt"
, the asterisk is interpreted by git
. So in case there is a file in the repository that matches the wildcard, it will be returned.
Example:
> git init
Initialized empty Git repository in /foo/bar/.git/
> ls
> touch foo-c.txt
> git add .; git commit -am 'foo-c'
[master (root-commit) 3523fc3] foo-c
1 file changed, 1 insertion(+)
create mode 100644 foo-c.txt
> rm foo-c.txt
> git ls-files
foo-c.txt
> git ls-files foo-*.txt
fish: No matches for wildcard 'foo-*.txt'.
git ls-files foo-*.txt
^
> git ls-files 'foo-*.txt'
foo-c.txt
> touch foo-a.txt
> touch foo-b.txt
> git ls-files 'foo-*.txt'
foo-c.txt
> git ls-files foo-*.txt
In the example, we first setup a git repository, then we create a file foo-c.txt
. Now we add that file and make a commit. Next we remove the file. If we now call git ls-files foo-*.txt
, it is fish
(the shell) that complains that no such file can be found. If we however pass foo-*.txt
in a string, git
has no problem matching foo-c.txt
.
If we later add foo-a.txt
and foo-b.txt
to the directory, by performing the wildcard outside the string environment, git
gets git ls-files foo-a.txt foo-b.txt
, but since no such file is under subversioning, it returns nothing (it cannot find these files). If you however use a wildcard withing a string, again it will come up with foo-c.txt
.