Secara rekursif menambahkan file berdasarkan pola

172

Bagaimana cara menambahkan file secara rekursif berdasarkan pola (atau gumpalan) yang terletak di direktori yang berbeda?

Sebagai contoh, saya ingin menambahkan A/B/C/foo.javadan D/E/F/bar.java(dan beberapa file java lainnya) dengan satu perintah:

git add '*.java'

Sayangnya, itu tidak berfungsi seperti yang diharapkan.

Michel Krämer
sumber
2
Ini berfungsi untuk saya (Mac OS X, Git 1.7.1+). Apa versi OS dan Git yang Anda gunakan?
Chris Johnsen
3
Jika Anda memiliki beberapa .javafile (sudah dilacak) di direktori Anda saat ini, Anda mungkin berlari ke, eh, penanganan wildcard yang rumit antara bash dan "helper" baris perintah msys . Saya tidak yakin tentang solusi. Anda dapat mencoba beberapa lapis tanda kutip: git add '"*.java"'(tanda kutip tunggal diambil oleh bash untuk mencegah ekspansi glob, tanda kutip ganda diambil oleh lapisan msys untuk mencegah ekspansi glob).
Chris Johnsen
1
Terima kasih atas catatannya. Sayangnya, itu juga tidak berhasil. Mereka mengatakan sudah diperbaiki, tetapi saya sudah memiliki versi terbaru.
Michel Krämer
1
git add *.javabekerja untuk saya (di PowerShell dengan klien GitHub)
ThaDafinser

Jawaban:

89

Jawaban Sergio Acosta mungkin adalah taruhan terbaik Anda jika beberapa file yang akan ditambahkan mungkin belum dilacak. Jika Anda ingin membatasi diri Anda pada file yang sudah diketahui git, Anda bisa menggabungkannya git-ls-filesdengan filter:

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

Git tidak menyediakan mekanisme mewah untuk melakukan ini sendiri, karena pada dasarnya masalah shell: bagaimana Anda mendapatkan daftar file untuk diberikan sebagai argumen untuk perintah yang diberikan.

Cascabel
sumber
8
Terima kasih! Saya sedikit memperbaiki perintah Anda dan sekarang melakukan apa yang saya cari:git ls-files -co --exclude-standard | grep '\.java$' | xargs git add
Michel Krämer
169

Anda dapat menggunakan git add [path]/\*.javauntuk menambahkan file java dari subdirektori,
misalnya git add ./\*.javauntuk direktori saat ini.

Dari git adddokumentasi :

Menambahkan konten dari semua *.txtfile di bawah Documentationdirektori dan subdirektori:

$ git add Documentation/\*.txt

Perhatikan bahwa tanda bintang *dikutip dari shell dalam contoh ini; ini memungkinkan perintah menyertakan file dari subdirektori Documentation/direktori.

Sergey Glotov
sumber
2
@ MichelKrämer mungkin bukan, tapi sekarang.
Alberto
7
Ini adalah solusi terbaik, bekerja di windows juga.
TheTFo
1
"tanda bintang * dikutip dari shell". Saya pikir maksud Anda "melarikan diri". Bagaimanapun, garis miring terbalik mencegah shell dari mengembangkannya.
gwideman
1
@ gwideman, saya pikir Anda benar, tetapi itu bukan saya. Ini kutipan dari docs git-scm.com/docs/git-add#_examples
Sergey Glotov
62

Dengan zshAnda dapat menjalankan:

git add "**/*.java"

dan semua *.javafile Anda akan ditambahkan secara rekursif.

Olivier Verdier
sumber
Terima kasih untuk itu, tapi saya bekerja dengan msysgit di Windows dan hanya memiliki bash.
Michel Krämer
1
Yah, saya melihat bahwa ada zshshell untuk windows ... Anda akan melakukan kebaikan untuk menggunakannya daripada bash, imho.
Olivier Verdier
1
Port Windows zsh didasarkan pada versi yang sangat lama dan lumpuh sepanjang waktu (misalnya saat saya masuk ls).
Michel Krämer
Wow, sempurna. Saya tidak tahu tentang fitur itu!
Tomáš Votruba
1
Ini tidak ada hubungannya dengan zsh. Saya pikir jawaban ini melewatkan poin bahwa Anda ingin melewati jalan dengan wildcard utuh untuk git dan biarkan git memprosesnya. Karena itu Anda ingin mencegah shell mana pun yang Anda gunakan dari memperluas wildcard (s). Untuk melakukan ini, Anda perlu mengutip beberapa cara yang sesuai untuk shell yang Anda gunakan. Lihat jawaban lain untuk detailnya.
gwideman
55

