Bagaimana saya dapat memvisualisasikan perbedaan per karakter dalam file diff terpadu?

122

Katakanlah saya mendapatkan tambalan yang dibuat dengan git format-patch. File tersebut pada dasarnya adalah sebuah diff terpadu dengan beberapa metadata. Jika saya membuka file di Vim, saya dapat melihat baris mana yang telah dimodifikasi, tetapi saya tidak dapat melihat karakter mana pada baris yang diubah berbeda. Adakah yang tahu cara (di Vim, atau beberapa perangkat lunak gratis lain yang berjalan di Ubuntu) untuk memvisualisasikan perbedaan per karakter?

Contoh counter dimana perbedaan per karakter divisualisasikan adalah saat mengeksekusi vimdiff a b.

perbarui Jum 12 Nov 22:36:23 UTC 2010

diffpatch berguna untuk skenario saat Anda bekerja dengan satu file.

perbarui Kam 16 Jun 17:56:10 UTC 2016

Lihat diff-highlight di git 2.9 . Skrip ini melakukan persis apa yang awalnya saya cari.

Adam Monsen
sumber
Ini mungkin lebih baik di superuser.com
Daenyth
13
Mungkin. Saya memilih stackoverflow.com karena FAQ menyebutkan ini adalah tempat untuk pertanyaan tentang "alat perangkat lunak yang biasa digunakan oleh pemrogram"
Adam Monsen
7
Saya tidak yakin bahwa ini secara langsung menjawab pertanyaan Anda, tetapi git diff --color-wordssangat berguna untuk melihat kata-kata apa yang berubah dalam baris, daripada keluaran diff terpadu yang biasa. Ini berbasis kata daripada berbasis karakter, jadi jika tidak ada banyak spasi dalam konten yang Anda bedakan maka hasilnya mungkin kurang rapi. (Diedit: Ups, saya melihat bahwa saya salah paham tentang apa yang Anda minta - namun mungkin komentar ini akan berguna bagi seseorang.)
Mark Longair

Jawaban:

13

Mengingat referensi Anda ke Vim dalam pertanyaan tersebut, saya tidak yakin apakah ini jawaban yang Anda inginkan :) tetapi Emacs dapat melakukan ini. Buka file yang berisi diff, pastikan bahwa Anda berada di diff-mode(jika file bernama foo.diffatau foo.patchini terjadi secara otomatis, jika tidak ketik M-x diff-mode RET), pergi ke sebongkah Anda tertarik dan tekan C-c C-buntuk refine-hunk. Atau menelusuri file satu per satu dengan M-n; yang akan melakukan pemurnian secara otomatis.

legoscia
sumber
1
Bekerja untuk saya! Heh, saya sudah menggunakan Vim selama 10 tahun, tapi saya baru saja menginstal emacs. :)
Adam Monsen
Tetapi emacs tidak mendukung membaca dari stdin, saya tidak bisa melakukannya, misalnyagit log master.. -p | emacs -
Hi-Angel
1
@ Hi-Angel Anda dapat membuka Emacs dan mengetik M-!untuk menjalankan perintah dan menangkap keluaran dalam buffer.
legoscia
172

Dalam git, Anda dapat menggabungkan tanpa melakukan. Gabungkan tambalan Anda terlebih dahulu, lalu lakukan:

git diff --word-diff-regex=.

Perhatikan titik setelah tanda sama dengan.

yingted
sumber
139
Lebih baik: git diff --color-words=..
ntc2
4
@ ntc2 Anda harus memberi jawaban pada komentar Anda.
Tyler Collier
1
Para upvoters harap dicatat, kasus penggunaan asli saya mengasumsikan Anda hanya memiliki file patch , tidak ada repo git atau bahkan versi dasar / modifikasi. Itu sebabnya saya menerima jawaban @ legoscia ... itu menjelaskan dengan tepat apa yang diminta.
Adam Monsen
2
@ ntc2 git diff --color-words=.dan git diff --color-words .bekerja secara berbeda. Lebih baik git diff --color-words ..
abhisekp
2
@abhisekp: terima kasih untuk fotonya. Saya pikir saya menemukan jawabannya: git diff --color-words .ini benar-benar sama dengan git diff --color-words -- .! Yaitu, .diartikan sebagai jalan. Anda dapat memverifikasi dengan mkdir x y; echo foo > x/test; git add x/test; git commit -m test; echo boo > x/test; cd y; git diff --color-words=.; git diff --color-words .; git diff --color-words -- ..
ntc2
145

Berikut adalah beberapa versi dengan keluaran yang lebih tidak berisik daripada git diff --word-diff-regex=<re>dan yang memerlukan lebih sedikit pengetikan daripada, tetapi setara dengan git diff --color-words --word-diff-regex=<re>,.

Sederhana (menyoroti perubahan ruang):

git diff --color-words

Sederhana (menyoroti perubahan karakter individu; tidak menyoroti perubahan spasi):

git diff --color-words=.

Lebih kompleks (menyoroti perubahan ruang):

git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'

Secara umum:

git diff --color-words=<re>

dimana <re>regexp mendefinisikan "kata-kata" untuk tujuan mengidentifikasi perubahan.

Ini tidak terlalu berisik karena mereka mewarnai "kata-kata" yang diubah, sedangkan menggunakan --word-diff-regex=<re>"kata-kata" yang cocok untuk mengelilingi dengan -/+penanda berwarna .

