Apakah mungkin untuk melakukan 'pencarian grep' di semua cabang proyek Git?

Jawaban:

195

Pertanyaan " Bagaimana cara grep (mencari) kode yang berkomitmen di histori git? " Merekomendasikan:

 git grep <regexp> $(git rev-list --all)

Itu mencari melalui semua komit, yang harus mencakup semua cabang.

Bentuk lain adalah:

git rev-list --all | (
    while read revision; do
        git grep -F 'yourWord' $revision
    done
)

Anda dapat menemukan lebih banyak contoh di artikel ini :

Saya mencoba hal di atas pada satu proyek yang cukup besar sehingga git mengeluh tentang ukuran argumennya, jadi jika Anda mengalami masalah ini, lakukan sesuatu seperti:

git rev-list --all | (while read rev; do git grep -e <regexp> $rev; done)

(lihat alternatif di bagian terakhir dari jawaban ini, di bawah)

Jangan lupa pengaturan tersebut, jika Anda menginginkannya:

# Allow Extended Regular Expressions
git config --global grep.extendRegexp true
# Always Include Line Numbers
git config --global grep.lineNumber true

Alias ​​ini juga dapat membantu:

git config --global alias.g "grep --break --heading --line-number"

Catatan: saran chernjie itu berlebihan. git rev-list --all

Perintah yang lebih halus dapat berupa:

git branch -a | tr -d \* | xargs git grep <regexp>

Yang memungkinkan Anda untuk mencari hanya cabang (termasuk cabang jarak jauh)

Anda bahkan dapat membuat alias bash / zsh untuk itu:

alias grep_all="git branch -a | tr -d \* | xargs git grep"
grep_all <regexp>

Pembaruan Agustus 2016: RM merekomendasikan di komentar

Saya mendapat " fatal: bad flag '->' used after filename" saat mencoba git branchversi. Kesalahan itu terkait dengan HEADnotasi aliasing.

Saya menyelesaikannya dengan menambahkan a sed '/->/d'di pipa, antara trdan xargsperintah.

 git branch -a | tr -d \* | sed '/->/d' | xargs git grep <regexp>

Itu adalah:

alias grep_all="git branch -a | tr -d \* | sed '/->/d' | xargs git grep"
grep_all <regexp>
VonC
sumber
Bukan ide yang baik untuk menyalurkan output git branchke tr atau sed; git branchadalah perintah porselen yang dimaksudkan untuk konsumsi manusia. Lihat stackoverflow.com/a/3847586/2562319 untuk alternatif pilihan.
jbyler
@ByLa Ironisnya, saya memposting jawaban tentang porselen jauh sebelum jawaban ini: stackoverflow.com/a/6978402/6309 . Dan saya menggunakannya misalnya di stackoverflow.com/a/19206916/6309 .
VonC
Ya, bagus. Melihat melalui jawaban lain, menurut saya jawaban dari @errordeveloper adalah yang terbersih: stackoverflow.com/a/21284342/2562319 : "git grep <regexatever $ (git for-each-ref --format = '% (refname) 'refs /) "
jbyler
2
Apakah ada cara untuk menampilkan nama cabang yang cocok dengan pencarian?
franksands
66

git log bisa menjadi cara yang lebih efektif untuk mencari teks di semua cabang, terutama jika ada banyak yang cocok, dan Anda ingin melihat perubahan yang lebih baru (relevan) terlebih dahulu.

git log -p --all -S 'search string'
git log -p --all -G 'match regular expression'

Daftar perintah log ini melakukan yang menambah atau menghapus string pencarian / regex yang diberikan, (umumnya) lebih baru terlebih dahulu. The -ppilihan menyebabkan diff relevan untuk ditampilkan di mana pola ditambahkan atau dihapus, sehingga Anda dapat melihatnya dalam konteks.

Setelah menemukan komit relevan yang menambahkan teks yang Anda cari (mis. 8beeff00d), temukan cabang yang berisi komit:

git branch -a --contains 8beeff00d
Edward Anderson
sumber
22

Menurut saya ini paling berguna:

git grep -i foo `git for-each-ref --format='%(refname)' refs/`

Anda perlu menyesuaikan argumen terakhir tergantung pada apakah Anda hanya ingin melihat cabang jarak jauh vs. lokal, yaitu:

  • git grep -i foo $(git for-each-ref --format='%(refname)' refs/remotes)
  • git grep -i foo $(git for-each-ref --format='%(refname)' refs/heads)

Alias ​​yang saya buat terlihat seperti ini:

