Bagaimana cara grit Git melakukan diff atau konten untuk kata tertentu?

622

Dalam repositori kode Git saya ingin mendaftar semua komit yang berisi kata tertentu. Saya mencoba ini

git log -p | grep --context=4 "word"

tetapi tidak selalu memberi saya kembali nama file (kecuali jika kurang dari 5 baris dari kata yang saya cari. Saya juga mencoba

git grep "word"

tapi itu hanya memberi saya file yang ada dan bukan histori.

Bagaimana cara mencari seluruh riwayat sehingga saya dapat mengikuti perubahan pada kata tertentu? Saya bermaksud mencari basis kode untuk mencari kata yang dapat melacak perubahan (pencarian dalam riwayat file).

Jesper Rønn-Jensen
sumber

Jawaban:

906

Jika Anda ingin menemukan semua komit di mana pesan komit berisi kata yang diberikan, gunakan

$ git log --grep=word

Jika Anda ingin menemukan semua komit tempat "kata" ditambahkan atau dihapus dalam konten file (lebih tepatnya: di mana jumlah kemunculan "kata" berubah), yaitu mencari konten komit , gunakan pencarian yang disebut pencarian 'beliung' dengan

$ git log -Sword

Di git modern juga ada

$ git log -Gword

untuk mencari perbedaan yang barisnya ditambahkan atau dihapus cocok dengan "kata" (juga komit konten ).

Perhatikan bahwa -Gsecara default menerima regex, sementara -Smenerima string, tetapi dapat dimodifikasi untuk menerima regex menggunakan --pickaxe-regex.

Untuk mengilustrasikan perbedaan antara -S<regex> --pickaxe-regexdan -G<regex>, pertimbangkan komit dengan perbedaan berikut dalam file yang sama:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

Sementara git log -G"regexec\(regexp"akan menunjukkan komit ini, git log -S"regexec\(regexp" --pickaxe-regextidak akan (karena jumlah kemunculan string itu tidak berubah).


Dengan Git 2.25.1 (Februari 2020), dokumentasi diklarifikasi di sekitar regex tersebut.

Lihat komit 9299f84 (06 Feb 2020) oleh Martin Ågren (``) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit 0d11410 , 12 Feb 2020)

diff-options.txt: hindari kelebihan "regex" pada contoh

Dilaporkan oleh: Adam Dinwoodie
Ditandatangani-oleh-oleh: Martin Ågren
Diulas oleh: Taylor Blau

Ketika kami mencontohkan perbedaan antara -Gdan -S(menggunakan --pickaxe-regex), kami melakukannya menggunakan contoh diff dan git diffdoa yang melibatkan "regexec", "regexp", "regmatch", ...

Contohnya benar, tetapi kita dapat membuatnya lebih mudah untuk dilepaskan dengan menghindari penulisan "regex. *" Kecuali jika benar-benar diperlukan untuk menunjukkan maksud kita.

Sebaliknya, gunakan kata-kata yang dibuat-buat, non-regexy.

The git diffDokumentasi sekarang termasuk:

Untuk mengilustrasikan perbedaan antara -S<regex> --pickaxe-regexdan -G<regex>, pertimbangkan komit dengan perbedaan berikut dalam file yang sama:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

Sementara git log -G"frotz\(nitfol"akan menunjukkan komit ini, git log -S"frotz\(nitfol" --pickaxe-regextidak akan (karena jumlah kemunculan string itu tidak berubah).

Jakub Narębski
sumber
3
@TankorSmash -S<string>Cari perbedaan yang memperkenalkan atau menghapus instance <string>. -G<string>Cari perbedaan yang garis tambah atau hapusnya cocok dengan <regex> yang diberikan.
m-ric
1
@ m-ric Oh, begitu, contoh string tunggal, versus seluruh baris! Terima kasih
TankorSmash
3
@ m-ric, @TankorSmash: Perbedaannya adalah -S<string>lebih cepat karena hanya memeriksa apakah jumlah kemunculan <string>diubah, sementara -G<string>pencarian ditambahkan dan dihapus pada setiap komit.
Jakub Narębski
3
Jika Anda perlu mencari kata dengan spasi di antaranya git log --grep="my words",.
MEM
4
@MEM, --grepberbeda dari -Sdan -G. Anda dapat mengutip string untuk setiap argumen ini.
Acumenus
255

git logBeliung akan menemukan komit dengan perubahan termasuk "kata" dengan git log -Sword

