Pergunta

Como faço para adicionar arquivos recursivamente por um padrão (ou bola) localizados em diretórios diferentes?

Por exemplo, eu gostaria de acrescentar A/B/C/foo.java e D/E/F/bar.java (e vários outros arquivos java) com um comando:

git add '*.java'

Infelizmente, isso não funciona conforme o esperado.

Foi útil?

Solução

A resposta de Sergio Acosta é provavelmente a sua melhor aposta se alguns dos arquivos a serem adicionados ainda não serão rastreados. Se você quiser se limitar aos arquivos que o git já conhece, você pode combinar git-ls-files com um filtro:

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

O Git não fornece nenhum mecanismos sofisticado para fazer isso por conta própria, pois é basicamente um problema de shell: como você obtém uma lista de arquivos a serem fornecidos como argumentos a um determinado comando.

Outras dicas

Você pode usar git add [path]/\*.java Para adicionar arquivos Java dos subdiretos,
por exemplo git add ./\*.java para diretório atual.

A partir de git add documentação:

Adiciona conteúdo de todos *.txt arquivos abaixo Documentation Diretório e seus subdiretos:

$ git add Documentation/\*.txt

Observe que o asterisco * é citado no shell neste exemplo; Isso permite que o comando inclua os arquivos dos subdiretos de Documentation/ diretório.

Um tópico um pouco fora (não especificamente relacionado ao git), mas se você estiver no Linux/Unix, uma solução alternativa pode ser:

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

E se você espera caminhos com espaços:

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

Mas eu sei que isso não é exatamente o que você pediu.

Com zsh você pode correr:

git add "**/*.java"

e todos os seus *.java Os arquivos serão adicionados recursivamente.

Resposta de Sergey (Não me crédito) está funcionando:

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

com um git recente:

$git version
git version 1.7.3.4

Arquivos para o teste:

$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

Status do Git:

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

Adicionando *.txt:

$git add \*.txt

Status atualizado:

$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

Se você já está rastreando seus arquivos e fez alterações e agora deseja adicioná -los seletivamente com base em um padrão, você pode usar o --modified bandeira

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

Por exemplo, se você deseja adicionar apenas as alterações do CSS a esse compromisso, você pode fazer

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

Ver man git-ls-files Para mais bandeiras

Eu queria adicionar apenas arquivos que tinham uma certa string baseada em git status:

git status | grep string | xargs git add

e então foi capaz de git commit -m 'commit msg Para comprometer todos os arquivos alterados com "String" no título do arquivo

Apenas use git add *\*.java. Isso adicionará todos os arquivos .java no diretório raiz e todos os subdiretos.

Como mencionado no "git:Como faço para adicionar recursivamente todos os arquivos em um diretório subárvore que correspondem a um padrão glob?", se você corretamente escape ou citar de seu pathspec "globbing" (como '*.java') e, em seguida, sim, git add '*.java'

Git 2.13 (Q2 2017) melhora o que interactivo adicionar:

Ver cometer 7288e12 (14 de março de 2017) por Jeff King (peff).
(Intercalado por Junio C Hamano -- gitster -- no cometer 153e0d7, 17 de Mar de 2017)

add --interactive:não expanda pathspecs com ls-files

Quando queremos obter a lista de arquivos modificados, nós em primeiro lugar, expanda qualquer fornecido pelo usuário pathspecs com "ls-files"e, em seguida, alimentar a lista resultante de caminhos como argumentos para "diff-index"e "diff-files".
Se o seu pathspec se expande para um grande número de caminhos, você pode executar em um dos dois problemas:

  1. O SO pode reclamar do tamanho do argumento lista, e se recusam a executar.Por exemplo:

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

No linux.git repositório, que tem cerca de 20 MIL arquivos na pasta "drivers" de diretório (nenhum deles modificado neste caso).O "ulimit -s"o truque é necessário para mostrar o problema no Linux, mesmo para um gigantesco conjunto de caminhos.
Outros sistemas operacionais têm muito menor limites (por exemplo, um caso reais, foi visto com apenas 5K arquivos no mac OS X).

  1. Mesmo quando ela não funciona, é muito lento.O pathspec o código não é otimizado para um grande número de caminhos.Aqui o mesmo caso sem o ulimit:

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

Podemos melhorar esta ignorando "ls-files"completamente, e apenas alimentando o original pathspecs para o diff comandos.

Historicamente, o pathspec idioma suportado pelo "diff-index"foi mais fraco, mas que não é mais o caso.

Adicionando uma solução de linha de comando do Windows que ainda não foi mencionada:

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

Coloque a linha em ~/.gitconfig

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

Se você deseja adicionar todo o arquivo java modificado, pode apenas fazer:git addt java

Samely, se você deseja adicionar todo o arquivo python modificado, pode apenas fazer:git addt py

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top