Git diff untuk hanya menampilkan garis yang telah dimodifikasi

128

Ketika saya melakukan git diff, itu menunjukkan baris yang telah ditambahkan:

+ this line is added

garis yang telah dihapus:

- this line is removed

tetapi juga menunjukkan banyak baris yang tidak dimodifikasi:

this line is not modified
this line is also not modified

Ini menghasilkan git diff yang sebenarnya terlihat seperti ini:

+ this line is added
  this line is not modified
- this line is removed
  this line is not modified

Bisakah saya meminta git untuk hanya menampilkan baris yang telah dimodifikasi dan mengabaikan semua kode lain yang belum dimodifikasi? Saya telah menulis metode yang akan menghapus semua baris yang tidak memiliki tanda "+" atau "-" di depannya, tetapi saya yakin pasti ada cara yang lebih sederhana untuk melakukan ini.

Di git diff saya, saya hanya tertarik melihat garis-garis yang telah dimodifikasi.

Terima kasih sebelumnya.

r3b00t
sumber

Jawaban:

182

Yang Anda inginkan adalah perbedaan dengan 0 baris konteks. Anda dapat menghasilkan ini dengan:

git diff --unified=0

atau

git diff -U0

Anda juga bisa mengatur ini sebagai opsi konfigurasi untuk repositori itu:

git config diff.context 0

Untuk mengaturnya secara global, untuk repositori apa pun:

 git config --global diff.context 0
Chris Hayes
sumber
4
Terima kasih atas balasan cepat. Ini menyelesaikan setengah dari masalah saya, tetapi saya masih mendapatkan beberapa baris seperti "@@ -1 +1 @@" di diff saya dan di atas git diff saya ada "diff - git a / db / xxxxxxx b / db / xxxx index xxxxx..aaaaaaa bbbbbbbbb
r3b00t
3
Saya tidak berpikir git menyediakan cara untuk menghindari mengeluarkan garis-garis itu, karena diff tidak akan masuk akal tanpa mereka (Anda tidak bisa tahu file mana yang Anda lihat, atau di mana Anda berada dalam file).
Chris Hayes
8
@Rakesh: Untuk memperluas, git-diff mencoba membuat diff yang sebenarnya dapat digunakan sebagai tambalan ke file sumber, yang tidak mungkin dilakukan tanpa informasi itu. Satu-satunya cara untuk menghapusnya adalah dengan mempostingnya sendiri, seperti via git diff | egrep "^(\+|-) ".
Chris Hayes
1
git config --global diff.context 0 untuk mengaturnya secara global
Andrzej Rehmann
Jika Anda ingin melihat di direktori tertentu, coba git diff -U0 <dir>
Eswar Yaganti
41

Peretasan lain (pada un * x) untuk hanya menampilkan baris yang dimulai dengan +dan -:

git diff -U0 | grep '^[+-]' | grep -Ev '^(--- a/|\+\+\+ b/)'

Kode di atas melakukan hal berikut:

  • git diff -U0: pilih 0 baris konteks
  • Grep pertama hanya mencakup semua baris yang dimulai dengan +atau-
  • Grep kedua mengecualikan garis yang dimulai dengan --- a/atau+++ b/

Warna

