- Tim Gradle sempat ingin mengadopsi Jujutsu (jj), VCS yang kompatibel dengan Git, untuk pengembangan sehari-hari, tetapi menunda adopsinya karena penanganan line ending pada
gradlew.bat di Windows
- Masalah intinya adalah
jj tidak bisa membaca aturan EOL per file di .gitattributes, sehingga tidak dapat menerapkan *.bat text eol=crlf
- Git menormalkan
gradlew.bat sebagai LF di repositori dan melakukan checkout sebagai CRLF di working directory, tetapi jj menganggap ini sebagai perubahan dan terus membuat phantom modification
- Mem-commit
gradlew.bat apa adanya dalam CRLF dan mengubahnya menjadi *.bat -text bisa menjadi jalan memutar, tetapi jika editor mengubahnya ke LF, Git tidak lagi memulihkannya secara otomatis sehingga keandalan eksekusi di Windows bisa terganggu
- Untuk sementara, tim Gradle akan tetap mengelola beberapa working directory dengan
git worktree, lalu mencoba lagi saat dukungan eol di jj sudah diimplementasikan
Penyebab sebenarnya yang menghalangi adopsi: gradlew.bat dan .gitattributes
- Jujutsu (
jj) adalah sistem kontrol versi yang kompatibel dengan Git yang, saat memakai backend Git, menyimpan commit dan file ke Git serta dapat bekerja berdampingan dengan repositori Git yang sudah ada
jj menghilangkan staging area dan merepresentasikan working copy sebagai commit nyata yang terus diperbarui
- Setelah pengeditan atau penyusunan ulang commit, commit lanjutan otomatis di-rebase, konflik bisa disimpan dalam riwayat alih-alih menghentikan pekerjaan, dan perubahan juga bisa dibatalkan dari operation log
- Upaya engineer Gradle untuk mengganti
git dengan jj terhambat bukan oleh model jj, melainkan oleh detail kecil tentang bagaimana proyek Gradle ditempatkan di disk
gradlew.bat membutuhkan CRLF di Windows
- Repositori Gradle pada umumnya menyertakan
gradlew.bat bersama Gradle Wrapper
gradlew.bat memakai label dan goto, dan cmd.exe bisa salah menangani batch file yang hanya memakai line ending LF
- Agar berjalan stabil di Windows,
gradlew.bat harus di-checkout sebagai CRLF
- Proyek Gradle memaksakan kebutuhan ini melalui
.gitattributes
*.bat text eol=crlf
- Di Git, perilaku ini adalah alur standar
- File disimpan dalam bentuk yang sudah dinormalisasi di index
- Atribut
eol=crlf mewujudkan CRLF ke working copy saat checkout
- Hasil edit kembali dinormalisasi saat disimpan lagi
Dukungan .gitattributes yang belum ada di jj memunculkan phantom diff
jj tidak membaca .gitattributes, sehingga tidak bisa menerapkan aturan line ending per file
- Fitur terkait sedang dilacak di isu lama jj-vcs/jj#53, dan setidaknya dukungan untuk atribut
eol sedang dibahas
- Saat ini, satu-satunya mekanisme yang bisa dipakai di
jj adalah konfigurasi global working-copy.eol-conversion
- Mirip
core.autocrlf di Git, tetapi diterapkan ke semua file sekaligus
- Tidak bisa menetapkan hanya untuk file
.bat
- Pada colocated repo, masalahnya langsung terlihat
- Git menyimpan
gradlew.bat sebagai LF dan melakukan checkout sebagai CRLF
- Karena
jj tidak menghormati atribut tersebut, CRLF di disk dicatat sebagai perubahan dibanding blob LF di Git
- Pada proyek Gradle yang terdampak, ini menimbulkan perubahan palsu yang terus-menerus pada
gradlew.bat
- Masalah ini bukan hanya terjadi pada tim Gradle
- Seorang pengguna melaporkan phantom change pada ratusan ribu file dan akhirnya berhenti memakai
jj
Jalan memutar yang diusulkan dan batasannya
- Penulis
jj mengusulkan non-colocated workspace sebagai salah satu pendekatan di isu tersebut
- Contoh: memakai
jj git init --git-repo=<path> dari luar working copy Git
- Engineer Gradle menilai cara ini juga tidak menyelesaikan masalah
- Saat
jj mewujudkan gradlew.bat dari blob LF yang tersimpan, file itu akan turun ke disk sebagai LF
gradlew.bat dengan LF tidak bisa dijalankan di Windows
- Konfigurasi global
working-copy.eol-conversion = input-output memang bisa memaksa CRLF
- Tetapi ini juga akan menulis ulang semua file teks menjadi CRLF saat checkout, sehingga memunculkan masalah lain
Solusi yang bekerja, tetapi rapuh
- Cara yang benar-benar bekerja adalah mem-commit
gradlew.bat ke repositori apa adanya dalam CRLF dan menghentikan normalisasi
- Aturannya berubah seperti ini
- Sebelumnya:
*.bat text eol=crlf
- Menjadi:
*.bat -text
- Dengan begitu, Git dan
jj sama-sama sepakat memakai CRLF baik di stored tree maupun working copy
- Tidak ada lagi konversi
- Phantom diff pun hilang
- Eksekusi di Windows tetap terjaga
- Namun
*.bat -text berarti melepaskan pemulihan otomatis yang sebelumnya diberikan oleh text eol=crlf
- Sebelumnya, jika LF masuk karena kesalahan, Git akan diam-diam menormalkannya lagi saat commit
- Sekarang, LF akan tetap ada dan
gradlew.bat bisa rusak diam-diam di Windows
- Konversi ini hanya perlu dilakukan sekali, dan edit yang keliru biasanya bisa tertangkap saat review
- Meski begitu, tim Gradle menilai terlalu berisiko menggantungkan ekosistem pada asumsi bahwa semua proyek Gradle akan mem-commit CRLF secara langsung dan tidak ada editor yang diam-diam mengubahnya
Alternatif yang dipertahankan untuk sementara: git worktree
- Workspace di
jj menyediakan beberapa working directory yang berbagi satu repositori, sehingga proses CI yang panjang atau perubahan yang masih berjalan tidak menghalangi pekerjaan berikutnya
- Tim Gradle sudah cukup memenuhi kebutuhan yang sama dengan
git worktree
git worktree add ../gradle-feature-x feature-x
git worktree add ../gradle-hotfix hotfix-7.6
- Pendekatan ini memakai dua checkout dan satu object store
- Dengan ini, pekerjaan paralel dan checkout
main yang dipertahankan dalam jangka panjang bisa dijalankan tanpa stash atau clone kedua
- Tim Gradle telah memakai pola ini selama bertahun-tahun
Kemungkinan meninjau ulang jj
- Kasus ini bukan penilaian final terhadap
jj untuk proyek Gradle
- Operation log milik
jj saja sudah cukup menarik untuk ditinjau lebih dalam
- Dukungan
eol diperlakukan sebagai masalah yang bisa diselesaikan, dan di isu tersebut juga ada pembahasan implementasi melalui gix-filter
- Jika dukungan itu hadir, tim Gradle berencana mencoba lagi
- Sampai saat itu, mereka tetap memakai Git karena
gradlew.bat, dan git worktree mengisi peran yang mereka butuhkan
1 komentar
Pendapat di Lobste.rs
Menurut saya, konfigurasi
autocrlfdi Git dan konfigurasi.gitattributesyang menyusulnya adalah kesalahan sejak awal, dan akan tetap begitu ke depannyaSistem version control tidak semestinya menyimpan file di dalam repository dalam bentuk yang berbeda dari file di disk
Jika ingin memaksakan format file, itu tugas linter, commit hook, atau merge hook, bukan peran sistem version control
core.{eol, safecrlf, autocrlf}harus dipindahkan ke status deprecatedKonversi akhir baris ditambahkan semata-mata karena Windows; format khusus ␍ sudah mati bahkan sebelum Git, dan semua platform kecuali Windows sudah menetap pada format khusus ␊
Sekarang, target utama yang benar-benar peduli pada ␍␊ tampaknya hanya file batch
Semua bahasa berusaha mendukung ␍␊, tetapi sekarang hampir tidak ada yang mengharuskan atau menghasilkannya
Jika Notepad masih memakai ␍␊ sebagai default, atau hanya mendukung itu, pengguna Notepad harus menanggung konsekuensinya
Area yang lebih menarik dalam kompatibilitas Windows adalah file mode
Git membawa mode Unix, dan jejaknya masih tersisa, sehingga saat bekerja di Windows kadang muncul kesalahan mode yang tidak disengaja
Jika tooling sudah cukup baik sehingga saat checkout otomatis memakai whitespace, atau menyesuaikannya ke jumlah whitespace yang sangat spesifik dan aneh yang dipaksakan seseorang, kita bisa menghentikan perdebatan tab versus spasi
Lebih jauh lagi, bisa saja kita berpendapat bahwa sistem version control seharusnya menyimpan abstract syntax tree (AST), bukan teks mentah
Saat ini mungkin sulit meyakinkan orang, tetapi mudah membayangkan lini masa lain atau masa depan di mana cara seperti ini terasa sangat natural
Saya tidak tahu file
.batitu akan dijalankan di mana kalau bukan di WindowsSaya juga bertanya-tanya dalam kasus apa perilaku lain, sekecil apa pun, bisa dianggap diinginkan
Saya tidak yakin dengan argumen bahwa kita tidak boleh meng-commit file persis dengan format akhir baris yang dibutuhkan
Intinya tampaknya adalah “seseorang bisa merusak akhir baris lalu meng-commit-nya, code review meloloskannya, dan skrip yang rusak masuk”
Semua itu benar, tetapi bukankah karena itu ada pemeriksaan lint di CI?
Pindai akhir baris yang bukan CRLF pada file tersebut, dan jika ditemukan, gagalkan CI; maka perubahan yang merusak akhir baris tidak akan bisa lolos tahap pull request
Jawaban “tinggal tambahkan CI saja” tidak cukup
Proyek terkait bisa saja berupa mod Minecraft yang dibuat oleh pemula, dan siapa pun di antara mereka bisa merusak
gradle.battanpa menyadarinyaSaya sendiri juga punya tanggung jawab karena mempromosikan jj sebagai alternatif yang jauh lebih baik daripada CLI Git untuk pemula
Apakah opsi berpindah dari
gradlew.batkegradlew.ps1, yaitu daricmd.exe/file batch ke PowerShell, memungkinkan?Sekarang MUNGKIN bisa diasumsikan bahwa 90% basis instalasi Windows memiliki PowerShell yang cukup baru
Namun, dalam beberapa kasus permission eksekusi default masih harus dinaikkan, dan di lingkungan perusahaan bisa saja dikunci
Saya tidak tahu seberapa banyak Anda pernah memakai PowerShell, tetapi rasanya bukan seperti “karena ada bash, tinggal jalankan file
.sh”Kumpulan fiturnya berbeda-beda antarversi Windows, sehingga rasanya seperti membandingkan
kshdenganbash4