Git projesinin tüm dallarında 'grep araması' yapmak mümkün müdür?


Yanıtlar:


189

" Git geçmişinde işlenmiş kodu nasıl grep (arama))? Sorusu şunları önerir:

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

Bu, tüm şubeleri içermesi gereken tüm taahhütleri araştırır.

Başka bir form:

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

Bu makalede daha da fazla örnek bulabilirsiniz :

Git argüman boyutu hakkında şikayet yeterince büyük bir projede yukarıdaki denedim, bu yüzden bu sorunla karşılaşırsanız, gibi bir şey yapın:

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

(aşağıdaki bu cevabın son bölümünde bir alternatife bakın)

İsterseniz bu ayarları unutmayın:

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

Bu takma ad da yardımcı olabilir:

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

Not: chernjie bunun aşırıya kaçması olduğunu öne sürdügit rev-list --all .

Daha rafine bir komut şunlar olabilir:

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

Bu, yalnızca dalları aramanıza olanak tanır (uzak dallar dahil)

Bunun için bir bash / zsh takma adı bile oluşturabilirsiniz:

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

Ağustos 2016'yı Güncelle: RM yorumlarda öneriliyor

Sürümü fatal: bad flag '->' used after filenamedenerken " " aldım git branch. Hata, bir HEADtakma ad gösterimi ile ilişkilendirildi .

Komutları sed '/->/d'arasına, trve xargskomutları arasına bir a ekleyerek çözdüm.

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

Yani:

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

git branchÇıkışını tr veya sed'e çekmek iyi bir fikir değildir ; git branchinsan tüketimi için tasarlanmış bir porselen komutudur. Tercih edilen alternatifler için stackoverflow.com/a/3847586/2562319 adresine bakın .
jbyler

@jbyler İyi bir nokta. İronik olarak, cevabı şu cevabdan çok önce porselen üzerine gönderdim: stackoverflow.com/a/6978402/6309 . Ve örneğin stackoverflow.com/a/19206916/6309 dosyasında kullanıyorum .
VonC

Evet, güzel. Diğer cevaplara baktığımda, @errordeveloper tarafından verilen cevap en temiz olduğunu düşünüyorum: stackoverflow.com/a/21284342/2562319 : "git grep <regexp> $ (git for-each-ref --format = '% (refname) 'refs /) "
jbyler

1
Aramayla eşleşen şubenin adını göstermenin bir yolu var mı?
franksands

63

git log özellikle çok sayıda eşleşme varsa ve önce daha yeni (alakalı) değişiklikler görmek istiyorsanız, tüm şubelerde metin aramanın daha etkili bir yolu olabilir.

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

Bu günlük komutları listesi, belirli bir arama dizesini / regex'i (genellikle) daha önce ekleyen veya kaldıran taahhüt eder. -pOpsiyon model eklendi veya kaldırıldı nereye bağlam içinde görebilirsiniz alakalı fark, gösterildiği neden olur.

Aradığınız metni ekleyen alakalı bir taahhüt bulduktan sonra (örn. 8beeff00d), taahhüdü içeren şubeleri bulun:

git branch -a --contains 8beeff00d

22

Bunu en yararlı buldum:

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

Son bağımsız değişkenleri yalnızca uzak ve yerel şubelere bakmak isteyip istemediğinize bağlı olarak ayarlamanız gerekir.

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

Oluşturduğum takma ad şöyle:

grep-refs = !sh -c 'git grep "$0" "$@" "$(git for-each-ref --format=\"%(refname)\"" refs/)'

1
İlginç takma ad. +1. Cevabımdan daha kesin.
VonC

Takma adınızı sıralı arama için nasıl çalıştırabilirsiniz? Parametre olarak "foo bar" ı ilettiğimde şunu elde ederim: fatal: belirsiz argüman 'bar': bilinmeyen düzeltme veya çalışma ağacında yol yok. Yolları revizyonlardan ayırmak için '-' kullanın
jutky

Uzaydan kaçmayı deneyin: "foo \ bar"
Garry Gomez

Bu açıkça kabul edilen cevap olacaktır;) Sadece projemin son dallarında arama yapmak için genişlettim (500'den fazla var, sorma, ve her grep yaklaşık 4sec alır, bu yüzden istemiyorum, gerek yok örneğin en son 100 tanesinden daha fazlasını aramak için). Bunun için git for-each-refile güncelledim --sort=-committerdate --count=100! Orijinal fikir için teşekkürler!
Vser

6

Bunu iki yaygın şekilde yapmak mümkündür: Bash veya Git takma adları

İşte üç komut:

  1. git grep-branch - Yerel ve uzak tüm şubelerde arama
  2. git grep-branch-local - Yalnızca yerel şubelerde ara
  3. git grep-branch-remote - Yalnızca uzak dallar

Kullanımı ile aynı git grep

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

GREP kullanımı: Git takma adları

Dosya ~ / .gitconfig

Eklediğiniz karmaşık kodu değerlendirip karıştırdığınız için komutlar ~/.gitconfigdosyaya manuel olarak eklenmelidir git config --global alias.


[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 "

Not: Takma ad eklediğinizde ve bunlar çalışmadığında - ters eğik çizgileri kontrol edin , bash komutlarına kıyasla \ek kaçış gerektirebilirler .\\

  • git branch -a - Tüm dalları göster;
  • sed -e 's/[ \\*]*//'- Kesme boşlukları (itibaren branch -a) ve * (etkin dal adında);
  • grep -v -e '\\->'- Gibi karmaşık isimleri yoksay remotes/origin/HEAD -> origin/master;
  • grep '^remotes' - Tüm uzak dalları alın;
  • grep -v -e '^remotes'- Uzak şubeler hariç şubeleri alın ;

Misal git grep-branch-local -n getTastyCookies

-n Satır numarasını eşleşen satırlara önekleyin.

[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)

Mevcut yapı:

: - Ayırıcı

  1. Şube: dev
  2. Satır numarası: 53
  3. Dosya yolu: modules/factory/getters.php
  4. Eşleşen hattı: function getTastyCookies($user)

GREP kullanımı: BASH

Bildiğiniz gibi: Bash komutları .shkomut dosyalarında saklanmalı veya bir kabukta çalıştırılmalıdır.

Yalnızca yerel şubeler

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

Yalnızca uzak dallar

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

Yerel ve uzak şubeler

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

Kulağa hoş geliyor, ama bu hatayı aldım git grep-branch "find my text":fatal: ambiguous argument 'client': both revision and filename
nealmcb

Neden her zaman -atüm dalları gösteren kullanın ? git branchBrachları ayırmak için komutun seçeneklerini kullanmanızı öneririm . Yerel şubelere bakarken, sadece bir tane var *, bu yüzden sed için kaçmaya gerek yok. Yani: git branch | sed -e 's/*/ /' | xargs git grep "TEXT"sadece yerel şubeler için, sadece git branch -r | grep -v -- "->" | xargs git grep "TEXT"uzak şubeler için ve git branch -a | grep -v -- "->" | xargs git grep "TEXT"tüm şubeler için
jalanb

4

İşte nasıl yaparım:

git for-each-ref --format='%(*refname)' | xargs git grep SEARCHTERM

2
Windows'da benim için çalışan tek çözüm (Git bash'ta)
Ivan

4

Herhangi bir taahhüde SHA-1 karma değeri verirseniz git grep verirseniz, çalışma kopyası yerine bunlarda arama yapabilirsiniz.

Tüm dalları aramak için, tüm ağaçları alabilirsiniz git rev-list --all. Hepsini koy

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

... ve sabrınız olsun

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.