Làm cách nào để tìm kiếm thông qua tất cả các cam kết Git và Mercurial trong kho lưu trữ cho một chuỗi nhất định?


287

Tôi có một kho lưu trữ Git với một vài chi nhánh và các cam kết lơ lửng. Tôi muốn tìm kiếm tất cả các cam kết như vậy trong kho lưu trữ cho một chuỗi cụ thể.

Tôi biết làm thế nào để có được một bản ghi của tất cả các cam kết trong lịch sử, nhưng chúng không bao gồm các nhánh hoặc các đốm màu lơ lửng, chỉ là lịch sử của CHÍNH. Tôi muốn có được tất cả, để tìm một cam kết cụ thể đã bị đặt sai chỗ.

Tôi cũng muốn biết làm thế nào để làm điều này trong Mercurial, khi tôi đang xem xét việc chuyển đổi.


Câu trả lời:


331

Bạn có thể thấy cam kết lơ lửng với git log -g.

-g, --walk-reflogs
 Instead of walking the commit ancestry chain, walk reflog entries from
 the most recent one to older ones. 

Vì vậy, bạn có thể làm điều này để tìm một chuỗi cụ thể trong thông điệp cam kết đang treo lủng lẳng:

git log -g --grep=search_for_this

Ngoài ra, nếu bạn muốn tìm kiếm các thay đổi cho một chuỗi cụ thể, bạn có thể sử dụng tùy chọn tìm kiếm pickaxe, "-S":

git log -g -Ssearch_for_this
# this also works but may be slower, it only shows text-added results
git grep search_for_this $(git log -g --pretty=format:%h)

Git 1.7.4 sẽ thêm tùy chọn -G , cho phép bạn vượt qua -G <regapi> để tìm khi một dòng chứa <regapi> được di chuyển, điều mà -S không thể làm được. -S sẽ chỉ cho bạn biết khi tổng số dòng chứa chuỗi thay đổi (tức là thêm / xóa chuỗi).

Cuối cùng, bạn có thể sử dụng gitk để trực quan hóa các cam kết lơ lửng với:

gitk --all $(git log -g --pretty=format:%h)

Và sau đó sử dụng các tính năng tìm kiếm của nó để tìm tệp thất lạc. Tất cả các công việc này giả sử cam kết bị mất chưa "hết hạn" và đã được thu gom rác, điều này có thể xảy ra nếu nó bị treo trong 30 ngày và bạn hết hạn sử dụng hoặc chạy một lệnh hết hạn.


4
Có lẽ thay vì chạy "git grep" trên số lượng cam kết (có thể lớn), sẽ tìm thấy tất cả các cam kết có 'search_for_this' ở đâu đó trong một dự án, sử dụng tùy chọn được gọi là "pickaxe", tức là tùy chọn '-S' để git log , tìm thấy các xác nhận đã giới thiệu hoặc loại bỏ chuỗi đã cho hoặc chính xác hơn là số lần xuất hiện của một chuỗi đã cho thay đổi.
Jakub Narębski

5
Bạn có thể chỉ định nhiều nhánh hoặc sử dụng tùy chọn '--all', ví dụ 'git log --grep = "chuỗi trong thông điệp cam kết" --all'
Jakub Narębski

Điều này chỉ cho phép tôi tìm một cam kết bị mất trong 2 ngày làm việc. Hoàn toàn lưu mông của tôi, cảm ơn!
Mike Chamberlain

2
Tôi đã gặp một số tình huống mà tôi đã cam kết trong cơ sở dữ liệu của mình nhưng không phải trong tài liệu của tôi. Tôi không biết mức độ phổ biến của nó. Tôi đã thử các cầu hg / git khác nhau. Tôi nghĩ rằng nó cũng có thể phát sinh với stash rơi. Trong mọi trường hợp, bí danh này hoạt động độc đáo để bắt những trường hợp đó:!git fsck --unreachable | sed -ne 's/^unreachable commit //p' | xargs git log --no-walk
dubiousjim

Lưu ý, điều đó không bao gồm các đối tượng ghi chú tìm kiếm. Điều đó chưa được triển khai: git.661346.n2.nabble.com/ từ
Antony Stubbs

54

Trong Mercurial, bạn sử dụng hg log --keywordđể tìm kiếm từ khóa trong thông điệp cam kết và hg log --usertìm kiếm một người dùng cụ thể. Xem hg help logcác cách khác để giới hạn nhật ký.


36
Josip đã viết rằng anh ta đang xem xét chuyển sang Mercurial và anh ta cũng muốn nghe cách nó được thực hiện ở đó.
Martin Geisler

1
hg log -ktìm kiếm cam kết tên người dùng và tên tệp trong bộ thay đổi (tôi thấy rằng trong Command.py:log), đây là một trong số ít những điều mà tôi không hiểu trong hg. Cần có các tùy chọn riêng để tìm kiếm trong thông điệp cam kết và tên tệp. Có vẻ như hg log --template '{desc}\n'|greplà cách chắc chắn.
Geoffrey Zheng

