git 按模式递归添加文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2855140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 08:24:31  来源:igfitidea点击:

Recursively add files by pattern

gitglobfilepattern

提问by Michel Kr?mer

How do I recursively add files by a pattern (or glob) located in different directories?

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

For example, I'd like to add A/B/C/foo.javaand D/E/F/bar.java(and several other java files) with one command:

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

git add '*.java'

Unfortunately, that doesn't work as expected.

不幸的是,这并没有按预期工作。

采纳答案by Cascabel

Sergio Acosta's answer is probably your best bet if some of the files to be added may not already be tracked. If you want to limit yourself to files git already knows about, you could combine git-ls-fileswith a filter:

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

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

Git doesn't provide any fancy mechanisms for doing this itself, as it's basically a shell problem: how do you get a list of files to provide as arguments to a given command.

Git 本身没有提供任何奇特的机制来执行此操作,因为它基本上是一个 shell 问题:如何获取文件列表以作为给定命令的参数提供。

回答by Sergey Glotov

You can use git add [path]/\*.javato add java files from subdirectories,
e.g. git add ./\*.javafor current directory.

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

From git adddocumentation:

git add文档

Adds content from all *.txtfiles under Documentationdirectory and its subdirectories:

$ git add Documentation/\*.txt

Note that the asterisk *is quoted from the shell in this example; this lets the command include the files from subdirectories of Documentation/directory.

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

$ git add Documentation/\*.txt

请注意,*在此示例中,星号是从 shell 引用的;这让命令包含来自目录子目录的Documentation/文件。

回答by Olivier Verdier

With zshyou can run:

有了zsh你可以运行:

git add "**/*.java"

and all your *.javafiles will be added recursively.

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

回答by Sergio Acosta

A bit off topic (not specifically git related) but if you're on linux/unix a workaround could be:

有点离题(与 git 无关),但如果您使用的是 linux/unix,则解决方法可能是:

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

And if you expect paths with spaces:

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

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

But I know that is not exactly what you asked.

但我知道这不是你问的。

回答by Alberto

Sergey's answer(don't credit me) is working:

谢尔盖的回答(不要相信我)是有效的:

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

with a recent git:

使用最近的 git:

$git version
git version 1.7.3.4

Files for the test:

测试文件:

$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 status:

git状态:

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

Adding *.txt:

添加 *.txt:

$git add \*.txt

Updated status:

更新状态:

$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

回答by Ram

If you are already tracking your files and have made changes to them and now you want to add them selectively based on a pattern, you can use the --modifiedflag

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

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

For example, if you only want to add the CSS changes to this commit, you can do

例如,如果您只想将 CSS 更改添加到此提交,您可以这样做

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

See man git-ls-filesfor more flags

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

回答by Jan Lovstrand

Just use git add *\*.java. This will add all .java files in root directory and all subdirectories.

只需使用git add *\*.java. 这将添加根目录和所有子目录中的所有 .java 文件。

回答by selalerer

Adding a Windows command line solution that was not yet mentioned:

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

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

回答by bdanin

I wanted to only add files that had a certain string based on git status:

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

git status | grep string | xargs git add

git status | grep string | xargs git add

and then was able to git commit -m 'commit msgto commit all changed files with "string" in the title of the file

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

回答by VonC

As mentioned in "git: How do I recursively add all files in a directory subtree that match a glob pattern?", if you properly escape or quote your pathspec globbing (like '*.java'), then yes, git add '*.java'

如“ git: How do I recursively add all files in a directory subtree that match a glob pattern?”中所述,如果您正确转义或引用您的路径规范通配符(如'*.java'),那么是的,git add'*.java'

Git 2.13 (Q2 2017) improves that for interactive add:

Git 2.13(2017 年第二季度)改进了交互式添加:

See commit 7288e12(14 Mar 2017) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster--in commit 153e0d7, 17 Mar 2017)

请参阅Jeff King ( ) 的commit 7288e12(2017 年 3 月 14 日(由Junio C Hamano合并-- --commit 153e0d7,2017 年 3 月 17 日)peff
gitster

add --interactive: do not expand pathspecs with ls-files

When we want to get the list of modified files, we first expand any user-provided pathspecs with "ls-files", and then feed the resulting list of paths as arguments to "diff-index" and "diff-files".
If your pathspec expands into a large number of paths, you may run into one of two problems:

  1. The OS may complain about the size of the argument list, and refuse to run. For example:

    $ (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.
    

That's on the linux.gitrepository, which has about 20K files in the "drivers" directory (none of them modified in this case). The "ulimit -s" trick is necessary to show the problem on Linux even for such a gigantic set of paths.
Other operating systems have much smaller limits (e.g., a real-world case was seen with only 5K files on OS X).

  1. Even when it does work, it's really slow. The pathspec code is not optimized for huge numbers of paths. Here's the same case without the ulimit:

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

We can improve this by skipping "ls-files" completely, and just feeding the original pathspecs to the diff commands.

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存储库中,它在“驱动程序”目录中有大约 20K 个文件(在这种情况下它们都没有修改)。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完全跳过“ ”来改进这一点,只需将原始路径规范提供给 diff 命令。

Historically the pathspec language supported by "diff-index" was weaker, but that is no longer the case.

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