Memahami Keluaran Git Diff secara Menyeluruh

Setelah git commit, git pull dan git push, git diff adalah perintah Git yang (mungkin) paling sering saya gunakan. Eksekusi git diff sebelum melakukan git commit menjadi rutinitas yang selalu saya lakukan, untuk memastikan tidak ada kesalahan penulisan sebelum saya mencatatkan perubahan saya di sebuah commit.

Perintah git diff memberitahu kita secara mendetail apa saja perubahan yang terjadi di antara dua titik referensi Git. Secara default, ketika kita menjalankan git diff tanpa argumen apa-apa, Git akan mencetak perubahan yang terjadi antara working tree dan HEAD. Informasi yang dicetak oleh Git tersebut sebenarnya sangat informatif, namun kadang kita melewatkannya karena kita hanya memedulikan data penambahan dan pengurangan pada kode kita. Mari kita telaah, apa saja informasi yang bisa kita dapatkan dari git diff.

Pada kasus di bawah, saya me-rename puisi/aku-chairil-anwar.md menjadi puisi/aku-chairil-anwar-new.md dan melakukan beberapa perubahan. Untuk lebih jelasnya, saya cantumkan juga perintah yang saya jalankan dari kondisi clean working tree.

mv puisi/aku-chairil-anwar.md puisi/aku-chairil-anwar-new.md
vim puisi/aku-chairil-anwar-new.md
sudo chmod +x puisi/aku-chairil-anwar-new.md
git add .
git diff --staged
diff --git a/puisi/aku-chairil-anwar.md b/puisi/aku-chairil-anwar-new.md
old mode 100644
new mode 100755
similarity index 86%
rename from puisi/aku-chairil-anwar.md
rename to puisi/aku-chairil-anwar-new.md
index fdcc0f3..1bcc061
--- a/puisi/aku-chairil-anwar.md
+++ b/puisi/aku-chairil-anwar-new.md
@@ -1,9 +1,10 @@
 # Aku
 ## oleh Chairil Anwar
+---

 Kalau sampai waktuku
 Ku mau tak seorang kan merayu
-Tidak juga kau
+Tidak juga kau!

 Tak perlu sedu sedan itu

@@ -20,3 +21,7 @@ Hingga hilang pedih peri

 Dan aku akan lebih tidak peduli
 Ku mau hidup seribu tahun lagi
+
+---
+Diperbarui pada 21 Juli 2017
+

Mari kita bedah bagian per bagian. Mulai dari baris pertama, yang disebut diff header, terdapat:

diff --git a/puisi/aku-chairil-anwar.md b/puisi/aku-chairil-anwar-new.md
old mode 100644
new mode 100755

Baris ini mengindikasikan awal dari perbandingan sebuah berkas antar referensi Git, sekaligus mengidentifikasi dua berkas yang perbandingannya akan dijabarkan kemudian. Penamaan a/ dan b/ di depan nama berkas yang dibandingkan mengacu pada posisi referensi yang kita oper ke git diff.

Dalam kasus ini, karena git diff kita panggil tanpa argumen referensi sama sekali, yang terjadi adalah HEAD berada di posisi a/, sedangkan working tree berada di posisi b/. Misalkan kita memanggil git diff dengan argumen referensi, seperti git diff HEAD~ HEAD, maka HEAD~ akan menempati posisi a/ sedangkan HEAD akan menempati posisi b/.

Baris old mode dan new mode mengindikasikan perubahan mode berkas (permissions) yang direpresentasikan dengan bilangan oktal seperti pada sistem Unix. 10644 berarti berkas biasa, sedangkan 100755 berarti berkas yang dapat dieksekusi.

Kemudian, di baris selanjutnya, kita melihat:

similarity index 86%
rename from puisi/aku-chairil-anwar.md
rename to puisi/aku-chairil-anwar-new.md

Bagian yang disebut extended header ini hanya muncul pada kasus berkas yang di-rename. Baris similarity index mengindikasikan proporsi kesamaan antara kedua state berkas yang kita bandingkan. Kita mendapatkan angka 86%, artinya berkas kita berubah 14% antara dua referensi yang kita bandingkan.

Dua baris selanjutnya cukup jelas, rename from mengindikasikan nama berkas sebelumnya, sementara rename to mengindikasikan nama berkas yang baru.

Baris selanjutnya, yang masih termasuk extended header berbunyi:

index fdcc0f3..1bcc061

