Chỉ hiển thị các khối có liên quan của diff / patch dựa trên regrec


20

git log -G<regex> -plà một công cụ tuyệt vời để tìm kiếm lịch sử của một cơ sở mã cho những thay đổi phù hợp với mẫu đã chỉ định. Tuy nhiên, có thể quá sức để xác định vị trí của hunk có liên quan trong sản lượng diff / patch trong một biển của những con chó săn chủ yếu không liên quan.

Tất nhiên có thể tìm kiếm đầu ra của git logchuỗi / regex ban đầu, nhưng điều đó không làm giảm tiếng ồn thị giác và mất tập trung của nhiều thay đổi không liên quan.

Đọc tiếp git log, tôi thấy có --pickaxe-all, điều hoàn toàn trái ngược với những gì tôi muốn: nó mở rộng đầu ra (cho toàn bộ thay đổi), trong khi tôi muốn giới hạn nó (với hunk cụ thể).

Về cơ bản, tôi đang tìm cách "phân tích" một cách thông minh các khác biệt / vá thành các khối riêng lẻ và sau đó thực hiện tìm kiếm theo từng khối (chỉ nhắm mục tiêu các dòng đã thay đổi), loại bỏ các khối không khớp và xuất ra các khối điều đó

Có một công cụ như tôi mô tả tồn tại? Có một cách tiếp cận tốt hơn để có được hunk phù hợp / bị ảnh hưởng?

Một số nghiên cứu ban đầu tôi đã thực hiện ...

  • Nếu có thể với grepđầu ra diff / patch và làm cho các giá trị tùy chọn ngữ cảnh động động nói, thông qua biểu thức chính quy thay vì đếm dòng có thể đủ. Nhưng grepkhông được xây dựng chính xác theo cách đó (tôi cũng không nhất thiết phải yêu cầu tính năng đó).

  • Tôi tìm thấy bộ patchutils , ban đầu nghe có vẻ phù hợp với nhu cầu của tôi. Nhưng sau khi đọc các mantrang của nó , các công cụ dường như không xử lý các khối tương ứng dựa trên biểu thức chính quy. (Họ có thể chấp nhận một danh sách những người đi săn, mặc dù ...)

  • Cuối cùng tôi đã tìm thấy splitpatch.rb , có vẻ như xử lý tốt việc phân tích cú pháp của bản vá, nhưng nó sẽ cần được tăng cường đáng kể để xử lý các bản vá đọc thông qua stdin, khớp với các hunk mong muốn, và sau đó xuất ra các hunk.


1
Không exacly những gì bạn yêu cầu nhưng hãy thử git log -Gfoo | ít hơn + / foo
James Youngman

Câu trả lời:


7

tại đây /programming//a353434714/5305907 được mô tả một cách để làm những gì bạn đang tìm kiếm. hiệu quả:

git diff -U1 | grepdiff 'console' --output-matching=hunk

Nó chỉ hiển thị các hunk khớp với "console" đã cho.


cảm ơn. grepdiffvề cơ bản là những gì tôi muốn; tôi phải bỏ lỡ tùy chọn khớp hunk của nó! tuy nhiên ... thông tin cam kết git bị tước bỏ grepdiff, do đó, khi bạn xác định vị trí của hunk có liên quan, bạn phải phân chia sha cam kết từ đối tượng / blob sha trong tiêu đề diff khác một thao tác đắt tiền. (xem stackoverflow.com/a/223890/2284440 ) nó sẽ giống nhưgit find-object SHA --reverse | head -1 | cut -c 1-7 | { read sha ; git log -1 $sha; }
wrksprfct

cũng lưu ý rằng có một phiên bản golang tronggrepdiff đó có nhiều barebones hơn về các đối số được chấp nhận. lưu ý rằng khi hunk khớp là hunk cuối cùng trong diff, nó không chính xác bao gồm tiêu đề git commit của cam kết sau đây một cái gì đó làm tôi bối rối cho đến khi tôi nhận ra chuyện gì đang xảy ra!
wrksprfct

0

Không chính xác những gì bạn đang yêu cầu, nhưng một cách để grep qua hunk là chế độ thêm tương tác. Điều này đòi hỏi bạn phải kiểm tra cam kết sau khi bản vá bạn quan tâm

git checkout COMMIT_ID

sau đó quay lại một bước nữa trong VCS, nhưng không phải trong thư mục làm việc

git reset --soft HEAD^

(Tại thời điểm này, sự khác biệt giữa chỉ mục và thư mục làm việc sẽ tương ứng với bản vá bạn quan tâm.)

Bây giờ bạn có thể thực hiện git add -p. Điều này sẽ khởi chạy một phiên tương tác có một /tùy chọn, cho phép bạn xác định vị trí những người đi đường trong đó một số dòng khớp với biểu thức chính quy. Đặc biệt hữu ích nếu bạn thực sự muốn xử lý thêm các bản vá đó (như, chuẩn bị một phần cherry-pick).

Thật không may, ít nhất là ngay bây giờ /lệnh add -pchỉ hoạt động trong một tệp duy nhất, vì vậy bạn có thể cần phải bỏ qua một số tệp không liên quan.


0

Dựa trên câu trả lời ở trên của @nagu và các câu trả lời được liên kết khác, tôi git log -Gchỉ có thể hiển thị những người có liên quan.

  1. Trước tiên, hãy tạo tập lệnh ở đâu đó trong $ PATH của bạn với nội dung này:

    #!/bin/bash
    
    # pickaxe-diff : external diff driver for Git.
    #                To be used with the pickaxe options (git [log|show|diff[.*] [-S|-G])
    #                to only show hunks containing the searched string/regex.
    
    path=$1
    old_file=$2
    old_hex=$3
    old_mode=$4
    new_file=$5
    new_hex=$6
    new_mode=$7
    
    filtered_diff=$(diff -u -p $old_file $new_file | \
                    grepdiff "$GREPDIFF_REGEX" --output-matching=hunk | \
                    grep -v -e '+++ ' -e '--- ')
    
    a_path="a/$path"
    b_path="b/$path"
    
    echo "diff --git $a_path $b_path"
    echo "index $old_hex..$new_hex $old_mode"
    echo "--- $a_path"
    echo "+++ $b_path"
    echo "$filtered_diff"
  2. Gọi git log -Gvà bảo Git sử dụng pickaxe-difftập lệnh làm trình điều khiển khác ngoài:

    export GREPDIFF_REGEX=<string>; 
    GIT_EXTERNAL_DIFF=pickaxe-diff git log -p --ext-diff -G $GREPDIFF_REGEX

    Điều này sẽ sử dụng tập lệnh pickaxe-diff chỉ để tạo ra các khác biệt, vì vậy phần còn lại của git logđầu ra (cam kết băm, thông báo, v.v.) sẽ không được xử lý.

Hãy cẩn thận
Cách mà công cụ chọn Git hoạt động là nó giới hạn đầu ra cho các tệp có phần thân thay đổi chuỗi / regex đã cho. Điều này có nghĩa là nếu một hunk khác trong các tệp này cũng chứa chuỗi tìm kiếm / regex, nhưng không thay đổi nó, nó vẫn sẽ được hiển thị với tập lệnh trên. Đây là một hạn chế của grepdiff. Có một yêu cầu kéo mở tại dự án patchutils để thêm một --only-matchingcờ vào grepdiff, nó sẽ cung cấp các chức năng cần thiết để lọc chính xác các khối này.


Tôi đã viết một giải pháp của tôi trong ý chính này .

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.