grep-refs = !sh -c 'git grep "$0" "$@" "$(git for-each-ref --format=\"%(refname)\"" refs/)'
errordeveloper
sumber
1
Alias ​​yang menarik. +1. Lebih tepat dari pada jawaban saya.
VonC
Bagaimana cara membuat alias Anda berfungsi untuk pencarian frase? Ketika saya meneruskan "foo bar" sebagai parameter, saya mendapatkan: fatal: argumen ambigu 'bar': revisi yang tidak diketahui atau jalur tidak ada di pohon kerja. Gunakan '-' untuk memisahkan jalur dari revisi
jutky
Coba keluar dari ruang: "foo \ bar"
Garry Gomez
Ini jelas akan menjadi jawaban yang diterima;) Saya telah memperluasnya untuk hanya mencari di cabang terbaru dari proyek saya (Mendapat lebih dari 500, jangan tanya, dan setiap grep membutuhkan waktu sekitar 4 detik jadi saya tidak ingin atau membutuhkan untuk menelusuri lebih dari, katakanlah, 100 yang terbaru). Untuk ini saya telah memperbarui git for-each-refdengan --sort=-committerdate --count=100! Terima kasih atas ide aslinya!
Vser
6

Anda dapat melakukannya dengan dua cara umum: alias Bash atau Git

Berikut tiga perintah:

  1. git grep-branch - Cari di semua cabang lokal & jarak jauh
  2. git grep-branch-local - Cari di cabang lokal saja
  3. git grep-branch-remote - Cabang terpencil saja

Penggunaannya sama dengan git grep

git grep-branch "find my text"
git grep-branch --some-grep-options "find my text"

GREP menggunakan: alias Git

Berkas ~ / .gitconfig

Perintah harus ditambahkan secara manual ke ~/.gitconfigfile, karena git config --global aliasmengevaluasi kode kompleks yang Anda tambahkan dan mengacaukannya.


[alias]
    grep-branch        = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | xargs git grep $@; };f "
    grep-branch-remote = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | grep '^remotes' | xargs git grep $@; };f"
    grep-branch-local  = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' -e '^remotes' | xargs git grep $@;  };f "

Catatan: Saat Anda menambahkan alias dan gagal dijalankan - periksa garis miring terbalik, \mereka mungkin memerlukan pelolosan tambahan \\dibandingkan dengan perintah bash .

  • git branch -a - Tampilkan semua cabang;
  • sed -e 's/[ \\*]*//'- Potong spasi (dari branch -a) dan * (nama cabang aktif memilikinya);
  • grep -v -e '\\->'- Abaikan nama yang rumit seperti remotes/origin/HEAD -> origin/master;
  • grep '^remotes' - Dapatkan semua cabang jarak jauh;
  • grep -v -e '^remotes'- Dapatkan cabang kecuali cabang jarak jauh;

Contoh git grep-branch-local -n getTastyCookies

-n Awali nomor baris ke baris yang cocok.

[user@pc project]$ git grep-branch-local -n getTastyCookies

dev:53:modules/factory/getters.php:function getTastyCookies($user);
master:50:modules/factory/getters.php:function getTastyCookies($user)

Struktur saat ini adalah:

: - Pemisah

  1. Cabang: dev
  2. Nomor baris: 53
  3. Jalur file: modules/factory/getters.php
  4. Garis yang cocok: function getTastyCookies($user)

GREP menggunakan: BASH

Seperti yang harus Anda ketahui: Perintah Bash harus disimpan dalam .shskrip atau dijalankan di shell.

Cabang lokal saja

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' -e '^remotes' | xargs git grep "TEXT"

Cabang jarak jauh saja

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | grep '^remotes' | xargs git grep "TEXT"

Cabang lokal & terpencil

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | xargs git grep "TEXT"
Devaldo
sumber
Kedengarannya bagus, tapi saya mendapatkan kesalahan ini dari git grep-branch "find my text":fatal: ambiguous argument 'client': both revision and filename
nealmcb
Mengapa selalu digunakan -a, yang menunjukkan semua cabang? Saya akan menyarankan menggunakan opsi untuk git branchperintah untuk memisahkan braches. Saat melihat cabang lokal, hanya ada satu *, jadi tidak perlu menghindarinya karena sed. Jadi: git branch | sed -e 's/*/ /' | xargs git grep "TEXT"untuk cabang lokal saja, git branch -r | grep -v -- "->" | xargs git grep "TEXT"untuk cabang terpencil saja, dan git branch -a | grep -v -- "->" | xargs git grep "TEXT"untuk semua cabang
jalanb
4

Begini cara saya melakukannya:

git for-each-ref --format='%(*refname)' | xargs git grep SEARCHTERM
William Entriken
sumber
2
Satu-satunya solusi yang berhasil untuk saya di Windows (di Git bash)
Ivan
4

Jika Anda memberikan komit nilai hash SHA-1, git grepAnda harus mencarinya di dalamnya, bukan di copy pekerjaan.

Untuk mencari semua cabang, Anda bisa mendapatkan semua pohon git rev-list --all. Taruh semuanya dengan

git grep "regexp" $(git rev-list --all)

... dan memiliki kesabaran

CharlesB
sumber