Рекурсивно добавлять файлы по шаблону - PullRequest
149 голосов
/ 18 мая 2010

Как мне рекурсивно добавлять файлы по шаблону (или глобусу), расположенным в разных каталогах?

Например, я хотел бы добавить A/B/C/foo.java и D/E/F/bar.java (и несколько других файлов Java) одной командой:

git add '*.java'

К сожалению, это не работает, как ожидалось.

Ответы [ 11 ]

133 голосов
/ 24 февраля 2012

Вы можете использовать git add [path]/\*.java для добавления файлов Java из подкаталогов,
например git add ./\*.java для текущего каталога.

Из git add документации :

Добавляет содержимое из всех файлов *.txt в каталоге Documentation и его подкаталогах:

$ git add Documentation/\*.txt

Обратите внимание, что звездочка * указана в командной строке в этом примере; это позволяет команде включать файлы из подкаталогов каталога Documentation/.

78 голосов
/ 18 мая 2010

Ответ Серхио Акосты - это, вероятно, ваш лучший выбор, если некоторые из файлов, которые будут добавлены, возможно, еще не отслежены. Если вы хотите ограничить себя файлами, о которых git уже знает, вы можете объединить git-ls-files с фильтром:

git ls-files [path] | grep '\.java$' | xargs git add

Git не предоставляет каких-либо причудливых механизмов для того, чтобы делать это самому, поскольку это в основном проблема оболочки: как получить список файлов для предоставления в качестве аргументов для данной команды.

52 голосов
/ 18 мая 2010

Немного не по теме (не относится к git), но если вы используете linux / unix, обходной путь может быть:

find . -name '*.java' | xargs git add

А если вы ожидаете пути с пробелами:

find . -name '*.java' -print0 | xargs -0 git add

Но я знаю, что это не совсем то, что вы спросили.

48 голосов
/ 18 мая 2010

С zsh вы можете запустить:

git add "**/*.java"

и все ваши *.java файлы будут добавлены рекурсивно.

12 голосов
/ 14 марта 2012

Ответ Сергея (не верить мне) работает:

You can use git add [path]/\*.java

с недавним мерзавцем:

$git version
git version 1.7.3.4

Файлы для теста:

$find -name .git -prune -o -type f -print | sort
./dirA/dirA-1/dirA-1-1/file1.txt
./dirA/dirA-1/dirA-1-2/file2.html
./dirA/dirA-1/dirA-1-2/file3.txt
./dirA/dirA-1/file4.txt
./dirB/dirB-1/dirB-1-1/file5.html
./dirB/dirB-1/dirB-1-1/file6.txt
./file7.txt

Статус Git:

$git status -s
?? dirA/
?? dirB/
?? file7.txt

Добавление * .txt:

$git add \*.txt

Обновлен статус:

$git status -s
A  dirA/dirA-1/dirA-1-1/file1.txt
A  dirA/dirA-1/dirA-1-2/file3.txt
A  dirA/dirA-1/file4.txt
A  dirB/dirB-1/dirB-1-1/file6.txt
A  file7.txt
?? dirA/dirA-1/dirA-1-2/file2.html
?? dirB/dirB-1/dirB-1-1/file5.html
7 голосов
/ 13 апреля 2012

Если вы уже отслеживаете свои файлы и внесли в них изменения, и теперь вы хотите добавить их выборочно на основе шаблона, вы можете использовать флаг --modified

git ls-files --modified | grep '<pattern>' | xargs git add

Например, если вы хотите добавить только изменения CSS в этот коммит, вы можете сделать

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

См. man git-ls-files для дополнительных флагов

3 голосов
/ 20 декабря 2017

Просто используйте git add *\*.java. Это добавит все файлы .java в корневой каталог и все подкаталоги.

3 голосов
/ 27 июля 2017

Я хотел добавить только файлы с определенной строкой на основе git status:

git status | grep string | xargs git add

и затем смог git commit -m 'commit msg зафиксировать все измененные файлы со «строкой» в заголовке файла

2 голосов
/ 19 декабря 2018

Добавление решения командной строки Windows, которое еще не было упомянуто:

for /f %G in ('dir /b/s *.java') do @git add %G
2 голосов
/ 10 апреля 2017

Как упомянуто в " git: как мне рекурсивно добавить все файлы в поддерево каталога, которые соответствуют шаблону glob? ", если вы правильно экранировали или указали в кавычках свою спецификацию пути (например, '*.java'), тогда да, мерзавец добавить '*.java'

В Git 2.13 (второй квартал 2017 года) улучшено это для интерактивного добавления:

См. коммит 7288e12 (14 марта 2017 г.) Джефф Кинг (peff) .
(Объединено Junio ​​C Hamano - gitster - в коммит 153e0d7 , 17 марта 2017 г.)

add --interactive: не расширять спецификации путей с помощью ls-files

Когда мы хотим получить список измененных файлов, мы сначала расширяем любые предоставленные пользователем пути с помощью «ls-files», а затем передаем полученный список путей в качестве аргументов «diff-index» и «diff-files ».
Если ваша спецификация пути распространяется на большое количество путей, вы можете столкнуться с одной из двух проблем:

  1. ОС может пожаловаться на размер аргумента список, и отказаться от запуска. Например:

    $ (ulimit -s 128 && git add -p drivers)
    Can't exec "git": Argument list too long at .../git-add--interactive line 177.
    Died at .../git-add--interactive line 177.
    

Он находится в репозитории linux.git, в котором содержится около 20 КБ файлов в каталоге «drivers» (в этом случае ни один из них не был изменен). Трюк "ulimit -s" необходим, чтобы показать проблему в Linux даже для такого гигантского набора путей.
Другие операционные системы имеют гораздо меньшие ограничения (например, в реальных случаях был замечен только 5K файлов на OS X).

  1. Даже когда это работает, это действительно медленно. Pathspec код не оптимизирован для огромного количества путей. Вот тот же случай без ограничения:

    $ time git add -p drivers
      No changes.
    
    real  0m16.559s
    user    0m53.140s
    sys 0m0.220s
    

Мы можем улучшить это, полностью пропустив "ls-files" и просто передавая исходные спецификации путей командам diff.

Исторически язык спецификации пути, поддерживаемый "diff-index", был слабее, но это уже не так.

...