자식 디렉토리 검색에서 특정 디렉토리 / 파일을 제외하는 방법


144

?를 사용하여 자식 저장소를 검색 할 때 특정 경로 / 디렉토리 / 파일을 제외시키는 방법이 git grep있습니까? --exclude일반 grep명령 의 옵션 과 비슷한 것이 있습니까?

큰 자식 저장소에서 직접 git grep사용 grep하는 것이 너무 느리기 때문에 사용해야 합니다.


bash는 그것을 이렇게하면 가능한 해결 될 것이다 : stackoverflow.com/questions/216995/...
치로 틸리을郝海东冠状病六四事件法轮功

8
1.9.0가에이 기능이 추가되었습니다 내 대답은 아래를 참조
onlynone

답변:



206

자식 1.9.0에서는 "마술 단어" excludepathspecs 에 추가되었습니다 . 따라서 foobar일치하는 파일을 제외한 모든 파일 을 검색 *.java하려면 다음을 수행하십시오.

git grep foobar -- './*' ':(exclude)*.java'

또는 !"짧은 형식"을 사용하여 제외하십시오.

git grep foobar -- './*' ':!*.java'

v2.12까지의 git 버전에서는 exclude를 사용할 때 pathspec하나 이상의 "inclusive"가 있어야합니다 pathspec. 위의 예에서 이것은 ./*(현재 디렉토리 아래의 모든 것을 재귀 적으로 포함) git v2.13에서는이 제한이 해제 git grep foobar -- ':!*.java'되어 ./*.

:(top)(짧은 형식 :)과 같은 것을 사용 :/하여 리포지토리의 상단에서 모든 것을 포함 할 수 있습니다 . 그러나 제외 pathspec를 맨 처음부터 시작 하도록 조정하고 싶을 수도 있습니다 :/!*.java(그렇지 않으면 *.java현재 디렉토리 아래의 파일 만 제외 합니다).

git-scm.com (또는 그냥 ) pathspec에서 허용되는 모든 "마법의 단어"에 대한 좋은 참고 자료가 있습니다 . 어떤 이유로 kernel.org 의 문서는 종종 Google 검색에서 처음 등장하지만 실제로 최신 버전이 아닙니다.git help glossary


4
git grep clock.gettime -- './*' ':!arch/**' ':!drivers/**'여러 개의 전체 디렉토리를 제외합니다. 그래도 재귀를 막을 수는 없다고 생각합니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
자주 사용하기 위해 다음을 제외하고 git alias를 만들 수 있습니다 git config alias.mygrep '!git grep "$@" -- "${GIT_PREFIX}/*" ":!*.java*" #'. 그럼 그냥 git mygrep foobar. (alias shell # trick and current dir 사용 )
medmunds

이 솔루션으로 해결할 수없는 문제는보고 된 파일 경로가 WC 루트와 관련이 있다는 것입니다. 따라서 WC의 하위 디렉토리에있는 경우 찾은 파일의 경로를 그대로 (예 : 덜) 사용할 수는 없지만 공통 경로를 뛰어 넘어야합니다. 이것에 대한 해결책이 있습니까? [win7의 git bash]
elonderin

1
@elonderin이 솔루션은 일치하는 파일을보고하는 방법과 관련이 없습니다. 하지만 난 그냥 시도한 git grepgit ls-files현재 디렉토리를 기준으로 하위 디렉토리 모두 보고서 파일 이름에서 (당신이 사용하는 경우에도이 ':(top)'pathspec 포함). 두 명령 모두 --full-name루트에 상대적인 이름을보고 하는 옵션이 있지만 기본적으로 해제되어 있습니다.
onlyn

1
나는 떠들썩한 기능을했다, 그래서 나는 자식 별칭을 사용하지 않지만, 아마도 자식 별칭이 더 gist.github.com/cmdcolin/04e2378b60f4457a41904c659368066f은
콜린 D

62

업데이트 : git> = 1.9의 경우 제외 패턴에 대한 기본 지원이 있습니다 ( oneone 's answer 참조) .

이것은 거꾸로 보일지 모르지만 제외 패턴 git grep과 일치하지 않는 파일 목록을 다음 과 같이 전달할 수 있습니다 .

git grep <pattern> -- `git ls-files | grep -v <exclude-pattern>`

grep -v일치 하지 않는 모든 경로를 반환합니다 <exclude-pattern>. 참고 git ls-files도 소요 --exclude매개 변수를하지만 단지에 적용되는 비 추적 파일 .


감사합니다! 힘내 그렙 너무 빨리 ACK 및 공동 이상의 아니라 임의의 경로를 제외 할 수있는 비트가 너무 : 말하자면 불편할 된 것입니다
토 마즈 지린 스키

2
불행히도 내 저장소에는 많은 파일이 있습니다. @kynan의 접근 방식을 시도하면 "-bash : / usr / bin / git : Argument list too long"
Benissimo

2
이렇게하면 Benissimo의 "인수 목록이 너무 깁니다"문제와 bash (예 : [])로 해석되는 파일 이름 caracters 또는 저장소에 공백이 포함 된 파일 이름 문제가 해결되었습니다. git ls-files | grep -v <exclue-pattern> | xargs -d '\ n'git grep <pattern>
Scout

2
아무도 대답을 확인하지 마십시오. 지금 완전히 현대 버전의 git 내 에서이 작업을 수행 할 수 있습니다.
David

왜 다운 보트인가? 이 답변은 여전히 ​​1.9 이전의 git 버전에 적용됩니다. 나는 오직 한 사람의 대답에 관한 메모를 추가했습니다.
kynan

5

저장소에 속성 파일을 작성하여 파일 또는 디렉토리를 2 진으로 표시 할 수 있습니다 (예 :

$ cat .git/info/attributes 
directory/to/ignore/*.* binary
directory/to/ignore/*/*.* binary
another_directory/to/also/ignore/*.* binary

이진 파일의 일치 항목은 포함 줄없이 나열됩니다 (예 :

$ git grep "bar"
Binary file directory/to/ignore/filename matches
other_directory/other_filename:      foo << bar - bazz[:whatnot]

2

@kynan의 예제를 기본으로 사용 하여이 스크립트를 만들고 경로 ( ~/bin/) 에 넣습니다 gg. git grep지정된 파일 형식을 사용 하지만 피합니다.

우리 저장소에는 많은 이미지가 있으므로 이미지 파일을 제외했으며 전체 저장소를 검색하면 serchtime이 1/3로 줄어 듭니다. 그러나 다른 파일 형식이나 겔러 패턴을 제외하도록 스크립트를 쉽게 수정할 수 있습니다.

#!/bin/bash                                                                    
#                                                                              
# Wrapper of git-grep that excludes certain filetypes.                         
# NOTE: The filetypes to exclude is hardcoded for my specific needs.           
#                                                                              
# The basic setup of this script is from here:                                 
#   https://stackoverflow.com/a/14226610/42580                                  
# But there is issues with giving extra path information to the script         
# therefor I crafted the while-thing that moves path-parts to the other side   
# of the '--'.                                                                 

# Declare the filetypes to ignore here                                         
EXCLUDES="png xcf jpg jpeg pdf ps"                                             

# Rebuild the list of fileendings to a good regexp                             
EXCLUDES=`echo $EXCLUDES | sed -e 's/ /\\\|/g' -e 's/.*/\\\.\\\(\0\\\)/'`      

