Исправление должно быть осторожным, например ::1001*
git diff '*.cpp'
или
git diff \*.cpp
или более формально:
git diff -- '*.cpp'
или аналогичный.
Что здесь происходит?
Отсутствует вопрос: желаемым выводом был diff для subdir/subfile.cpp
, но верхний уровень рабочего дерева содержал один файл с именем file.cpp
или аналогичный.
Проблема связана с тем, что вы используете оболочку в стиле Unix / Linux, которая расширяет *
и другие символы подстановки или glob символов перед выполнение команды, которую вы вводите в командной строке. Но здесь есть и тонкость.
Поскольку в текущем каталоге существует файл с именем file.cpp
, при запуске:
git diff *.cpp
оболочка заменяет *.cpp
именами всех файлов, имя которых заканчивается на .cpp
, и поэтому выполняется:
git diff file.cpp
Затем Git покорно создает diff - или, в данном случае, no diff, поскольку разницы нет - для одного файла с именем file.cpp
.
Если в каталоге верхнего уровня есть нет файлов с именами file.cpp
или zorg.cpp
или аналогичными, эта оболочка просто вызывает git
с аргументами diff
и *.cpp
, как если бы вы указали звездочку. Это дает Git возможность расширить аргумент *.cpp
, а когда Git расширяет его, это происходит не так, как оболочка.
Зачем использовать --
?
Команда git diff
принимает несколько параметров, таких как -s
, -p
, -w
, --name-status
, --name-only
и т. Д.
В зависимости от того, какие у вас есть файлы, предположим, что вам нужен список diff для файла с именем -z
в текущем каталоге. Если вы затем запустите:
git diff -z
Git считает, что вы хотите указать -z
параметр вместо того, чтобы получить список diff для файла с именем -z
. Аналогичная проблема применяется, если вы хотите использовать diff для -z*
и т. П.
В общем, вы можете обойти эту проблему, используя имя файла ./-z
вместо -z
. Поскольку ./-z
не начинается с -
, Git не думает, что это вариант. Но эта проблема носит более общий характер и затрагивает и другие случаи (другие команды). Например, предположим, что у вас есть файл с именем develop
и вы выполняете:
git checkout develop
Git подумает, что вы хотите проверить ветку с именем develop
.
Все команды Git принимают --
в качестве разделителя , что обычно означает , больше никаких опций: что-либо после этой точки является аргументом вместо . Для git diff
все, что после --
обрабатывается как pathspec , что включает в себя расширение glob, при условии, что символы glob сделали его за оболочкой.
Это то, что описание синтаксиса в разделе SYNOPSIS документации git diff
означает:
git diff [<options>] [<commit>] [--] [<path>...]
git diff [<options>] --cached [<commit>] [--] [<path>...]
git diff [<options>] <commit> <commit> [--] [<path>...]
git diff [<options>] <blob> <blob>
git diff [<options>] --no-index [--] <path> <path>
Квадратные скобки указывают, что что-то не является обязательным, поэтому все параметры являются необязательными. Угловые скобки указывают, что некоторые аргументы должны быть заменены строкой, которая соответствует требованиям типа внутри скобок. Литерал --
или другие литеральные опции подразумевают, что вы должны вводить эти символы буквально, поэтому, например, git diff --cached
требует буквальную строку --cached
. Наконец, ...
означает «повторять предыдущее так часто, как вам нравится».
Поскольку буквенная строка --
является необязательной, вам не нужно ее вводить - но если вы это сделаете, все после должно иметь форму <path>
. Эта форма довольно общая: почти любой символ действителен. Однако в документации отсутствует перекрестная ссылка на определение pathspec (и, вероятно, здесь следует использовать <pathspec>
, а не просто <path>
). Полное описание pathspecs находится в gitglossary .