Untuk menampilkan perbedaan warna, coba yang berikut ini:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • Ekspresi,, ^\e\[[^m]*m[-+]mencari awal baris ( ^), kemudian pelacak melarikan diri ( \e) diikuti dengan [yang bersama-sama memulai urutan pelarian, lalu setiap karakter yang bukan "m" (angka, titik koma, atau tidak sama sekali), diikuti oleh " m "yang mengakhiri urutan pelarian.
  • Perhatikan bahwa semua berikut ini adalah urutan keluar yang valid: \e[0m(reset), \e[m(juga reset), \e[1m(tebal), \e[31m(merah), \e[32m(hijau), \e[9;31m(mogok + merah), \e[31;9m(merah + mogok), \e[1;4;9;31m(tebal + garis bawahi + mogok + merah). Warna default git menggunakan merah dan hijau, tetapi mereka dapat dikonfigurasi ulang.
  • --colorsama dengan --color=always.
  • Pembatasan pada --- a/atau +++ b/untuk muncul di awal garis telah dihapus untuk mengakomodasi urutan pelarian dan ini dapat mengarah pada kasus tepi.

Catatan tambahan:

  • Solusi di atas perlu diubah jika Anda menggunakan opsi-opsi git diff seperti -R, --src-prefix, --dst-prefix, --no-prefix, dll
  • Kedua greps dapat digabungkan menjadi satu grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )', tetapi saya menemukan versi grep ganda lebih mudah dimengerti.
pengguna650654
sumber
2
Bagus Suara positif untuk penjelasan yang jelas pada setiap filter.
henrebotha
Saya melihat banyak git diffbaris jenis "header" yang dimulai dengan @@, tetapi apa git diffbaris yang dimulai dengan ---atau +++? Saya tidak menyadarinya.
Gabriel Staples
Ah, tidak apa-apa. Itu menunjukkan nama file untuk file yang berisi penambahan ( +++) atau penghapusan ( ---). Saya melihatnya di sini sekarang: git-scm.com/docs/git-diff#_combined_diff_format .
Gabriel Staples
Koreksi lagi: --- a/filenametampaknya menunjukkan "file di sebelah kiri", atau file seperti sebelumnya, dan +++ b/filenametampaknya menunjukkan "file di sebelah kanan", atau file seperti sekarang dengan perubahan Anda. Saya sangat terbiasa menggunakan git difftooldengan berbaur , yang menunjukkan perbandingan berdampingan yang indah, sehingga saya tidak pernah benar-benar terbiasa melihat git diff, jadi itu masih terlihat aneh bagi saya, dan saya tidak pernah benar-benar melihat nuansa ini sebelumnya.
Gabriel Staples
1
@GabrielStaples, dukungan untuk warna telah ditambahkan. Terima kasih.
user650654
6

Menindaklanjuti komentar terbaru Chris, masalah utama dengan post-processing adalah Anda ingin tetap menggunakan jalur -|+tetapi Anda juga ingin menyaring yang memulai ---|+++. Jika Anda menyimpan file tambalan di repo Anda (saya lakukan, di Pydoop ), di sisi lain, Anda ingin menjaga garis yang dimulai dengan --|++, sehingga regexp menjadi sedikit terlibat:

git diff | grep -P '^\+(?:(?!\+\+))|^-(?:(?!--))'

Regexp menggunakan lookahead negatif: lihat jawaban Peter Boughton untuk pertanyaan ini untuk penjelasan terperinci.

Jika Anda sering melakukan ini, Anda mungkin ingin mengatur alias git untuk itu:

git config --global alias.diffonly '!git diff | grep -P "^\+(?:(?!\+\+))|^-(?:(?!--))"'
simleo
sumber
1
ini tidak bekerja untuk saya di Windows git bash. Tidak tahu mengapa (grep mengatakan opsi P tidak valid), tidak memiliki chutzpa untuk melihatnya saat ini.
Dennis
1
-Patau --perl-regexpdigunakan untuk menafsirkan pola sebagai rexpression reguler Perl, tetapi tidak selalu dilaksanakan. Itu tidak bekerja untuk saya di OSX. gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega
5

Saya pikir untuk kasus sederhana regex bisa menjadi jauh lebih pendek dan lebih mudah diingat, dengan peringatan bahwa ini tidak akan berfungsi jika Anda memiliki perubahan garis di mana garis itu sendiri dimulai dengan +atau-

$ git diff | grep '^[+|-][^+|-]'

Regex mengatakan bahwa garis harus dimulai dengan +atau -, dan karakter yang mengikuti segera seharusnya bukan keduanya. Saya mendapat hasil yang sama apakah saya lolos +atau tidak di sini, btw ...


Contoh:

$ cat testfile
A
B
C
D
E
F
G

Katakan saya mengubah Cke X, Eke Y, dan Gke Z.

$ git diff | grep '^[+|-][^+|-]'
-C
+X
-E
+Y
-G
+Z

Seperti yang saya katakan di atas, ini hanya untuk sebagian besar kasus. Jika Anda mem-pipe output itu ke file dout, lalu coba regex yang sama, itu tidak akan berfungsi.

$ git diff dout | grep '^[+|-][^+|-]'
$

Bagaimanapun, harapan yang membantu dalam kasus Anda

galois
sumber
Untuk kasus di mana garis dimulai dengan "-" itu tidak akan berfungsi. Contoh: - name: No pdbdalam file yaml.
anapaulagomes
3

Jawaban ini akan mempertahankan warna merah / hijau asli agar mudah dibaca. Saya memberikan beberapa variasi dalam sintaks:

git diff --color | grep --color=never $'^\e\[3[12]m'
git diff --color | grep --color=never $'^\033\[3[12]m'
git diff --color | grep --color=never -P '^\e\[3[12]m'
git diff --color | grep --color=never -P '^\033\[3[12]m'

Penjelasan:

  • Ini git diff --colordiperlukan untuk mencegah git menonaktifkan warna ketika sedang dipipihkan.
  • Ini grep --color=neveruntuk mencegah grep menghapus warna asli dan menyorot string yang cocok.
  • Kami mencocokkan untuk garis yang dimulai dengan kode escape merah ( \e[31m) atau hijau ( \e[32m).
  • The $'...'(ANSI-C mengutip sintaks) atau -P(sintaks perl) adalah membiarkan grepuntuk menafsirkan \eatau \033sebagai ESCkarakter.
wisbucky
sumber
Terima kasih untuk ini. Inilah bentuk alternatif yang baru saja saya buat. $''Bagian Anda terutama membantu saya. stackoverflow.com/a/61929887/4561887
Gabriel Staples
1

Cara menggunakan awkuntuk menampilkan hanya garis +dan -, akuntansi untuk setiap warna atau format teks git diffmungkin menghasilkan:

Tidak satu pun dari jawaban lain di sini (termasuk jawaban saya yang lain ) akan melakukan apa yang Anda inginkan 100% dengan benar. Namun, jawaban ini akan. Ini adalah 1-liner yang dapat Anda salin dan tempel ke terminal Anda. Saya baru saja membuatnya beberapa baris agar mudah dibaca - Anda dapat menyalin-menempelnya dengan cara yang sama sehingga saya mungkin membuatnya dapat dibaca! Itu bergantung pada awkbahasa pemrograman:

git diff --color=always "$@" | awk '
# 1. Match and then skip "--- a/" and "+++ b/" lines
/^(\033\[(([0-9]{1,2};?){1,10})m)?(--- a\/|\+\+\+ b\/)/ {
    next 
} 
# 2. Now print the remaining "+" and "-" lines ONLY! Note: doing step 1 above first was required or
# else those lines would have been matched by this matcher below too since they also begin with 
# the "+" and "-" symbols.
/^(\033\[(([0-9]{1,2};?){1,10})m)?[-+]/ {
    print $0 
}
' | less -RFX

Berikut fitur-fiturnya. Semua fitur ini, ketika diambil bersama-sama, menyelesaikan kekurangan dari setiap jawaban lainnya di sini:

  1. Ini menangani warna DAN output tanpa warna. Itulah yang dilakukan ekspresi reguler ini:^(\033\[(([0-9]{1,2};?){1,10})m)?
  2. Ini menangani SEMUA WARNA dan SEMUA PILIHAN PEMBENTUKAN TEKS, termasuk cetak tebal, miring, dicoret, dll, yang dapat Anda atur dalam git configpengaturan Anda . Itu sebabnya regex di atas memiliki ;?dan {1,10}di dalamnya: jika ia mendeteksi awal kode pemformatan warna atau teks, itu akan cocok dengan 10 urutan kode ANSI gabungan ini.
  3. Ini TIDAK juga termasuk baris yang dimulai dengan @@dan kata diff, seperti jawaban yang diterima . Jika Anda ingin garis-garis itu (yang terus terang, saya pikir berguna :)), lakukan ini sebagai gantinya:

    git diff --unified=0
    

    atau

    git diff -U0
    
  4. Ini menunjukkan output dengan cara yang sama persis seperti yang git diffakan: dalam lesspager dengan output warna opsional ( -R), dan hanya jika teksnya> 1 halaman ( -F), dan sambil mempertahankan halaman teks saat ini di layar ketika Anda quit ( -X) .

Ini juga memiliki manfaat menjadi kuat dan mudah dikonfigurasi karena menggunakan bahasa pemrograman awk.

Jika Anda tertarik mempelajari awk , berikut ini beberapa sumber:

  1. gawkawkManual (GNU ): https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. Pelajari git diffndan komentar di dalamnya: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    1. Jika Anda menginginkannya git diffn, yaitu git diffdengan nomor baris, lihat di sini: Git beda dengan nomor baris (Catatan log dengan nomor baris)
  3. Beberapa contoh "hello world" dan contoh uji sintaks: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

Sebagai bonus, saya juga membungkus di atas untuk digunakan sebagai git diffc, yang berarti "git diff untuk menunjukkan HANYA 'c'hanges". Penggunaannya identik dengan git diff; gunakan git diffcsaja! Ini mendukung opsi SEMUA. Warna AKTIF secara default. Untuk mematikannya, cukup gunakan git diffc --no-coloratau git diffc --color=never. Lihat man git diffdetailnya.

Karena saya baru saja selesai git diffn(alat untuk menunjukkan git diffdengan garis 'n'umber) tadi malam, menulis git diffcitu sepele. Saya pikir saya lebih baik melakukannya sekarang sementara pengetahuan masih segar di kepala saya.

Pasang git diffc:

Ikuti instruksi di akhir jawaban ini di sini , kecuali di mana pun Anda melihat git-diffndalam instruksi, gunakan git-diffcsaja. Itu termasuk dalam wgetperintah juga. Mengunduh dan menginstalnya git diffcmudah: itu hanya beberapa perintah.

Gabriel Staples
sumber
0

Inilah cara lain yang lebih sederhana untuk menemukan hanya garis yang telah dimodifikasi, dan karenanya mulai dengan satu +atau -, sambil mempertahankan keluaran warna:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. Kata -U0mengatakan untuk memasukkan 0 baris konteks di sekitar baris yang diubah - yaitu: hanya memasukkan baris yang diubah sendiri. Lihat man git diff.
  2. The -Euntuk grep memungkinkan untuk bekerja dengan ekspresi reguler diperpanjang
  3. The $''sintaks tampaknya memungkinkan ANSI mengutip, yang benar menafsirkan ESC (escape, atau 0x1b) karakter dengan benar. Lihat di sini .
  4. Dan inilah deskripsi regex dari https://www.regex101.com :masukkan deskripsi gambar di sini
  5. Pada dasarnya, ^cocok dengan awal baris, \ecocok dengan karakter Escape, yang merupakan awal dari kode warna di terminal, \[cocok dengan karakter berikutnya dalam kode warna, yaitu [, dan kemudian (this|that)sintaksinya cocok dengan "ini" atau "itu" , di mana "ini" adalah 32m+, yang merupakan garis + hijau, dan 31m-merupakan garis merah.
  6. Warna seperti ini: \e[32mhijau dan \e[31mmerah.
  7. +menunjukkan garis yang ditandai dengan git diffditambahkan, tentu saja, dan -menunjukkan garis yang ditandai git diffsebagai dihapus.
  8. Perhatikan bahwa --color=neveryang diperlukan dalam 2 grepekspresi untuk mencegah dari menyoroti pertandingan, yang dinyatakan akan mengacaukan kode warna yang datang dari git diffsebelah kiri.
  9. Itu +harus diloloskan juga karena \+karena kalau tidak, itu +adalah ekspresi reguler khusus (regex) karakter yang menentukan satu atau lebih kejadian elemen sebelumnya . Lihat di sini: https://en.wikipedia.org/wiki/Regular_expression#Basic_concepts .

Referensi:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. Jawaban oleh @ user650654: Git diff untuk hanya menampilkan baris yang telah dimodifikasi
  3. Jawaban oleh @wisbucky: Git diff hanya menampilkan baris yang telah dimodifikasi

Terkait:

  1. [jawabanku sendiri] Git diff dengan nomor baris (Git log dengan nomor baris)
  2. [jawaban orang lain] Git beda dengan nomor baris (Git log dengan nomor baris)
  3. git beda dengan nomor baris dan pelurusan / lekukan kode yang tepat
  4. git-filechange-search.sh- skrip yang memungkinkan Anda untuk mencari file untuk variabel atau nama fungsi dan mencari tahu yang melakukan berisi perubahan dengan variabel atau nama fungsi tersebut. Ex. penggunaan: ./git-filechange-search.sh path/to/my/file.cpp variable_nameakan menemukan semua komit dengan perubahan pada file.cpp yang berisi variable_namedi dalamnya. Ini berguna untuk melihat di mana dan kapan fitur-fitur tertentu diubah. Seolah-olah itu adalah pencarian yang dapat mengamati bagian dari file yang ditampilkan melalui git blamewaktu ke waktu.
Gabriel Staples
sumber