2012-05-02 32 views
97

Có cách nào để tìm kiếm kho git bằng cách sử dụng git grep nhưng loại trừ các đường dẫn/thư mục nhất định khỏi tìm kiếm không? Giống như tùy chọn --exclude trong lệnh grep bình thường.Làm cách nào để loại trừ các thư mục/tập tin nhất định khỏi tìm kiếm git grep

Nếu bạn tò mò: Tôi không muốn sử dụng grep bình thường vì nó chậm hơn nhiều so với git grep khi kích thước của kho git lớn.

+0

Làm điều đó trên bash sẽ là cách giải quyết khả thi: http://stackoverflow.com/questions/216995/how-can-i-use-inverse-or-negative-wildcards-when-pattern-matching-in-a -unix-linu –

+5

Tính năng này đã được thêm vào trong 1.9.0 [xem câu trả lời của tôi bên dưới] (/ a/30084612/436287) – onlynone

Trả lời

16

Không thể, nhưng has been discussed recently. Đề xuất giải pháp thay thế trong liên kết:

Bạn có thể đặt *.dll vào tệp .gitignore sau đó git grep --exclude-standard.

CHỈNH SỬA xem chỉ có câu trả lời, vì git 1.9.0 có thể.

+0

Bất kỳ ý tưởng nào nếu điều này vẫn không thể thực hiện được? Hoặc có điều gì đó đã thay đổi trong 2 năm qua? –

+3

@ mustafa.0x xem câu trả lời được trả lời nhiều nhất, có thể – CharlesB

+1

Kiểm tra câu trả lời của người khác, có thể làm điều này hoàn toàn trong git ngay bây giờ. – David

54

Cập nhật: Đối với git> = 1.9 có hỗ trợ gốc cho các mẫu loại trừ, hãy xem onlyone's answer.

Điều này có vẻ ngược, nhưng bạn có thể vượt qua một danh sách các tập tin không phù hợp với mô hình loại trừ của bạn để git grep như thế này:

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

grep -v lợi nhuận mỗi con đường không phù hợp với <exclude-pattern>. Lưu ý rằng git ls-files cũng có thông số --exclude nhưng chỉ áp dụng cho các tệp không được theo dõi.

+0

Cảm ơn vì điều này! Git grep là nhanh hơn rất nhiều so với ack & co nhưng không thể loại trừ đường dẫn tùy ý là hơi quá bất tiện để nói :) –

+1

Thật không may repo của tôi có rất nhiều tệp. Khi tôi thử cách tiếp cận @ kynan, tôi nhận được: "-bash:/usr/bin/git: Danh sách đối số quá dài" – Benissimo

+1

Điều này sẽ giải quyết cả vấn đề "Danh sách đối số quá dài" của Benissimo và vấn đề của tôi với tên tệp caracters được bash giải thích (như []) hoặc tên tệp có chứa khoảng trống trong kho lưu trữ: git ls-files | grep -v | xargs -d '\ n' git grep - – Scout

2

Với ví dụ của @kynan làm cơ sở tôi đã tạo tập lệnh này và đặt nó trong đường dẫn của tôi (~/bin/) là gg. Nó sử dụng git grep nhưng tránh một số loại tệp được chỉ định.

Trong repo của nó rất nhiều hình ảnh vì vậy tôi đã loại trừ các imagefiles, và điều này sẽ serchtime xuống 1/3 nếu tôi tìm kiếm toàn bộ repo. Tuy nhiên, kịch bản có thể dễ dàng được sửa đổi để loại trừ các kiểu mẫu khác hoặc các mẫu mã.

#!/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 "[email protected]" -- `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 "[email protected]"; 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                  

Note 1

Theo this chúng ta có thể đặt tên cho điều git-gg và có thể gọi nó như là một lệnh git thường xuyên như:

$ git gg searchstring 

Nhưng tôi có thể không làm việc này. Tôi đã tạo tập lệnh trong số ~/bin/ và tạo liên kết tượng trưng git-gg trong /usr/lib/git-core/.

Note 2

Lệnh không thể được làm thành một thường xuyên sh git-alias vì nó sẽ sau đó được gọi vào thư mục gốc của repo. Và đó không phải là điều tôi muốn!

122

Trong git 1.9.0 "từ ma thuật" exclude đã được thêm vào pathspec s.Vì vậy, nếu bạn muốn tìm kiếm foobar trong mỗi tập tin ngoại trừ đối với những phù hợp với *.java bạn có thể làm:

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

Hoặc sử dụng ! "hình thức ngắn" cho loại trừ:

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

Lưu ý rằng khi sử dụng loại trừ pathspec, bạn phải có ít nhất một "bao gồm" pathspec. Trong các ví dụ trên, đây là ./* (đệ quy bao gồm mọi thứ trong thư mục hiện tại).

Bạn cũng có thể sử dụng một cái gì đó như :(top) (dạng ngắn: :/) để bao gồm mọi thứ từ đầu repo. Nhưng sau đó bạn có thể cũng muốn điều chỉnh loại trừ của mình pathspec để bắt đầu từ trên cùng: :/!*.java (nếu không nó sẽ chỉ loại trừ *.java tệp từ trong thư mục hiện tại của bạn).

Có một tham chiếu tốt cho tất cả "từ ma thuật" được phép trong một số pathspec tại git-scm.com (hoặc chỉ git help glossary). Vì lý do nào đó, tài liệu tại kernel.org thực sự lạc hậu ngay cả khi chúng thường xuất hiện đầu tiên trong các tìm kiếm trên google.

+1

'git grep clock.gettime - './*' ':! Arch/**' ':! Drivers/**'' để loại trừ nhiều thư mục. Tôi không nghĩ rằng nó ngăn cản đệ quy mặc dù. –

+0

Để sử dụng thường xuyên, bạn có thể tạo bí danh git với các loại trừ: 'git config alias.mygrep '! Git grep" $ @ "-" $ {GIT_PREFIX}/* "":! *. Java * "#'' . Sau đó, chỉ cần 'git mygrep foobar'. (Sử dụng bí danh [shell # trick] (http://stackoverflow.com/a/39523506/647002) và [dir hiện tại] (http://stackoverflow.com/a/22039008/647002).) – medmunds

+0

vấn đề tôi không thể giải quyết với giải pháp này là các đường dẫn được báo cáo của các tệp có liên quan đến gốc WC. Vì vậy, nếu tôi đang ở trong một thư mục phụ của WC, tôi không thể chỉ sử dụng đường dẫn của (các) tệp được tìm thấy như (ví dụ: ít hơn) nhưng phải sử dụng các đường dẫn chung. Có một giải pháp cho điều này (w/o phải emply sed bản thân mình)? [git bash trên win7] – elonderin

Các vấn đề liên quan