ntc2
sumber
9
Saya sendiri suka --color-words, tanpa =.bagian.
Tyler Collier
1
git diff --color-words='\w'akan bekerja lebih baik dengan diakritik (git v1.7.10.4)
nr
1
Versi Anda yang lebih kompleks berfungsi dengan baik. Saya menambahkan --word-diff=plainjuga memiliki [-dan -]mengelilingi penghapusan dan {+dan +}mengelilingi tambahan. Namun, seperti yang diperingatkan oleh manual, kejadian sebenarnya dari pembatas ini dalam sumber tidak luput dengan cara apa pun
Tobias Kienzler
2
Sayangnya, versi Anda yang lebih kompleks tampaknya tidak menyoroti, mis. Perubahan indentasi, saya telah membuka pertanyaan tentang ini
Tobias Kienzler
Jawaban ini bagus! Namun apakah ada cara untuk benar-benar mengubah latar belakang dari perubahan tersebut menjadi hijau / merah?
WoLfPwNeR
45
git diff --color-words="[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+"

Regex di atas ( dari Thomas Rast ) melakukan pekerjaan yang layak untuk memisahkan fragmen diff pada tingkat tanda baca / karakter (meski tidak seribut --word-diff-regex=.).

Saya memposting tangkapan layar dari output yang dihasilkan di sini .


Memperbarui:

Artikel ini memiliki beberapa saran bagus. Secara khusus, contrib/pohon repo git memiliki diff-highlightskrip perl yang menampilkan sorotan halus.

Mulai cepat menggunakannya:

$ curl https://git.kernel.org/cgit/git/git.git/plain/contrib/diff-highlight/diff-highlight > diff-highlight
$ chmod u+x diff-highlight
$ git diff --color=always HEAD~10 | diff-highlight | less -R
Justin M. Keyes
sumber
5
Anda dapat mempersingkatnya menjadi--color-words=[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Eddified
saya harus menambahkan 'ke awal nilai di sana. kalau tidak saya mendapat kesalahan. Juga, saya hanya menggunakan --color-wordssaya mendapatkan perilaku yang sama persis dengan menggunakan regexp itu.
gcb
3
@gcb Konten teks itu penting. Jika perubahan Anda dipisahkan oleh spasi, tidak ada perbedaan. Tapi jika Anda berubah jika Anda mengubah sesuatu seperti foo.baruntuk foo.quxAnda akan melihat perbedaannya.
Justin M. Keyes
5
Sederhana: git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'.
ntc2
1
Saya telah menginstal git dengan Homebrew dan sudah memiliki skrip itu di /usr/local/share/git-core/contrib/diff-highlight/diff-highlight. Ini sepertinya menunjukkan bahwa Homebrew's git menginstal seluruh kontribusinya /usr/local/share/git-core/contrib/. Jadi akhirnya, yang berikut berhasil untuk sayagit diff --color=always | /usr/local/share/git-core/contrib/diff-highlight/diff-highlight
Ashutosh Jindal
6

Jika Anda tidak menentang penginstalan NodeJS, ada paket bernama "diff-so-fancy" ( https://github.com/so-fancy/diff-so-fancy ), yang sangat mudah dipasang dan berfungsi dengan sempurna:

npm install -g diff-so-fancy
git diff --color | diff-so-fancy | less -R

Sunting: Baru tahu itu sebenarnya pembungkus untuk diff-highlight resmi ... Setidaknya lebih mudah untuk menginstal perlophobes seperti saya dan halaman GitHub didokumentasikan dengan baik :)

walnutz.dll
sumber
2

Saya tidak mengetahui alat perbedaan per karakter, tetapi ada alat perbedaan per kata: wdiff.

lihat contoh 4 Alat Perbedaan File Teratas di UNIX / Linux - Diff, Colordiff, Wdiff, Vimdiff .

thegeek
sumber
wdiff menarik, terima kasih! Untuk memperjelas pertanyaan awal saya, saya mencari sesuatu yang menyediakan penyorotan sintaks yang ditingkatkan untuk satu file yang kebetulan dalam format diff terpadu.
Adam Monsen
Sedikit offtopic (tentang kata-demi-kata diffs, tidak meningkatkan keluaran diff yang sudah ada), tapi saya telah menemukan kombinasi berikut terbaik untuk visualisasi kata-demi-kata: * wdiff old_file new_file | cdiff * vimdiff , lalu di dalam vim :windo wincmd Kuntuk beralih ke tata letak jendela vertikal (satu di bawah yang lain) dari sisi ke sisi yang satu. Tata letak itu jauh lebih baik untuk file dengan garis panjang.
Aleksander Adamowski
2
BTW, Beberapa alat senilai lainnya memeriksa, tidak disebutkan dalam artikel terkait: wdiff2, mdiff, dan alat online Google .
Aleksander Adamowski
1

Setelah sedikit riset, saya melihat pertanyaan ini muncul dua kali baru-baru ini di milis utama Vim. The NrrwRgn Plugin disebutkan kedua kali (membuat dua daerah sempit dan diff mereka). Menggunakan NrrwRgn seperti yang dijelaskan oleh Christian Brabandt terasa lebih seperti solusi daripada solusi, tapi mungkin itu cukup bagus.

Saya mencoba NrrwRgn dan itu, bersama dengan: diffthis, memang berguna untuk menggambarkan perbedaan per karakter dalam bagian dari satu file. Tapi butuh banyak penekanan tombol. Vimscript saya cukup berkarat, tetapi kemungkinan besar dapat ditulis. Mungkin NrrwRgn dapat ditingkatkan untuk menyediakan fungsionalitas yang diinginkan.

Pikiran?

Adam Monsen
sumber