Aggiungi ricorsivamente file per modello


172

Come faccio ad aggiungere in modo ricorsivo i file tramite un pattern (o glob) situato in directory diverse?

Ad esempio, vorrei aggiungere A/B/C/foo.javae D/E/F/bar.java(e diversi altri file java) con un solo comando:

git add '*.java'

Sfortunatamente, ciò non funziona come previsto.


2
Funziona per me (Mac OS X, Git 1.7.1+). Quale versione di OS e Git stai usando?
Chris Johnsen,

3
Se .javanella directory corrente sono presenti alcuni file (già tracciati) , è possibile che si stia eseguendo una complessa gestione dei caratteri jolly tra bash e "helper" della riga di comando msys . Non sono sicuro di una soluzione. Potresti provare più livelli di virgolette: git add '"*.java"'(le virgolette singole sono prese da bash per impedire l'espansione glob, le virgolette doppie sono prese dal livello msys per prevenire l'espansione glob).
Chris Johnsen,

1
Grazie per la nota. Sfortunatamente, neanche quello funziona. Dicono che il problema è stato risolto, ma ho già l'ultima versione.
Michel Krämer,


1
git add *.javafunziona per me (su PowerShell con client GitHub)
ThaDafinser

Risposte:


89

La risposta di Sergio Acosta è probabilmente la soluzione migliore se alcuni dei file da aggiungere potrebbero non essere già tracciati. Se vuoi limitarti ai file che Git conosce già, potresti combinarli git-ls-filescon un filtro:

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

Git non fornisce alcun meccanismo di fantasia per farlo da solo, poiché è fondamentalmente un problema di shell: come si ottiene un elenco di file da fornire come argomenti a un determinato comando.


8
Grazie! Ho leggermente migliorato il tuo comando e ora sta facendo quello che stavo cercando:git ls-files -co --exclude-standard | grep '\.java$' | xargs git add
Michel Krämer,

169

È possibile utilizzare git add [path]/\*.javaper aggiungere file Java da sottodirectory,
ad esempio git add ./\*.javaper la directory corrente.

Dalla git adddocumentazione :

Aggiunge contenuto da tutti i *.txtfile nella Documentationdirectory e nelle sue sottodirectory:

$ git add Documentation/\*.txt

Si noti che l'asterisco *è citato dalla shell in questo esempio; questo consente al comando di includere i file dalle sottodirectory della Documentation/directory.


2
@ MichelKrämer probabilmente non lo era, ma lo è ora.
Alberto

7
Questa è la soluzione migliore, funziona anche su Windows.
TheTo

1
"l'asterisco * è citato dalla shell". Penso che intendi "fuggito". In ogni caso, la barra rovesciata impedisce alla shell di espanderla.
Gwideman,

1
@gwideman Penso che tu abbia ragione, ma non sono io. È una citazione dai documenti git-scm.com/docs/git-add#_examples
Sergey Glotov

62

Con zshte puoi eseguire:

git add "**/*.java"

e tutti i tuoi *.javafile verranno aggiunti in modo ricorsivo.


Grazie per quello, ma sto lavorando con msysgit su Windows e ha solo un bash.
Michel Krämer,

1
Bene, vedo che esiste una zshshell per Windows ... ti farai un favore per usarla invece di bash, imho.
Olivier Verdier,

1
La porta Windows di zsh si basa su una versione molto vecchia e si blocca continuamente (ad esempio quando entro ls).
Michel Krämer,

Wow, perfetto. Non sapevo di quella funzione!
Tomáš Votruba,

1
Questo non ha nulla a che fare con zsh. Penso che questa risposta manchi al punto che vuoi passare il percorso con i caratteri jolly intatti per git e lasciare che git la elabori. Pertanto, si desidera impedire a qualsiasi shell che si sta utilizzando di espandere i caratteri jolly. Per fare questo è necessario citare in qualche modo appropriato per la shell che si sta utilizzando. Vedi altre risposte per i dettagli.
Gwideman,

55

Un po 'fuori tema (non specificamente correlato a git) ma se sei su linux / unix una soluzione alternativa potrebbe essere:

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

