Hanya tampilkan bakhil yang relevan dari suatu diff / patch berdasarkan pada regexp

20

git log -G<regex> -padalah alat yang luar biasa untuk mencari sejarah basis kode untuk perubahan yang cocok dengan pola yang ditentukan. Namun, itu bisa menjadi luar biasa untuk menemukan bongkahan yang relevan di output diff / patch di lautan bakhil yang sebagian besar tidak relevan.

Tentu saja mungkin untuk mencari output dari git logstring / regex asli, tetapi itu tidak banyak mengurangi kebisingan visual dan gangguan banyak perubahan yang tidak terkait.

Membaca git log, saya melihat ada --pickaxe-all, yang merupakan kebalikan dari apa yang saya inginkan: itu memperluas output (ke seluruh changeset), sedangkan saya ingin membatasi (ke bingkah tertentu).

Pada dasarnya, saya mencari cara untuk "secara cerdas" mengurai diff / patch ke masing-masing bakhil dan kemudian melakukan pencarian terhadap masing-masing bakhil (hanya menargetkan baris yang diubah), membuang bakhil yang tidak cocok, dan menghasilkan yang itu.

Apakah alat seperti yang saya jelaskan ada? Apakah ada pendekatan yang lebih baik untuk mendapatkan bakhil yang cocok / terpengaruh?

Beberapa penelitian awal yang telah saya lakukan ...

  • Jika dimungkinkan untuk grepkeluaran diff / patch dan membuat nilai opsi konteks menjadi dinamis — katakanlah, melalui regexps alih-alih jumlah baris — itu mungkin sudah cukup. Tapi greptidak persis seperti itu (saya juga tidak perlu meminta fitur itu).

  • Saya menemukan paket patchutils , yang awalnya terdengar seperti mungkin sesuai dengan kebutuhan saya. Tetapi setelah membaca manhalaman - halamannya, alat tersebut tampaknya tidak menangani bakhil yang cocok berdasarkan regexps. (Mereka dapat menerima daftar orang bakhil, meskipun ...)

  • Saya akhirnya menemukan splitpatch.rb , yang tampaknya menangani penguraian tambalan dengan baik, tetapi perlu ditambah secara signifikan untuk menangani pembacaan tambalan melalui stdin, mencocokkan bakhil yang diinginkan, dan kemudian menghasilkan bakhil.

wrksprfct
sumber
1
Tidak persis apa yang Anda minta tetapi coba git log -Gfoo | kurang + / foo
James Youngman

Jawaban:

7

di sini /programming//a/35434714/5305907 dijelaskan cara untuk melakukan apa yang Anda cari. secara efektif:

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

Ini hanya menampilkan bakhil yang cocok dengan string "konsol" yang diberikan.

nagu
sumber
Terima kasih. grepdiffpada dasarnya adalah apa yang saya inginkan; saya pasti melewatkan opsi pencocokan pasangannya! Namun ... info git commit dilucuti grepdiff, jadi setelah Anda menemukan bingkah yang relevan, Anda harus melihat sha kom dari objek / gumpalan sha di header diff-operasi yang cukup mahal. (lihat stackoverflow.com/a/223890/2284440 ) itu akan menjadi sepertigit find-object SHA --reverse | head -1 | cut -c 1-7 | { read sha ; git log -1 $sha; }
wrksprfct
juga perhatikan ada versi golanggrepdiff yang lebih barebones dalam hal argumen yang diterima. perhatikan bahwa ketika cowok yang cocok adalah cowok terakhir dalam diff, itu salah memasukkan header git commit dari commit berikut — sesuatu yang benar-benar membingungkan saya sampai saya menyadari apa yang terjadi!
wrksprfct
0

Tidak persis apa yang Anda minta, tetapi satu cara untuk memahami bakhil adalah mode add-interaktif. Ini mengharuskan Anda untuk memeriksa komit setelah tambalan yang Anda minati

git checkout COMMIT_ID

lalu kembali satu langkah lagi di VCS, tetapi tidak di direktori kerja

git reset --soft HEAD^

(Pada titik ini, perbedaan antara indeks dan direktori kerja akan sesuai dengan patch yang Anda minati.)

Anda sekarang dapat mengeksekusi git add -p. Ini akan meluncurkan sesi interaktif yang memiliki /opsi, yang memungkinkan Anda untuk menemukan bakhil di mana beberapa baris cocok dengan regex. Sangat berguna jika Anda benar-benar ingin memproses tambalan-tambalan itu (seperti, menyiapkan pick-cherry parsial).

Sayangnya, setidaknya saat ini /perintah add -phanya berfungsi dalam satu file, jadi Anda mungkin perlu melewati beberapa file yang tidak relevan.

leftaroundabout
sumber
0

Membangun jawaban di atas oleh @nagu, dan jawaban terkait lainnya, saya hanya bisa git log -Gmenunjukkan bakhil yang relevan.

  1. Pertama buat skrip di suatu tempat di $ PATH Anda dengan konten ini:

    #!/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. Panggil git log -Gdan beri tahu Git untuk menggunakan pickaxe-diffskrip sebagai driver diff eksternal:

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

    Ini akan menggunakan skrip pickaxe-diff hanya untuk menghasilkan diff, sehingga sisa git logoutput (komit hash, pesan, dll) akan tersentuh.

Peringatan
Cara kerja beliung Git adalah membatasi keluaran ke file yang bakhilnya mengubah string / regex yang diberikan. Ini berarti bahwa jika sepotong lain dalam file ini juga berisi string pencarian / regex, tetapi tidak mengubahnya, itu masih akan ditampilkan dengan skrip di atas. Ini adalah batasan grepdiff. Ada permintaan tarik terbuka di proyek patchutils untuk menambahkan --only-matchingbendera ke grepdiff, yang akan menyediakan fungsionalitas yang diperlukan untuk memfilter bakhun ini dengan benar.


Saya melakukan penulisan solusi saya di intisari ini .

philb
sumber