Git: Menampilkan semua dari berbagai perubahan ke satu baris dalam file tertentu di seluruh sejarah git

112

Saya telah melihat sekeliling, dan tidak yakin apakah ini mungkin, tetapi ini dia:

Saya memiliki file (javascript) (katakanlah /lib/client.js) di mana saya memiliki pengenal unik yang ditetapkan ke variabel, seperti: var identifier = "SOME_IDENTIFIER";

Anda dapat menganggap pengenal seperti nomor versi: Secara berkala, kami akan mengubah variabel ini menjadi pengenal baru.

Yang ingin saya lakukan adalah menemukan semua pengenal unik yang pernah kami gunakan. Bagaimana saya bisa melakukan ini dengan git?

Saya membayangkan mungkin ada cara untuk mencari melalui sejarah git, dan mencetak pencocokan baris "var identifier =". Saya dapat menghapus duplikat daftar ini secara manual.

Bagaimanapun, saya menghargai semua wawasan di sini. Terima kasih.

findchris
sumber
3
kemungkinan duplikat dari Ambil log komit untuk baris tertentu dalam file?
Aron Rotteveel

Jawaban:

106

Sejak git 1.8.4 , ada cara yang lebih langsung untuk menjawab pertanyaan Anda.

Dengan asumsi baris itu 110adalah baris yang mengatakan var identifier = "SOME_IDENTIFIER";, maka lakukan ini:

git log -L110,110:/lib/client.js

Ini akan mengembalikan setiap komit yang menyentuh baris kode itu.

[ Dokumentasi Git (lihat parameter baris perintah "-L")]

Alexander Bird
sumber
49

Lihat halaman manual untuk git-logdan gitdiffcore. Saya yakin perintah ini akan melakukannya, tetapi mungkin kurang tepat:

git log -G "var identifier =" file.js

EDIT: Inilah awal yang kasar untuk skrip bash untuk menunjukkan baris yang sebenarnya. Ini mungkin lebih dari yang Anda cari.

for c in $(git log -G "something" --format=%H -- file.js); do
    git --no-pager grep -e "something" $c -- file.js
done

Ini digunakan git log -Guntuk menemukan komit yang menarik, menggunakan --format=%Huntuk menghasilkan daftar hash komit. Itu kemudian mengulangi setiap komit yang menarik, meminta git grepuntuk menunjukkan baris dari komit itu dan file yang berisi regex, diawali dengan hash komit.


EDIT: Diubah untuk digunakan, -Gbukan -Sseperti yang disarankan dalam komentar.

rampok
sumber
@Rob - terima kasih untuk ini - edit kecil pada skrip Anda - menempatkan hanya nama file hanya menunjukkan komit yang hanya mempengaruhi file itu - jika komit mereferensikan file lain itu tidak terdaftar
Adrian Cornish
@AdrianCornish - Senang itu membantu. Saya pikir OP hanya ingin melihat satu file, tetapi Anda benar bahwa menghapus nama file mungkin merupakan skrip yang lebih berguna secara umum.
merampok
Saya memiliki situasi yang lebih sulit. File yang dimaksud dipindahkan dari paht_a / file ke path_b / file. Sekarang ketika saya melakukannya di path_b itu hanya menunjukkan perubahan hingga ketika file dipindahkan dari path_a ke path_b. Jika saya melakukannya di path_a, ia memberi tahu saya fatal: argumen ambigu 'file': revisi yang tidak diketahui atau jalur tidak ada di pohon kerja.
Andy Song
@AndySong - Jika string yang Anda cari cukup unik, mungkin Anda dapat meninggalkan nama file dan tetap mendapatkan apa yang Anda cari.
merampok
Lebih nyaman bagi saya - letakkan baris kosong setelah setiap komit, sfile=path/to/some_file; sfind='string_to_find'; for c in $(git log -G $sfind --format=%H -- $sfile); do git --no-pager grep -e $sfind -n $c -- $sfile; echo; done
sebutkan
14

Anda juga dapat melakukan ini dengan gitk:

gitk file.js

Di tarik-turun "komit", pilih "tambah / hapus string:" dan di kotak teks di sebelahnya, masukkan "var identifier =", dan komit apa pun yang menambah atau menghapus baris yang berisi string itu akan disorot.

Ethan Brown
sumber
Ini membantu menentukan komit di mana baris yang berisi "var identifier =" telah ditambahkan, tetapi tidak menunjukkan komit berikutnya yang mengubah baris ini.
findchris
2
Sudahkah Anda mencoba git blame file.jsatau git gui blame file.js?
Ethan Brown
1
Saya tahu apa yang dilakukan git menyalahkan; Saya mencari riwayat lengkap revisi, bukan perbedaan tunggal.
findchris
1
git gui blame file.jsakan melakukan itu ... itu akan menampilkan semua revisi file dan siapa yang mengubahnya; Anda cukup mengeklik mundur melalui riwayat.
Ethan Brown
Saya akhirnya melangkah melalui visual dengan gitk. Saya membayangkan ada beberapa teknik git yang elegan untuk melakukan ini, tetapi gitk sudah cukup baik. Terima kasih.
findchris
9

Jika Anda mengadaptasi jawaban @ rob sedikit, git logpada dasarnya akan melakukannya untuk Anda, jika yang Anda butuhkan hanyalah perbandingan visual:

git log -U0 -S "var identifier =" path/to/file

-U0berarti keluaran dalam mode tambalan ( -p), dan menunjukkan garis nol konteks di sekitar tambalan.

Anda bahkan dapat melakukan ini di seluruh cabang:

git log -U0 -S "var identifier =" branchname1 branchname2 -- path/to/file

Mungkin ada cara untuk menekan header diff, tapi saya tidak tahu satu pun.

Andrew
sumber
Bekerja untuk saya! Terima kasih.
Roberto Bonini
3

Di magit , Anda dapat melakukannya dengan

l, =L

Ini kemudian akan meminta Anda untuk file dan mulai, garis akhir.

daerah kumuh
sumber