Có thể thực hiện 'tìm kiếm grep' trong tất cả các nhánh của dự án Git không?


137

Có thể chạy git grepbên trong tất cả các nhánh của dự án có nguồn gốc kiểm soát Git không? Hoặc có một lệnh khác để chạy?



Câu trả lời:


188

Câu hỏi " Làm thế nào để grep (tìm kiếm) mã cam kết trong lịch sử git? " Đề xuất:

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

Đó là tìm kiếm thông qua tất cả các cam kết, trong đó bao gồm tất cả các chi nhánh.

Một hình thức khác sẽ là:

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

Bạn có thể tìm thấy nhiều ví dụ hơn trong bài viết này :

Tôi đã thử ở trên một dự án đủ lớn để git phàn nàn về kích thước đối số, vì vậy nếu bạn gặp phải vấn đề này, hãy làm một cái gì đó như:

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

(xem phần thay thế trong phần cuối của câu trả lời này, bên dưới)

Đừng quên các cài đặt đó, nếu bạn muốn chúng:

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

Bí danh này cũng có thể giúp:

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

Lưu ý: chernjie đề nghị đó git rev-list --alllà một quá mức cần thiết.

Một lệnh tinh tế hơn có thể là:

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

Điều này sẽ cho phép bạn chỉ tìm kiếm các chi nhánh (bao gồm các chi nhánh từ xa)

Bạn thậm chí có thể tạo bí danh bash / zsh cho nó:

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

Cập nhật tháng 8 năm 2016: RM khuyến nghị trong các ý kiến

Tôi đã nhận được một " fatal: bad flag '->' used after filename" khi thử git branchphiên bản. Lỗi được liên kết với một HEADký hiệu răng cưa.

Tôi đã giải quyết nó bằng cách thêm một sed '/->/d'trong ống, giữa trvà các xargslệnh.

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

Đó là:

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

Nó không phải là một ý tưởng tốt để dẫn đầu ra của git branchtr hoặc sed; git branchlà một lệnh sứ có nghĩa là cho tiêu dùng của con người. Xem stackoverflow.com/a/3847586/2562319 để biết các lựa chọn thay thế ưa thích.
jbyler

@jbyler Điểm tốt. Trớ trêu thay, tôi đã đăng câu trả lời lên đồ sứ từ lâu trước câu trả lời này: stackoverflow.com/a/6978402/6309 . Và tôi sử dụng nó chẳng hạn trong stackoverflow.com/a/19206916/6309 .
VonC

Đúng, tốt đẹp. Nhìn qua các câu trả lời khác, tôi nghĩ câu trả lời của @errordeveloper là sạch nhất: stackoverflow.com/a/21284342/2562319 : "git grep <regapi> $ (git for-Each-ref --format = '% (refname) 'refs /) "
jbyler

1
Có cách nào để hiển thị tên của chi nhánh phù hợp với tìm kiếm không?
franksands

63

git log có thể là một cách hiệu quả hơn để tìm kiếm văn bản trên tất cả các chi nhánh, đặc biệt là nếu có nhiều kết quả khớp và bạn muốn xem các thay đổi gần đây (có liên quan) trước.

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

Các danh sách lệnh log này cam kết thêm hoặc xóa chuỗi tìm kiếm / regex đã cho, (nói chung) gần đây hơn trước. Các -ptùy chọn làm cho diff có liên quan sẽ được hiển thị nơi các mô hình đã được bổ sung hoặc loại bỏ, vì vậy bạn có thể nhìn thấy nó trong ngữ cảnh.

Đã tìm thấy một cam kết có liên quan bổ sung thêm văn bản bạn đang tìm kiếm (ví dụ: 8beeff00d), hãy tìm các nhánh có chứa cam kết:

git branch -a --contains 8beeff00d

22

Tôi thấy điều này hữu ích nhất:

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

Bạn cần điều chỉnh các đối số cuối cùng tùy thuộc vào việc bạn có muốn chỉ nhìn từ xa so với các nhánh cục bộ hay không, tức là:

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

Bí danh tôi tạo ra trông như thế này:

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

1
Bí danh thú vị. +1. Chính xác hơn trong câu trả lời của tôi.
VonC

Làm thế nào để làm cho bí danh của bạn để làm việc cho tìm kiếm cụm từ? Khi tôi vượt qua "foo bar" làm tham số, tôi nhận được: fatal: đối số mơ hồ 'bar': sửa đổi không xác định hoặc đường dẫn không nằm trong cây làm việc. Sử dụng '-' để tách các đường dẫn khỏi các phiên bản
jutky