u0b34a0f6ae
sumber
60
Ini tidak sepenuhnya tepat. -S <string> Cari perbedaan yang memperkenalkan atau menghapus turunan dari <string>. Perhatikan bahwa ini berbeda dari string yang hanya muncul dalam output diff;
tymtam
4
Meskipun ini pada umumnya jawaban yang tepat, saya menurunkan hanya untuk mendorong orang lain untuk membaca jawaban ini ( stackoverflow.com/a/1340245/586983 ) yang memiliki 3 cara berbeda dan menjelaskan kehalusan mereka.
jakeonrails
18
Astaga! Saya tidak berpikir itu alasan yang bagus untuk menurunkan jawaban yang tepat ... Anda tidak percaya diri termasuk tautan dalam komentar akan cukup memberi dorongan?
Deborah
@ jakeonrails, Jawaban itu seharusnya merupakan edit untuk yang ini (lebih tua), jadi kami tidak memiliki duplikat yang menjengkelkan ini. Tetapi orang-orang hanya menginginkan reputasi, bukan halaman jawaban yang bersih.
Iulian Onofrei
22

Setelah banyak percobaan, saya dapat merekomendasikan yang berikut ini, yang menunjukkan komit yang memperkenalkan atau menghapus baris yang berisi regexp yang diberikan, dan menampilkan perubahan teks di masing-masing, dengan warna yang menunjukkan kata-kata yang ditambahkan dan dihapus.

git log --pickaxe-regex -p --color-words -S "<regexp to search for>"

Butuh beberapa saat untuk menjalankan ... ;-)

CharlesW
sumber
2
Ini adalah salah satu yang terbaik sejauh ini. Petunjuk: hanya daftar semua hasil tanpa paging, baik tambahkan perintah dengan GIT_PAGER=catatau tambahkan| cat
Zack Morris
Tentukan jalur atau file akan jauh lebih cepatgit log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
fangxing
10

Anda dapat mencoba perintah berikut:

git log --patch --color=always | less +/searching_string

atau menggunakan grepcara berikut:

git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'

Jalankan perintah ini di direktori induk tempat Anda ingin mencari.

kenorb
sumber
2
Saya suka metode ini karena komit yang saya lihat memiliki ratusan baris perubahan yang tidak terkait, dan saya hanya tertarik pada tambalan aktual yang melibatkan kata yang saya cari. Untuk mendapatkan penggunaan warna git log --patch --color=always | less +/searching_string.
Radon Rosborough
9

Satu lagi cara / sintaks untuk melakukannya adalah: git log -S "word"
Seperti ini Anda dapat mencari misalnyagit log -S "with whitespaces and stuff @/#ü !"

1u-
sumber
1

buron-vim adalah serbaguna untuk pemeriksaan semacam itu di Vim.

Gunakan :Ggrepuntuk melakukan itu. Untuk informasi lebih lanjut, Anda dapat menginstal pelarian vim dan mencari turorial dengan :help Grep. Dan episode ini: menjelajahi-sejarah-repositori-git akan memandu Anda untuk melakukan semua itu.

Lerner Zhang
sumber
1

Untuk menggunakan konektor boolean pada ekspresi reguler:

git log --grep '[0-9]*\|[a-z]*'

Ekspresi reguler ini mencari ekspresi reguler [0-9] * atau [az] * pada pesan komit.

Reudismam
sumber
-1

Jika Anda ingin mencari data sensitif untuk menghapusnya dari riwayat git Anda (yang merupakan alasan mengapa saya mendarat di sini), ada alat untuk itu. Github sebagai halaman bantuan khusus untuk masalah itu .

Inilah intisari dari artikel tersebut:

The BFG Repo-Cleaner adalah, alternatif yang lebih cepat sederhana untuk git filter-cabang untuk menghapus data yang tidak diinginkan. Misalnya, untuk menghapus file Anda dengan data sensitif dan membiarkan komit terbaru Anda tidak tersentuh), jalankan:

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

Untuk mengganti semua teks yang terdaftar di passwords.txt di mana pun itu dapat ditemukan dalam riwayat repositori Anda, jalankan:

bfg --replace-text passwords.txt

Lihat dokumentasi Repo-Cleaner BFG untuk penggunaan penuh dan instruksi pengunduhan.

edelans
sumber
Anda mungkin ingin menambahkan jawaban ini ke stackoverflow.com/questions/872565/… alih-alih di sini
lacostenycoder