Dua sistem operasi tidak sepakat soal cara mengakhiri satu baris teks: Windows memakai dua karakter (carriage return dan line feed, CRLF), sedangkan Linux dan macOS memakai satu (line feed, LF). Perbedaan ini tidak terlihat di editor biasa, tetapi terlihat jelas oleh Git: bagi Git, kedua versi berkas adalah isi yang berbeda, sehingga satu berkas yang diedit lintas sistem operasi bisa muncul sebagai perubahan di seluruh barisnya. Chapter Instalasi Git di WSL
sudah memperlihatkan gejala ini; sekarang kita atur obatnya — kunci core.autocrlf untuk konversi otomatis per mesin, dan berkas .gitattributes untuk aturan yang berlaku bagi seluruh anggota tim.
Melihat Masalahnya Secara Nyata #
Kita buat berkas berakhiran CRLF lalu mengamatinya dengan cat -A, yang menandai akhir baris sebagai $ dan carriage return sebagai ^M:
cd demo-ch11
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'baris pertama\r\nbaris kedua\r\n' > berkas-crlf.txt
cat -A berkas-crlf.txtOutput yang Dihasilkan:
baris pertama^M$
baris kedua^M$Tanda ^M$ di akhir tiap baris berarti carriage return dan line feed hadir bersamaan. Tanpa pengaturan apa pun, Git menyimpan berkas apa adanya — kita buktikan dengan memasukkannya ke staging area lalu membaca status akhir barisnya:
git add berkas-crlf.txt
git ls-files --eolOutput yang Dihasilkan:
i/crlf w/crlf attr/ berkas-crlf.txtTiga kolom pada keluaran tersebut adalah kunci pembacaannya: i/ menggambarkan isi yang tersimpan di repository (index), w/ menggambarkan isi berkas di direktori kerja (working copy), dan attr/ menampilkan aturan .gitattributes yang berlaku. Keluaran i/crlf menegaskan bahwa Git akan menyimpan CRLF mentah-mentah ke dalam repository — rekan tim yang memakai Linux kemudian menerima berkas penuh carriage return, dan diff antar sistem operasi menjadi penuh derau.
core.autocrlf: Tiga Mode #
Kunci core.autocrlf menginstruksikan Git mengonversi akhir baris secara otomatis pada dua titik: saat berkas masuk repository dan saat berkas keluar repository. Tiga nilainya memberi kombinasi berbeda:
| Nilai | Saat masuk repository | Saat keluar repository | Cocok untuk |
|---|---|---|---|
false | tanpa konversi | tanpa konversi | Linux/macOS; atau tim yang sudah memakai .gitattributes |
input | CRLF menjadi LF | tanpa konversi | Linux/macOS yang sering menerima berkas hasil editor Windows |
true | CRLF menjadi LF | LF menjadi CRLF | Windows tanpa .gitattributes |
Kita uji mode input pada repository sandbox. Nilainya cukup diatur level local agar demo tidak menyentuh konfigurasi akun:
git config core.autocrlf input
git rm --cached berkas-crlf.txt
git add berkas-crlf.txtOutput yang Dihasilkan:
rm 'berkas-crlf.txt'
warning: in the working copy of 'berkas-crlf.txt', CRLF will be replaced by LF the next time Git touches itBaris rm mengeluarkan berkas lama dari staging area — caranya memastikan berkas di-add ulang, karena Git membiarkan berkas yang statusnya tak berubah. Baris warning bukan galat: Git sekadar mengingatkan bahwa berkas di direktori kerja masih CRLF, dan versi LF akan menimpanya saat Git menulis ulang berkas itu. Sekarang kita baca ulang status akhir barisnya:
git ls-files --eolOutput yang Dihasilkan:
i/lf w/crlf attr/ berkas-crlf.txtKolom i/ berubah menjadi lf — isi yang tersimpan di repository kini LF, sementara berkas di direktori kerja tetap CRLF. Isi repository itu bisa kita lihat langsung dari blob yang tersimpan:
git cat-file -p :berkas-crlf.txt | cat -AOutput yang Dihasilkan:
baris pertama$
baris kedua$Hanya $ yang tersisa — carriage return tidak pernah sampai ke repository. Mode true melengkapi lingkarannya di sisi Windows: berkas keluar sebagai CRLF saat checkout, masuk kembali sebagai LF saat commit. Kita bisa membuktikan putaran itu di sandbox: simpan kondisi bersih ini sebagai commit, hapus berkas dari direktori kerja, lalu ambil kembali dengan core.autocrlf true:
git config core.autocrlf true
git commit -m "Simpan berkas dengan LF di repository"
rm berkas-crlf.txt
git checkout -- berkas-crlf.txt
cat -A berkas-crlf.txtOutput yang Dihasilkan:
baris pertama^M$
baris kedua^M$Repository menyimpan LF, mesin berkerja dalam CRLF — tidak ada satu pun byte yang berubah di repository karena perpindahan sistem operasi.
.gitattributes: Solusi Lintas Platform #
core.autocrlf hidup di konfigurasi tiap mesin, dan itulah kelemahannya: perilaku repository menjadi bergantung pada pengaturan komputer masing-masing anggota tim. Berkas .gitattributes menempatkan aturan di dalam repository itu sendiri — ikut di-commit, ikut di-clone, berlaku sama bagi semua orang. Untuk akhir baris, satu baris aturan sudah cukup:
echo '* text=auto' > .gitattributesAturan * text=auto berarti: semua berkas yang Git anggap teks akan dinormalkan ke LF di repository, apa pun pengaturan core.autocrlf di mesin pembuka. Kejujuran teknisnya: pendekatan ini lebih deterministik daripada core.autocrlf, karena hasilnya tidak lagi tergantung pada konfigurasi mesin. Kita buktikan dengan meniadakan konfigurasi autocrlf sepenuhnya:
git config core.autocrlf false
printf 'baris pertama\r\nbaris kedua\r\n' > berkas-crlf.txt
git add .gitattributes
git rm --cached berkas-crlf.txt
git add berkas-crlf.txt
git ls-files --eolOutput yang Dihasilkan:
i/lf w/lf attr/text=auto .gitattributes
i/lf w/crlf attr/text=auto berkas-crlf.txtDua hal terbaca dari keluaran tersebut. Kolom attr/ kini terisi text=auto — bukti aturan aktif dan berlaku pada kedua berkas. Dan meski core.autocrlf sudah false, berkas CRLF tetap tersimpan sebagai i/lf — konversi terjadi karena aturan .gitattributes, bukan karena pengaturan mesin.
Rekomendasi lengkap ketiga pendekatan ini, termasuk alasan Git for Windows menyarankan core.autocrlf true pada penginstalnya, tersedia di Pro Git: Git Configuration
. Dengan akhir baris aman, pengaturan teknis kita sudah layak pakai — tinggal satu polesan terakhir untuk kenyamanan harian: pintasan perintah lewat alias, chapter berikutnya.