Jadi saya menemukan pertanyaan tentang cara melihat riwayat perubahan file, tetapi riwayat perubahan file khusus ini sangat besar dan saya benar-benar hanya tertarik pada perubahan metode tertentu. Jadi, apakah mungkin melihat riwayat perubahan hanya untuk metode tertentu itu?
Saya tahu ini akan memerlukan git untuk menganalisis kode dan analisisnya akan berbeda untuk bahasa yang berbeda, tetapi deklarasi metode / fungsi terlihat sangat mirip di sebagian besar bahasa, jadi saya pikir mungkin seseorang telah menerapkan fitur ini.
Bahasa yang saya gunakan saat ini adalah Objective-C dan SCM yang saat ini saya gunakan adalah git, tapi saya tertarik untuk mengetahui apakah fitur ini tersedia untuk SCM / bahasa apa pun.
Jawaban:
Versi terbaru dari
git log
mempelajari bentuk khusus dari-L
parameter:Dengan kata lain: jika Anda meminta Git
git log -L :myfunction:path/to/myfile.c
, sekarang dengan senang hati akan mencetak riwayat perubahan fungsi itu.sumber
Menggunakan
git gui blame
sulit untuk digunakan dalam skrip, dan sementaragit log -G
dangit log --pickaxe
masing-masing dapat menunjukkan kepada Anda ketika definisi metode muncul atau hilang, saya belum menemukan cara untuk membuat daftar semua perubahan yang dibuat pada tubuh metode Anda.Namun, Anda dapat menggunakan
gitattributes
dantextconv
properti untuk mengumpulkan solusi yang dapat melakukannya. Meskipun fitur ini pada awalnya dimaksudkan untuk membantu Anda bekerja dengan file biner, fitur ini berfungsi dengan baik di sini.Kuncinya adalah meminta Git menghapus semua baris dari file kecuali yang Anda minati sebelum melakukan operasi diff. Kemudian
git log
,,git diff
dll. Hanya akan melihat area yang Anda minati.Inilah garis besar dari apa yang saya lakukan dalam bahasa lain; Anda dapat menyesuaikannya untuk kebutuhan Anda sendiri.
Tulis skrip shell pendek (atau program lain) yang menggunakan satu argumen - nama file sumber - dan hanya menampilkan bagian yang menarik dari file itu (atau tidak ada jika tidak ada yang menarik). Misalnya, Anda dapat menggunakan
sed
sebagai berikut:#!/bin/sh sed -n -e '/^int my_func(/,/^}/ p' "$1"
Tentukan
textconv
filter Git untuk skrip baru Anda. (Lihatgitattributes
halaman manual untuk lebih jelasnya.) Nama filter dan lokasi perintah bisa apapun yang Anda suka.Beri tahu Git untuk menggunakan filter itu sebelum menghitung diff untuk file yang dimaksud.
$ echo "my_file diff=my_filter" >> .gitattributes
Sekarang, jika Anda menggunakan
-G.
(perhatikan.
) untuk membuat daftar semua komit yang menghasilkan perubahan yang terlihat saat filter Anda diterapkan, Anda akan memiliki komit yang Anda minati. Opsi lain yang menggunakan rutinitas diff Git, seperti--patch
, akan juga dapatkan tampilan terbatas ini.Voilà!
Satu perbaikan berguna yang mungkin ingin Anda lakukan adalah membuat skrip filter Anda menggunakan nama metode sebagai argumen pertamanya (dan file sebagai yang kedua). Ini memungkinkan Anda menentukan metode baru yang menarik hanya dengan memanggil
git config
, daripada harus mengedit skrip Anda. Misalnya, Anda mungkin berkata:$ git config diff.my_filter.textconv "/path/to/my_command other_func"
Tentu saja, skrip filter dapat melakukan apa pun yang Anda suka, mengambil lebih banyak argumen, atau apa pun: ada banyak fleksibilitas di luar yang telah saya tunjukkan di sini.
sumber
git log memiliki opsi '-G' dapat digunakan untuk menemukan semua perbedaan.
Cukup berikan regex yang tepat dari nama fungsi yang Anda pedulikan. Sebagai contoh,
$ git log --oneline -G'^int commit_tree' 40d52ff make commit_tree a library function 81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory 7b9c0a6 git-commit-tree: make it usable from other builtins
sumber
--oneline
dengan-p
Hal terdekat yang dapat Anda lakukan adalah menentukan posisi fungsi Anda dalam file (mis. Katakanlah fungsi Anda
i_am_buggy
ada di baris 241-263 darifoo/bar.c
), kemudian jalankan sesuatu yang mempengaruhi:git log -p -L 200,300:foo/bar.c
Ini akan membuka lebih sedikit (atau pager yang setara). Sekarang Anda dapat mengetik
/i_am_buggy
(atau setara pager Anda) dan mulai melangkah melalui perubahan.Ini bahkan mungkin berhasil, tergantung pada gaya kode Anda:
git log -p -L /int i_am_buggy\(/,+30:foo/bar.c
Ini membatasi pencarian dari klik pertama regex itu (idealnya deklarasi fungsi Anda) hingga tiga puluh baris setelah itu. Argumen akhir juga bisa berupa regexp, meskipun mendeteksi bahwa dengan regexp adalah proposisi iffier.
sumber
-L ":int myfunc:foo/bar.c"
dan membatasi fungsi dengan nama itu. Ini luar biasa - terima kasih atas penunjuknya! Sekarang jika saja pendeteksian fungsi sedikit lebih dapat diandalkan ...Cara yang benar adalah menggunakan
git log -L :function:path/to/file
seperti yang dijelaskan dalam jawaban eckes .Tetapi sebagai tambahan, jika fungsi Anda sangat panjang, Anda mungkin ingin melihat hanya perubahan yang telah diperkenalkan oleh berbagai komit, bukan seluruh baris fungsi, termasuk yang tidak dimodifikasi, untuk setiap komit yang mungkin hanya menyentuh satu dari baris ini. Seperti orang biasa
diff
.Biasanya
git log
dapat melihat perbedaan dengan-p
, tetapi ini tidak berfungsi-L
. Jadi, Anda harusgrep
git log -L
menunjukkan hanya baris yang terlibat dan header commit / files untuk mengontekstualisasikannya. Triknya di sini adalah mencocokkan hanya garis berwarna terminal, menambahkan--color
sakelar, dengan regex. Akhirnya:git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3
Perhatikan bahwa
^[
harus aktual, literal^[
. Anda dapat mengetiknya dengan menekan ^ V ^ [di bash, yaitu Ctrl+ V, Ctrl+ [. Referensi di sini .Juga
-3
saklar terakhir , memungkinkan untuk mencetak 3 baris konteks keluaran, sebelum dan sesudah setiap baris yang cocok. Anda mungkin ingin menyesuaikannya dengan kebutuhan Anda.sumber
git menyalahkan menunjukkan kepada Anda siapa yang terakhir mengubah setiap baris file; Anda dapat menentukan baris yang akan diperiksa untuk menghindari histori baris di luar fungsi Anda.
sumber
git gui blame
Anda dapat menavigasi revisi lama.Tampilkan riwayat fungsi dengan
git log -L :<funcname>:<file>
seperti yang ditunjukkan dalam jawaban eckes dan git docJika hal itu menunjukkan tidak ada, lihat Mendefinisikan kustom sepotong-header untuk menambahkan sesuatu seperti
*.java diff=java
ke.gitattributes
file yang mendukung bahasa Anda.Tampilkan riwayat fungsi antara komit dengan
git log commit1..commit2 -L :functionName:filePath
Tampilkan riwayat fungsi yang kelebihan beban (mungkin ada banyak fungsi dengan nama yang sama, tetapi dengan parameter berbeda) dengan
git log -L :sum\(double:filepath
sumber