# Store the stuff that is moved from the arguments.                            
moved=                                                                         

# If git-grep returns this "fatal..." then move the last element of the        
# arg-list to the list of files to search.                                     
err="fatal: bad flag '--' used after filename"                                 
while [ "$err" = "fatal: bad flag '--' used after filename" ]; do              
    {                                                                          
        err=$(git grep "$@" -- `git ls-files $moved | grep -iv "$EXCLUDES"` \  
            2>&1 1>&3-)                                                        
    } 3>&1                                                                     

    # The rest of the code in this loop is here to move the last argument in   
    # the arglist to a separate list $moved. I had issues with whitespace in   
    # the search-string, so this is loosely based on:                          
    #   http://www.linuxjournal.com/content/bash-preserving-whitespace-using-set-and-eval
    x=1                                                                        
    items=                                                                     
    for i in "$@"; do                                                          
        if [ $x -lt $# ]; then                                                 
            items="$items \"$i\""                                              
        else                                                                   
            moved="$i $moved"                                                  
        fi                                                                     
        x=$(($x+1))                                                            
    done                                                                       
    eval set -- $items                                                         
done                                                                           
# Show the error if there was any                                              
echo $err                                                                      

참고 1

에 따르면 이 일을 이름을 할 수 있어야 git-gg하고 같은 일반 자식 명령으로 호출 할 수 :

$ git gg searchstring

그러나 나는 이것을 작동시킬 수 없다. 내 스크립트를 만들고에서 심볼릭 링크를 ~/bin/만들었 git-gg습니다 /usr/lib/git-core/.

노트 2

명령은 shrepo의 루트에서 호출되므로 일반 git-alias 로 만들 수 없습니다 . 그리고 그것은 내가 원하는 것이 아닙니다!

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