Làm thế nào để grep Git commit diffs hoặc nội dung cho một từ nhất định?


622

Trong kho lưu trữ mã Git, tôi muốn liệt kê tất cả các xác nhận có chứa một từ nhất định. Tôi đã thử nó

git log -p | grep --context=4 "word"

nhưng nó không nhất thiết phải trả lại cho tôi tên tệp (trừ khi nó ít hơn 5 dòng so với từ tôi đã tìm kiếm. Tôi cũng đã thử

git grep "word"

nhưng nó chỉ cung cấp cho tôi các tập tin hiện tại và không phải là lịch sử.

Làm cách nào để tìm kiếm toàn bộ lịch sử để tôi có thể theo dõi các thay đổi trên một từ cụ thể? Tôi dự định tìm kiếm cơ sở mã của mình để tìm sự xuất hiện của từ để theo dõi các thay đổi (tìm kiếm trong lịch sử tập tin).


Câu trả lời:


905

Nếu bạn muốn tìm tất cả các xác nhận trong đó thông điệp cam kết chứa từ đã cho, hãy sử dụng

$ git log --grep=word

Nếu bạn muốn tìm tất cả các xác nhận trong đó "từ" đã được thêm hoặc xóa trong nội dung tệp (chính xác hơn: nơi số lần xuất hiện của "từ" đã thay đổi), tức là tìm kiếm nội dung cam kết , hãy sử dụng tìm kiếm 'pickaxe' với

$ git log -Sword

Trong git hiện đại cũng có

$ git log -Gword

để tìm sự khác biệt có dòng được thêm hoặc xóa khớp với "từ" (cũng cam kết nội dung ).

Lưu ý rằng -Gtheo mặc định chấp nhận một biểu thức chính quy, trong khi -Schấp nhận một chuỗi, nhưng có thể được sửa đổi để chấp nhận các biểu thức chính bằng cách sử dụng --pickaxe-regex.

Để minh họa sự khác biệt giữa -S<regex> --pickaxe-regex-G<regex>, hãy xem xét một cam kết với khác biệt sau trong cùng một tệp:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

Trong khi git log -G"regexec\(regexp"sẽ hiển thị cam kết này, git log -S"regexec\(regexp" --pickaxe-regexsẽ không (vì số lần xuất hiện của chuỗi đó không thay đổi).


Với Git 2.25.1 (tháng 2 năm 2020), tài liệu được làm rõ xung quanh các biểu thức đó.

Xem cam kết 9299f84 (06 tháng 2 năm 2020) của Martin gren (``) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 0d11410 , ngày 12 tháng 2 năm 2020)

diff-options.txt: tránh quá tải "regex" trong ví dụ

Báo cáo bởi: Adam Dinwoodie
Đã đăng ký: Martin gren
Được đánh giá bởi: Taylor Blau

Khi chúng tôi minh họa sự khác biệt giữa -G-S(sử dụng --pickaxe-regex), chúng tôi sẽ sử dụng một ví dụ khác và git diffgọi liên quan đến "regexec", "regrec", "regmatch", ...

Ví dụ này là chính xác, nhưng chúng ta có thể làm cho việc gỡ rối dễ dàng hơn bằng cách tránh viết "regex. *" Trừ khi thực sự cần thiết để đưa ra quan điểm của chúng tôi.

Thay vào đó, hãy sử dụng một số từ trang điểm, không gây khó chịu.

Các git difftài liệu hiện bao gồm:

Để minh họa sự khác biệt giữa -S<regex> --pickaxe-regex-G<regex>, hãy xem xét một cam kết với khác biệt sau trong cùng một tệp:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

Trong khi git log -G"frotz\(nitfol"sẽ hiển thị cam kết này, git log -S"frotz\(nitfol" --pickaxe-regexsẽ không (vì số lần xuất hiện của chuỗi đó không thay đổi).


3
@TankorSmash -S<string>Tìm kiếm sự khác biệt giới thiệu hoặc xóa một thể hiện của <chuỗi>. -G<string>Tìm kiếm sự khác biệt có dòng được thêm hoặc xóa phù hợp với <regex> đã cho.
m-ric

1
@ m-ric Tôi thấy, một trường hợp chuỗi đơn, so với toàn bộ một dòng! Cảm ơn
TankorSmash

3
@ m-ric, @TankorSmash: Sự khác biệt là -S<string>nhanh hơn vì nó chỉ kiểm tra nếu số lần xuất hiện <string>thay đổi, trong khi -G<string>các tìm kiếm được thêm và xóa dòng trong mỗi lần xác nhận khác nhau.
Jakub Narębski

3
Nếu bạn cần tìm kiếm các từ có khoảng trắng ở giữa , git log --grep="my words".
MEM