Hãy thử thoát khỏi không gian: "foo \ bar"
Garry Gomez

Đây rõ ràng sẽ là câu trả lời được chấp nhận;) Tôi đã mở rộng trên đó để chỉ tìm kiếm trên các chi nhánh mới nhất của dự án của tôi (Có hơn 500, đừng hỏi và mỗi grep mất khoảng 4 giây nên tôi không muốn cũng không cần để tìm kiếm trên nhiều hơn, giả sử, 100 mới nhất trong số họ). Đối với điều này, tôi đã cập nhật git for-each-refvới --sort=-committerdate --count=100! Cảm ơn ý tưởng ban đầu!
Vser

6

Có thể làm điều đó theo hai cách phổ biến: bí danh Bash hoặc Git

Dưới đây là ba lệnh:

  1. git grep-branch - Tìm kiếm trong tất cả các chi nhánh địa phương và từ xa
  2. git grep-branch-local - Chỉ tìm kiếm trong các chi nhánh địa phương
  3. git grep-branch-remote - Chỉ chi nhánh từ xa

Cách sử dụng giống như git grep

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

GREP sử dụng: bí danh Git

Tệp ~ / .gitconfig

Các lệnh nên được thêm thủ công vào ~/.gitconfigtệp, vì git config --global aliasđánh giá mã phức tạp mà bạn thêm và làm rối nó.


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

Lưu ý: Khi bạn thêm bí danh và chúng không chạy được - hãy kiểm tra dấu gạch chéo ngược, \chúng có thể yêu cầu thoát bổ sung \\so với các lệnh bash .

  • git branch -a - Hiển thị tất cả các chi nhánh;
  • sed -e 's/[ \\*]*//'- Cắt khoảng trắng (từ branch -a) và * (tên nhánh hoạt động có nó);
  • grep -v -e '\\->'- Bỏ qua các tên phức tạp như remotes/origin/HEAD -> origin/master;
  • grep '^remotes' - Nhận tất cả các chi nhánh từ xa;
  • grep -v -e '^remotes'- Nhận chi nhánh trừ chi nhánh từ xa;

Thí dụ git grep-branch-local -n getTastyCookies

-n Tiền tố số dòng để phù hợp với dòng.

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

Cấu trúc hiện tại là:

: - Dấu phân cách

  1. Chi nhánh: dev
  2. Số dòng: 53
  3. Đường dẫn tập tin: modules/factory/getters.php
  4. Dòng phù hợp: function getTastyCookies($user)

GREP sử dụng: BASH

Như bạn nên biết: Các lệnh Bash nên được lưu trữ trong .shcác tập lệnh hoặc chạy trong trình bao.

Chỉ chi nhánh địa phương

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

Chỉ chi nhánh từ xa

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

Chi nhánh địa phương và từ xa

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

Nghe có vẻ hay, nhưng tôi đã nhận được lỗi này từ git grep-branch "find my text":fatal: ambiguous argument 'client': both revision and filename
nealmcb

Tại sao luôn luôn sử dụng -a, trong đó hiển thị tất cả các chi nhánh? Tôi sẽ đề nghị sử dụng các tùy chọn cho git branchlệnh để phân tách đau khổ. Khi nhìn vào các chi nhánh địa phương, chỉ có một chiếc duy nhất *, vì vậy không cần phải thoát khỏi nó cho sed. Vì vậy: chỉ git branch | sed -e 's/*/ /' | xargs git grep "TEXT"dành cho các chi nhánh địa phương, chỉ git branch -r | grep -v -- "->" | xargs git grep "TEXT"cho các chi nhánh ở xa và git branch -a | grep -v -- "->" | xargs git grep "TEXT"cho tất cả các chi nhánh
jalanb

4

Đây là cách tôi làm điều đó:

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

2
Giải pháp duy nhất hiệu quả với tôi trên Windows (trong Git bash)
Ivan

4

Nếu bạn đưa ra bất kỳ cam kết nào về giá trị băm SHA-1 cho git grepbạn, hãy tìm kiếm trong đó, thay vì bản sao làm việc.

Để tìm kiếm tất cả các chi nhánh, bạn có thể lấy tất cả các cây với git rev-list --all. Đặt tất cả với

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

... và kiên nhẫn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.