@GeoffreyZheng: có nhiều cách để làm điều đó. Xem "hg help revsets", đặc biệt là các hàm desc (), user () và file (). Ngoài ra còn có các chuyển đổi nhật ký hg cho hầu hết các hành vi này. Theo kinh nghiệm của tôi, mặc dù -k / keyword () thường là cách hữu ích nhất để tìm kiếm mọi thứ.
Kevin Horn

Làm thế nào để một tìm kiếm thông qua nội dung tập tin cam kết thực tế ... khác biệt? Tôi biết nó sẽ là một tìm kiếm chậm, nhưng tôi muốn thực hiện tìm kiếm sâu cho một tên hàm bị thiếu.
Jonathan

Ồ đây rồi:hg grep --all <term>
Jonathan

24

Ngoài câu trả lời phong phú về việc sử dụng git log -g --grep=<regexp>hoặc git grep -e <regexp> $(git log -g --pretty=format:%h): hãy xem các bài đăng trên blog sau đây của Junio ​​C Hamano, người duy trì git hiện tại


Tóm lược

Cả git grepgit log --grep đều được định hướng theo dòng , trong đó chúng tìm kiếm các dòng khớp với mẫu đã chỉ định.

Bạn có thể sử dụng git log --grep=<foo> --grep=<bar>(hoặc git log --author=<foo> --grep=<bar>dịch nội bộ thành hai --grep) để tìm các xác nhận khớp với một trong hai mẫu (ẩn HOẶC ngữ nghĩa).

Do được định hướng theo dòng, nên ngữ nghĩa AND hữu ích là sử dụng git log --all-match --grep=<foo> --grep=<bar>để tìm cam kếtcả khớp dòng đầu tiên và khớp dòng thứ hai ở đâu đó.

Với git grepbạn có thể kết hợp nhiều mô hình (tất cả mà phải sử dụng -e <regexp>theo mẫu) với --or(đó là mặc định), --and, --not, (). Đối với grep --all-matchcó nghĩa là tệp phải có các dòng khớp với từng lựa chọn thay thế.


Này Jakub, hãy tích hợp các trích dẫn / tóm tắt từ các bài đăng trên blog ở đây? Có vẻ như một trong những câu trả lời chỉ liên kết cổ điển ngay bây giờ.
Nathan Tuggy

11

Dựa trên câu trả lời của rq, tôi thấy dòng này thực hiện những gì tôi muốn:

git grep "search for something" $(git log -g --pretty=format:%h -S"search for something")

Sẽ báo cáo ID cam kết, tên tệp và hiển thị dòng phù hợp, như thế này:

91ba969:testFile:this is a test

... Có ai đồng ý rằng đây sẽ là một lựa chọn tốt để được đưa vào lệnh git grep tiêu chuẩn không?


5

Bất kỳ lệnh nào lấy tham chiếu làm đối số sẽ chấp nhận --alltùy chọn được ghi lại trong trang man git rev-listnhư sau:

   --all
       Pretend as if all the refs in $GIT_DIR/refs/ are listed on the
       command line as <commit>.

Vì vậy, ví dụ git log -Sstring --allsẽ hiển thị tất cả các cam kết đề cập stringvà có thể truy cập được từ một chi nhánh hoặc từ một thẻ (Tôi giả sử rằng các cam kết lơ lửng của bạn ít nhất được đặt tên bằng một thẻ).


3
Điều này dường như không phải là trường hợp git grep, nơi --alldường như được dịch sang / được sử dụng như --all-match. Điều này có vẻ như là một lỗi đối với tôi .. sử dụng Git 1.7.2.3 (sử dụng $(git rev-list --all)các tác phẩm).
xanh

5

Với Mercurial bạn làm một

$ hg grep "search for this" [file...]

Có các tùy chọn khác thu hẹp phạm vi sửa đổi được tìm kiếm.


1
Tôi cũng thích cờhg grep --all
Jonathan

2

Không biết về git, nhưng trong Mercurial, tôi chỉ chuyển đầu ra của nhật ký hg sang một số tập lệnh sed / perl / bất cứ thứ gì để tìm kiếm bất cứ thứ gì bạn đang tìm kiếm. Bạn có thể tùy chỉnh đầu ra của nhật ký hg bằng cách sử dụng một mẫu hoặc một kiểu để giúp tìm kiếm dễ dàng hơn, nếu bạn muốn.

Điều này sẽ bao gồm tất cả các chi nhánh được đặt tên trong repo. Mercurial không có cái gì đó giống như những đốm sáng lơ lửng afaik.


1
Tôi không hiểu câu trả lời này có liên quan đến vấn đề được chỉ định như thế nào.
jribeiro

3
Đó là một câu trả lời cho câu hỏi dành cho Mercurial, câu hỏi ban đầu hỏi về đoạn cuối.
Kurt Schelfthout


1

Để thêm chỉ một giải pháp nữa chưa được đề cập, tôi phải nói rằng sử dụng hộp tìm kiếm đồ họa của gitg là giải pháp đơn giản nhất đối với tôi. Nó sẽ chọn lần xuất hiện đầu tiên và bạn có thể tìm lần xuất hiện tiếp theo bằng Ctrl-G.


1

Một lệnh trong git mà tôi nghĩ rằng việc tìm chuỗi dễ dàng hơn nhiều:

git log --pretty=oneline --grep "string to search"

hoạt động trong Git 2.0.4

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.