4
@MEM, --grepkhác với -S-G. Bạn có thể trích dẫn chuỗi cho mỗi đối số này.
Acumenus

255

git logPickaxe sẽ tìm thấy các cam kết với các thay đổi bao gồm "từ" với git log -Sword


60
Điều này không hoàn toàn chính xác. -S <string> Tìm kiếm sự khác biệt giới thiệu hoặc xóa một thể hiện của <chuỗi>. Lưu ý rằng điều này khác với chuỗi đơn giản xuất hiện trong đầu ra khác;
tymtam

4
Mặc dù đây thường là câu trả lời đúng, tôi chỉ đánh giá thấp để khuyến khích người khác đọc câu trả lời này ( stackoverflow.com/a/1340245/586983 ) có 3 cách khác nhau và giải thích sự tinh tế của họ.
jakeonrails 7/1/2016

18
trời ạ Tôi không nghĩ rằng đó là một lý do chính đáng để đánh giá thấp một câu trả lời đúng ... bạn không tự tin bao gồm liên kết trong một bình luận sẽ đủ khích lệ?
Deborah

@jakeonrails, Câu trả lời đó đáng lẽ phải là một chỉnh sửa cho cái này (cũ hơn), vì vậy chúng tôi không có những bản sao khó chịu này. Nhưng mọi người chỉ muốn danh tiếng, thay vì một trang câu trả lời sạch sẽ.
Iulian Onofrei

22

Sau rất nhiều thử nghiệm, tôi có thể đề xuất các mục sau, trong đó hiển thị các cam kết giới thiệu hoặc xóa các dòng có chứa biểu thức chính quy và hiển thị các thay đổi văn bản trong mỗi, với màu sắc hiển thị các từ được thêm và xóa.

git log --pickaxe-regex -p --color-words -S "<regexp to search for>"

Mất một lúc để chạy mặc dù ... ;-)


2
Đây là một trong những tốt nhất cho đến nay cảm ơn. Gợi ý: chỉ liệt kê tất cả các kết quả mà không cần phân trang, hoặc thêm lệnh vào GIT_PAGER=cathoặc nối nó với| cat
Zack Morris

Chỉ định đường dẫn hoặc tệp sẽ nhanh hơn nhiềugit log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
fangxing

10

Bạn có thể thử lệnh sau:

git log --patch --color=always | less +/searching_string

hoặc sử dụng greptheo cách sau:

git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'

Chạy lệnh này trong thư mục cha mà bạn muốn tìm kiếm.


2
Tôi thích phương pháp này vì các cam kết tôi đang xem có hàng trăm dòng thay đổi không liên quan và tôi chỉ quan tâm đến các bản vá thực tế có liên quan đến từ mà tôi đang tìm kiếm. Để có được màu sử dụng git log --patch --color=always | less +/searching_string.
Radon Rosborough

9

Một cách nữa / cú pháp để làm điều đó là: git log -S "word"
Như thế này bạn có thể tìm kiếm ví dụgit log -S "with whitespaces and stuff @/#ü !"


1

vim-fugitive là linh hoạt cho loại kiểm tra đó trong Vim.

Sử dụng :Ggrepđể làm điều đó. Để biết thêm thông tin, bạn có thể cài đặt vim-fugitive và tìm kiếm khu vực bằng cách :help Grep. Và tập phim này: expl-the-history-of-a-git-repository sẽ hướng dẫn bạn làm tất cả những điều đó.


1

Để sử dụng trình kết nối boolean trên biểu thức chính quy:

git log --grep '[0-9]*\|[a-z]*'

Tìm kiếm biểu thức chính quy này cho biểu thức chính quy [0-9] * hoặc [az] * trên các thông điệp cam kết.


-1

Nếu bạn muốn tìm kiếm dữ liệu nhạy cảm để xóa nó khỏi lịch sử git của bạn (đó là lý do tại sao tôi hạ cánh ở đây), có những công cụ cho việc đó. Github như một trang trợ giúp dành riêng cho vấn đề đó .

Đây là ý chính của bài viết:

Các BFG Repo-Cleaner là một nhanh hơn, đơn giản hơn thay thế cho git filter-branch để loại bỏ dữ liệu không mong muốn. Ví dụ: để xóa tệp của bạn bằng dữ liệu nhạy cảm và không để lại cam kết mới nhất của bạn), hãy chạy:

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

Để thay thế tất cả văn bản được liệt kê trong password.txt bất cứ nơi nào có thể tìm thấy trong lịch sử kho lưu trữ của bạn, hãy chạy:

bfg --replace-text passwords.txt

Xem tài liệu BFG Repo-Cleaner để biết hướng dẫn sử dụng và tải xuống đầy đủ.


Bạn có thể muốn thêm câu trả lời này vào stackoverflow.com/questions/872565/, thay vì ở đây
lacostenycoder
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.