Baris ini berisi hash yang menandai versi berkas sebelum dan sesudah, yang disebut dengan preimage dan postimage hash. Mirip dengan commit hash yang digunakan untuk mengidentifikasi commit, namun hash ini berguna untuk mengidentifikasi objek individual dalam Git, yang dalam hal ini adalah sebuah berkas.

Berlanjut ke bagian selanjutnya, yang berbunyi:

--- a/puisi/aku-chairil-anwar.md
+++ b/puisi/aku-chairil-anwar-new.md

Ini bagian yang sering disalahartikan. Banyak yang menganggap tanda --- menunjukkan bagian yang dihapus, sementara tanda +++ menunjukkan bagian yang ditambahkan. Hampir benar, namun definisi sebenarnya dari dua baris tersebut adalah untuk memberikan indikator keadaan kode pada masing-masing versi berkas. Dalam kasus ini, simbol --- digunakan sebagai indikator keadaan kode pada a/puisi/aku-chairil-anwar.md, sementara +++ mengindikasikan keadaan kode pada b/puisi/aku-chairil-anwar-new.md berdasarkan urutan referensi yang kita oper ke perintah git diff.

Kenapa saya bilang kurang tepat jika kedua tanda itu diinterpretasikan sebagai 'pengurangan' dan 'penambahan'? Karena jika kita membalik urutan referensi yang kita oper ke git diff, kedua indikator tersebut pun menjadi terbalik. Bayangkan, ketika kita membuat suatu commit yang menambahkan beberapa baris kode, kemudian kita lakukan git diff antara HEAD dengan HEAD~, baris yang kita tambahkan sebelumnya akan berlabel -. Tidak masuk akal jika kita menyebutnya penghapusan alih-alih perbedaan antara dua versi, bukan?

Bagian selanjutnya disebut sebagai hunk, yaitu penjabaran perbedaan antar versi berkas. Hunk terdiri atas baris yang disebut sebagai hunk header, yang menjelaskan lokasi beserta panjang potongan kode yang akan diperlihatkan, diikuti dengan chunk, yaitu potongan kode beserta penjabaran perbedaannya. Berikut adalah hunk header yang akan kita bedah:

@@ -1,9 +1,10 @@

Terdapat angka-angka di dalamnya yang dapat kita bagi dua, pertama -1,9, kedua +1,10. Seperti yang sudah kita ketahui tadi, simbol - dan + adalah referensi ke versi berkas yang diperbedakan. Angka -1,9 berarti chunk yang akan diperlihatkan dimulai dari baris ke-1 sebanyak 9 baris pada keadaan berkas yang direferensikan oleh simbol - (a/puisi/aku-chairil-anwar.md).

Sementara itu, +1,10 mengindikasikan bahwa chunk yang sama berada pada baris ke-1 sebanyak 10 baris pada keadaan berkas yang direpresentasikan oleh simbol + (b/puisi/aku-chairil-anwar-new.md). Hal ini berarti terdapat perbedaan satu baris kode pada chunk tersebut.

Lanjut ke chunk-nya itu sendiri:

 # Aku
 ## oleh Chairil Anwar
+---

 Kalau sampai waktuku
 Ku mau tak seorang kan merayu
-Tidak juga kau
+Tidak juga kau!

 Tak perlu sedu sedan itu

Di sini kita bisa melihat langsung perbedaan antara kedua versi berkas kita. Perbedaan kode di sini ditunjukkan dengan simbol - dan +. Sekali lagi, camkanlah bahwa kedua simbol itu merepresentasikan dua versi berbeda dari berkas kita, bukan penghapusan dan penambahan. Dapat dilihat pada chunk ini saya terdapat --- pada baris ketiga dan Tidak juga kau! pada baris ketujuh berkas b/puisi/aku-chairil-anwar-new.md, sementara pada a/puisi/aku-chairil-anwar.md yang ada di baris ketujuh adalah Tidak juga kau.

Selanjutnya adalah deskripsi hunk yang memiliki perbedaan, yang cara bacanya tidak berbeda dari hunk yang barusan kita baca.


Kurang lebih seperti itulah cara membaca keluaran git diff yang baik dan benar. Banyak informasi yang bisa digali dari perintah tersebut, namun sayangnya dokumentasi lengkapnya bisa dibilang nyaris nihil. Semoga Anda merasakan ketertarikan yang sama dengan saya terhadap informasi ini!