E se ti aspetti percorsi con spazi:

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

Ma so che non è esattamente quello che hai chiesto.


6
Problema minore con questo approccio: se "trovi" un file corrispondente al tuo .gitignore, git si lamenta che stai provando ad aggiungere un file che gli hai detto di ignorare.
yo

2
@yoyo - Ho appena aggiunto -f alla fine, e che fissi che
Maslow

5
@Maslow, che aggiungerà forzatamente il file, anche se avrebbe dovuto essere ignorato (basato su .gitignore). Preferirei ricevere il reclamo e non aggiungere il file (che è il comportamento predefinito.)
yoyo

In che modo è meglio che lasciare che git esegua l'espansione jolly?
Gwideman,

12

La risposta di Sergey (non attribuirmi credito) sta funzionando:

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

con un recente git:

$git version
git version 1.7.3.4

File per il 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

Stato Git:

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

Aggiunta di * .txt:

$git add \*.txt

Stato aggiornato:

$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

Se stai già monitorando i tuoi file e hai apportato modifiche a loro e ora vuoi aggiungerli selettivamente in base a un modello, puoi usare il --modifiedflag

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

Ad esempio, se desideri solo aggiungere le modifiche CSS a questo commit, puoi farlo

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

Vedi man git-ls-filesper più bandiere


5

Basta usare git add *\*.java. Ciò aggiungerà tutti i file .java nella directory principale e tutte le sottodirectory.


Bella risposta. Ho aggiunto git * / pom.xml per aggiungere tutti i nomi di file pom.xml.
Philip Rego,

4

Aggiunta di una soluzione della riga di comando di Windows non ancora menzionata:

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

3

Volevo solo aggiungere file con una determinata stringa basata su git status:

git status | grep string | xargs git add

e quindi è stato in grado di git commit -m 'commit msgeseguire il commit di tutti i file modificati con "stringa" nel titolo del file


2

Come accennato in " git: come posso aggiungere ricorsivamente tutti i file in una sottostruttura di directory che corrispondono a un modello glob? ", Se fuggi correttamente o citi il ​​tuo globbing pathspec (come '*.java'), quindi sì, git add'*.java'

Git 2.13 (Q2 2017) migliora quello per l'aggiunta interattiva:

Vedi commit 7288e12 (14 marzo 2017) di Jeff King ( peff) .
(Unita da Junio ​​C Hamano - gitster- in commit 153e0d7 , 17 mar 2017)

add --interactive: non espande pathspecs con ls-files

Quando vogliamo ottenere l'elenco dei file modificati, espandiamo prima tutti i pathspec forniti dall'utente con " ls-files", quindi alimentiamo l'elenco risultante dei percorsi come argomenti a " diff-index" e " diff-files".
Se pathspec si espande in un gran numero di percorsi, potresti riscontrare uno dei due problemi seguenti:

  1. Il sistema operativo potrebbe lamentarsi delle dimensioni dell'elenco degli argomenti e rifiutarsi di eseguire. Per esempio:

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

Questo è sul linux.gitrepository, che ha circa 20K file nella directory "drivers" (nessuno di questi è stato modificato in questo caso). Il " ulimit -s" trucco è necessario per mostrare il problema su Linux anche per un insieme così enorme di percorsi.
Altri sistemi operativi hanno limiti molto più piccoli (ad esempio, è stato visto un caso reale con solo file 5K su OS X).

  1. Anche quando funziona, è molto lento. Il codice pathspec non è ottimizzato per un numero enorme di percorsi. Ecco lo stesso caso senza l'ulimit:

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

Possiamo migliorarlo saltando " ls-files" completamente, e semplicemente alimentando i pathspec originali ai comandi diff.

Storicamente il linguaggio pathspec supportato da " diff-index" era più debole, ma non è più così.


1

mettere la linea in ~ / .gitconfig

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

Se vuoi aggiungere tutto il file java modificato puoi semplicemente fare: git addt java

Samely, se vuoi aggiungere tutto il file Python modificato puoi semplicemente fare: git addt py

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.