按模式递归添加文件


172

如何通过位于不同目录中的模式(或glob)递归添加文件?

例如,我想用一个命令添加A/B/C/foo.javaD/E/F/bar.java(以及其他几个Java文件):

git add '*.java'

不幸的是,这不能按预期工作。


2
它适用于我(Mac OS X,Git 1.7.1+)。您正在使用哪个OS和Git版本?
克里斯·约翰森

3
如果.java当前目录中有一些文件(已经被跟踪),则可能是bash和msys命令行“ helper” 之间遇到了复杂的通配符处理。我不确定解决方案。您可以尝试使用多层引号:git add '"*.java"'bash采用单引号以防止glob扩展,msys层采用双引号以防止glob扩展)。
克里斯·约翰森

1
感谢您的来信。不幸的是,这也不起作用。他们说该问题已得到修复,但是我已经有了最新版本。
MichelKrämer2010年


1
git add *.java为我工作(与GitHub客户端
一起

Answers:


88

如果某些要添加的文件可能尚未被跟踪,Sergio Acosta的答案可能是最好的选择。如果要限制自己使用git已经知道的文件,可以将其git-ls-files与过滤器结合使用:

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

Git本身并没有提供任何出色的机制,因为这基本上是一个shell问题:如何获取文件列表以作为给定命令的参数提供。


8
谢谢!我稍微改善了您的命令,现在它正在执行我想要的操作:git ls-files -co --exclude-standard | grep '\.java$' | xargs git add
MichelKrämer2010年

169

您可以用来git add [path]/\*.java从子目录添加Java文件,
例如git add ./\*.java用于当前目录。

git add文档

从目录及其子目录*.txt下的所有文件添加内容Documentation

$ git add Documentation/\*.txt

注意,*在此示例中,星号是从外壳引号引起的;这使命令可以包含Documentation/目录子目录中的文件。


2
@MichelKrämer可能不是,但是现在。
阿尔贝托

7
这是最好的解决方案,也适用于Windows。
TheTFo 2014年

1
“星号*从外壳引用”。我认为您的意思是“逃脱”。在任何情况下,反斜杠都会阻止外壳扩展。
gwideman

1
@gwideman我认为您是对的,但不是我。摘自docs git-scm.com/docs/git-add#_examples
Sergey Glotov

62

有了zsh你就可以运行:

git add "**/*.java"

并且您的所有*.java文件将被递归添加。


谢谢你,但是我正在Windows上使用msysgit,它只有一个bash。
米歇尔·克雷默(MichelKrämer)2010年

1
好吧,我看到有一个zsh用于Windows 的外壳……您会帮自己使用它而不是bash,恕我直言。
Olivier Verdier,2010年

1
zsh的Windows端口基于一个非常旧的版本,并且始终崩溃(例如,当我输入时ls)。
MichelKrämer2010年

哇,完美。我不知道该功能!
托马什Votruba

1
这与zsh无关。我认为这个答案错过了要传递通配符完整路径到git并让git处理它的观点。因此,您想防止正在使用的任何外壳扩展通配符。为此,您需要使用适合您所用外壳的某种方式对其进行引用。有关详细信息,请参见其他答案。
gwideman

55

有点不合主题(与git无关),但是如果您使用的是Linux / unix,则可以采用以下解决方法:

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

如果您希望路径带有空格:

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

但是我知道那不完全是您的要求。


6
这种方法的一个小问题-如果您“查找”与.gitignore匹配的文件,则git抱怨您正在尝试添加一个告诉它忽略的文件。
yoyo 2012年

2
@yoyo-我刚在末尾添加了-f,并且已解决该问题
Maslow

5
@Maslow,将强制添加文件,即使该文件应被忽略(基于.gitignore)。我宁愿让投诉,而不是添加文件(这是默认行为。)
YOYO

与让git执行通配符扩展相比,这有什么更好的方法?
gwideman

12

Sergey的回答(不要相信我)正在起作用:

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

最近的git:

$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

8

如果您已经在跟踪文件并对其进行了更改,现在您想根据模式有选择地添加它们,则可以使用该--modified标志

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

例如,如果您只想向此提交添加CSS更改,则可以执行

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

查看man git-ls-files更多标志



4

添加尚未提及的Windows命令行解决方案:

for /f "delims=" %G in ('dir /b/s *.java') do @git add %G

3

我只想基于添加具有特定字符串的文件git status

git status | grep string | xargs git add

然后能够git commit -m 'commit msg提交所有更改的文件,文件标题中带有“ string”


2

如“ git:如何在目录子树中以递归方式添加与glob模式匹配的所有文件? ”中所述,如果您正确地转义或引用了pathspec globbing(例如'*.java'),那么可以,git add'*.java'

Git 2.13(Q2 2017)改进了交互式添加:

参见Jeff King(提交7288e12(2017年3月14日(通过合并JUNIOÇ滨野- -提交153e0d7 3月17日2017)peff
gitster

add --interactive:不要使用 ls-files

当我们想要获取修改后的文件列表时,我们首先用“ ls-files” 扩展任何用户提供的pathspecs ,然后将生成的路径列表作为“ diff-index”和“ diff-files”的参数提供。
如果您的pathspec扩展为大量路径,则可能会遇到以下两个问题之一:

  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文件位于存储库中,在“ drivers”目录中大约有2万个文件(在这种情况下,没有一个文件被修改)。ulimit -s即使对于如此庞大的路径集,“ ”技巧对于显示Linux上的问题也是必需的。
其他操作系统的限制要小得多(例如,在OS X上只能看到5K文件的情况)。

  1. 即使它确实起作用,也确实很慢。pathspec代码并未针对大量路径进行优化。这是没有ulimit的情况:

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

我们可以通过ls-files完全跳过“ ”并仅将原始pathspec传递给diff命令来改善此效果。

从历史上看,“ diff-index” 支持的pathspec语言较弱,但现在不再如此。


1

将行放在〜/ .gitconfig中

[alias] addt = !sh -c 'git ls-files | grep \"\\.$1*\" | xargs git add' -

如果要添加所有修改过的java文件,可以这样做: git addt java

同样,如果您想添加所有修改后的python文件,可以执行以下操作: git addt py

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.