Git 프로젝트의 모든 브랜치에서 'grep search'를 수행 할 수 있습니까?


답변:


189

" git history에서 커밋 된 코드를 grep (검색)하는 방법은? "

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

모든 커밋을 검색하며 여기에는 모든 분기가 포함되어야합니다.

다른 형태는 다음과 같습니다.

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

이 기사 에서 더 많은 예를 찾을 수 있습니다 .

git이 인수 크기에 대해 불평 할 정도로 충분히 큰 프로젝트에서 위의 시도를 했으므로이 문제가 발생하면 다음과 같이하십시오.

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

(아래 답변의 마지막 섹션에서 대안을 참조하십시오)

원하는 경우 해당 설정을 잊지 마십시오.

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

이 별명도 도움이 될 수 있습니다.

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

참고 : chernjie 이것이 git rev-list --all과잉 이라고 제안 했습니다 .

보다 세련된 명령은 다음과 같습니다.

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

지점 만 검색 할 수 있습니다 (원격 지점 포함).

bash / zsh 별명을 작성할 수도 있습니다.

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

2016 년 8 월 업데이트 : 의견에서 RM 권장

버전을 fatal: bad flag '->' used after filename시도 할 때 " "가 git branch있습니다. 이 오류는 HEAD앨리어싱 표기법 과 관련이 있습니다.

sed '/->/d'파이프 trxargs명령 사이에 파이프 를 추가하여 문제를 해결했습니다 .

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

그건:

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

출력 git branch을 tr 또는 sed로 파이프하는 것은 좋지 않습니다 . git branch인간 소비를위한 도자기 명령입니다. 선호되는 대안 은 stackoverflow.com/a/3847586/2562319 를 참조하십시오 .
jbyler

@jbyler 좋은 지적입니다. 아이러니하게도, 나는이 답변보다 오래 전에 도자기에 대한 답변을 게시했습니다 : stackoverflow.com/a/6978402/6309 . 그리고 예를 들어 stackoverflow.com/a/19206916/6309 에서 사용합니다 .
VonC

그래, 좋아 다른 답변을 살펴보면 @errordeveloper의 답변이 가장 깨끗합니다. stackoverflow.com/a/21284342/2562319 : "git grep <regexp> $ (git for-each-ref --format = '% (refname) 'refs /)'
jbyler

1
검색과 일치하는 지점의 이름을 표시하는 방법이 있습니까?
franksands

63

git log 일치하는 항목이 많고 가장 최근 (관련) 변경 사항을 먼저보고자하는 경우 모든 브랜치에서보다 효과적인 텍스트 검색 방법이 될 수 있습니다.

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

이 로그 명령은 주어진 검색 문자열 / 정규식을 (일반적으로) 가장 최근에 추가하거나 제거하는 커밋을 나열합니다. 이 -p옵션을 사용하면 패턴이 추가되거나 제거 된 위치에 관련 diff가 표시되므로 컨텍스트에서 볼 수 있습니다.

찾고있는 텍스트 (예 : 8beeff00d)를 추가하는 관련 커밋을 찾은 경우 커밋이 포함 된 분기를 찾습니다.

git branch -a --contains 8beeff00d

22

나는 이것이 가장 유용하다는 것을 알았다.

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

원격 지점과 로컬 지점 만보고 싶은지 여부에 따라 마지막 인수를 조정해야합니다.

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

내가 만든 별칭은 다음과 같습니다.

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

1
재미있는 별칭. +1. 내 대답보다 더 정확합니다.
VonC

구문 검색에 별칭을 사용하려면 어떻게해야합니까? "foo bar"를 매개 변수로 전달하면 치명적인 : 모호한 인수 'bar': 알 수없는 개정 또는 작업 트리에없는 경로가 표시됩니다. '-'를 사용하여 경로와 개정판을 분리하십시오
jutky

공간을 탈출 해보세요 : "foo \ bar"
Garry Gomez

이것은 분명히 대답이 될 것입니다;) 나는 프로젝트의 최신 지점에서만 검색하도록 확장했습니다 (500 개 이상, 묻지 말고 각 grep은 약 4 초가 걸리므로 원하지 않거나 필요하지 않습니다 100 개가 넘는 최신 검색). 이를 위해 나는 업데이트되었습니다 git for-each-ref와 함께 --sort=-committerdate --count=100! 독창적 인 아이디어에 감사드립니다!
Vser

6

Bash 또는 Git 별칭의 두 가지 일반적인 방법으로 수행 할 수 있습니다.

다음은 세 가지 명령입니다.

  1. git grep-branch -모든 지점에서 로컬 및 원격으로 검색
  2. git grep-branch-local -현지 지점에서만 검색
  3. git grep-branch-remote -원격 지점 만

사용법은 git grep

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

GREP 사용 : Git 별칭

파일 ~ / .gitconfig

추가 한 복잡한 코드를 평가하고 엉망으로 만들기 ~/.gitconfig때문에 명령을 파일 에 수동으로 추가해야 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 "

참고 : 별명을 추가하고 별명을 실행할 \수없는 경우 백 슬래시 를 점검 \\하면 bash 명령 과 비교하여 추가 이스케이프가 필요할 수 있습니다 .

  • git branch -a -모든 지점을 표시;
  • sed -e 's/[ \\*]*//'- 트림 공간 (행branch -a 내기 ) 및 * (활성 분기 이름에 있음);
  • grep -v -e '\\->' -복잡한 이름은 무시하십시오remotes/origin/HEAD -> origin/master .
  • grep '^remotes' -모든 원격 지점을 가져옵니다;
  • grep -v -e '^remotes'- 원격 지점을 제외한 지점을 가져옵니다.

git grep-branch-local -n getTastyCookies

-n 줄 번호 앞에 일치하는 줄을 붙입니다.

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

현재 구조는 다음과 같습니다

: -분리기

  1. 분기: dev
  2. 줄 번호 : 53
  3. 파일 경로: modules/factory/getters.php
  4. 일치하는 줄 : function getTastyCookies($user)

GREP 사용 : BASH

아시다시피 : Bash 명령은 .sh 스크립트에 하거나 쉘에서 실행 .

현지 지점 만

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

원격 지점 만

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

현지 및 원격 지점

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

git grep-branch "find my text"fatal: ambiguous argument 'client': both revision and filename
좋게 들리지만

왜 항상 -a모든 분기를 표시하는를 사용합니까? git branch브 래치를 분리 하기 위해 명령에 옵션을 사용하는 것이 좋습니다 . 로컬 브랜치를 볼 때 단 하나만 *있으므로 sed를 위해 벗어날 필요가 없습니다. 그래서 : git branch | sed -e 's/*/ /' | xargs git grep "TEXT"지역 만 가지에 대한 git branch -r | grep -v -- "->" | xargs git grep "TEXT"원격 지사에 대해서만, 그리고 git branch -a | grep -v -- "->" | xargs git grep "TEXT"모든 지점에 대한
jalanb

4

내가하는 방법은 다음과 같습니다.

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

2
Windows에서 나를 위해 일한 유일한 솔루션 (Git bash에서)
Ivan

4

커밋에 SHA-1 해시 값을 부여 git grep하면 작업 복사본 대신 값을 검색하게됩니다.

모든 가지를 검색하려면을 사용하여 모든 나무를 얻을 수 있습니다 git rev-list --all. 다 넣어

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

... 그리고 인내심을 가지고

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.