Sedikit topik (tidak terkait git), tetapi jika Anda menggunakan linux / unix, solusinya adalah:

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

Dan jika Anda mengharapkan jalur dengan spasi:

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

Tapi saya tahu bukan itu yang Anda minta.

Sergio Acosta
sumber
6
Masalah kecil dengan pendekatan ini - jika Anda "menemukan" file yang cocok dengan .gitignore Anda, maka git mengeluh bahwa Anda mencoba untuk menambahkan file yang Anda abaikan.
yoyo
2
@ yoyo - Saya baru saja menambahkan -f pada akhirnya, dan itu telah memperbaikinya
Maslow
5
@Maslow, itu akan secara paksa menambahkan file, meskipun itu seharusnya diabaikan (berdasarkan .gitignore). Saya lebih suka mendapatkan keluhan dan tidak menambahkan file (yang merupakan perilaku default.)
yoyo
Bagaimana ini bisa lebih baik daripada membiarkan git melakukan ekspansi wildcard?
gwideman
12

Jawaban Sergey (jangan kreditkan saya) berfungsi:

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

dengan git terbaru:

$git version
git version 1.7.3.4

File untuk ujian:

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

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

Menambahkan * .txt:

$git add \*.txt

Status yang diperbarui:

$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
Alberto
sumber
8

Jika Anda sudah melacak file Anda dan telah membuat perubahan padanya dan sekarang Anda ingin menambahkannya secara selektif berdasarkan suatu pola, Anda dapat menggunakan --modifiedbendera

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

Misalnya, jika Anda hanya ingin menambahkan perubahan CSS ke komit ini, Anda bisa melakukannya

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

Lihat man git-ls-fileslebih banyak bendera

Ram
sumber
5

Gunakan saja git add *\*.java. Ini akan menambahkan semua file .java di direktori root dan semua subdirektori.

Jan Lovstrand
sumber
Jawaban yang bagus Saya git menambahkan * / pom.xml untuk menambahkan semua nama file pom.xml.
Philip Rego
4

Menambahkan solusi baris perintah Windows yang belum disebutkan:

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

Saya hanya ingin menambahkan file yang memiliki string tertentu berdasarkan git status:

git status | grep string | xargs git add

dan kemudian dapat git commit -m 'commit msgmelakukan semua file yang diubah dengan "string" pada judul file

bdanin
sumber
2

Seperti disebutkan dalam " git: Bagaimana cara menambahkan semua file secara rekursif dalam subtree direktori yang cocok dengan pola glob? ", Jika Anda benar-benar lolos atau mengutip pathspec globbing (seperti '*.java') Anda, maka ya, git add'*.java'

Git 2.13 (Q2 2017) meningkatkannya untuk penambahan interaktif:

Lihat komit 7288e12 (14 Mar 2017) oleh Jeff King ( peff) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit 153e0d7 , 17 Mar 2017)

add --interactive: jangan perluas pathspecs dengan ls-files

Saat kami ingin mendapatkan daftar file yang dimodifikasi, pertama-tama kita perluas pathspec yang disediakan oleh pengguna dengan " ls-files", dan kemudian berikan daftar path yang dihasilkan sebagai argumen untuk " diff-index" dan " diff-files".
Jika pathspec Anda berkembang menjadi sejumlah besar jalur, Anda dapat mengalami salah satu dari dua masalah:

  1. OS mungkin mengeluh tentang ukuran daftar argumen, dan menolak untuk menjalankan. Sebagai contoh:

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

Itu ada di linux.gitrepositori, yang memiliki sekitar 20 ribu file di direktori "driver" (tidak ada yang dimodifikasi dalam hal ini). ulimit -sTrik " " diperlukan untuk menunjukkan masalah di Linux bahkan untuk set path raksasa seperti itu.
Sistem operasi lain memiliki batas yang jauh lebih kecil (misalnya, kasus dunia nyata terlihat dengan hanya 5K file pada OS X).

  1. Bahkan ketika itu berhasil, itu sangat lambat. Kode pathspec tidak dioptimalkan untuk sejumlah besar jalur. Inilah kasus yang sama tanpa ulimit:

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

Kami dapat meningkatkan ini dengan melewatkan " ls-files" sepenuhnya, dan hanya memberi makan pathspec asli ke perintah diff.

Secara historis bahasa pathspec yang didukung oleh " diff-index" lebih lemah, tetapi tidak lagi demikian.

VONC
sumber
1

masukkan baris ~ / .gitconfig

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

Jika Anda ingin menambahkan semua file java yang dimodifikasi, cukup lakukan: git addt java

Samely, jika Anda ingin menambahkan semua file python yang dimodifikasi, cukup lakukan: git addt py

Hong Emrys
sumber