- Gradle ekibi, Git uyumlu VCS olan Jujutsu(jj)’yi günlük geliştirme süreçlerine dahil etmeye çalıştı; ancak Windows için
gradlew.bat dosyasındaki satır sonu işleme nedeniyle benimsemeyi erteledi
- Temel sorun,
jj’nin .gitattributes içindeki dosya bazlı EOL kurallarını okuyamaması ve bu yüzden *.bat text eol=crlf kuralını uygulayamaması
- Git,
gradlew.bat dosyasını depoda LF’ye normalize edip çalışma dizinine CRLF olarak checkout ederken, jj bunu değişiklik olarak algılıyor ve sürekli phantom modification üretiyor
gradlew.bat dosyasını CRLF haliyle commit edip *.bat -text olarak değiştirmek bir geçici çözüm olabilir; ancak bir editör dosyayı LF’ye çevirirse Git bunu otomatik olarak düzeltmediği için Windows’ta çalışma kararlılığı riske girebilir
- Gradle ekibi şimdilik birden fazla çalışma dizinini
git worktree ile yönetecek; jj’de eol desteği uygulanınca tekrar denemeyi planlıyor
Benimsemeyi engelleyen gerçek neden: gradlew.bat ve .gitattributes
- Jujutsu(
jj), Git backend’i kullanırken commit’leri ve dosyaları Git’te saklayan, mevcut Git depolarıyla birlikte çalışabilen Git uyumlu bir sürüm kontrol sistemidir
jj, staging alanını ortadan kaldırır ve çalışma kopyasını sürekli güncellenen gerçek bir commit olarak temsil eder
- Commit düzenleme veya yeniden sıralama sonrasında takip eden commit’leri otomatik olarak rebase eder; çakışmalar işi durdurmak yerine kayıtta tutulabilir ve çalışma günlüğünden geri alma yapılabilir
- Bir Gradle mühendisinin
git yerine jj kullanma girişimi, jj’nin modelinden değil, Gradle projesinin diskte nasıl durduğuna dair küçük bir ayrıntıdan dolayı engellendi
Windows’ta gradlew.bat CRLF’ye ihtiyaç duyuyor
- Tipik bir Gradle deposunda Gradle Wrapper ile birlikte
gradlew.bat bulunur
gradlew.bat, label ve goto kullanır; cmd.exe, yalnızca LF satır sonlarına sahip batch dosyalarını hatalı işleyebilir
- Windows’ta kararlı şekilde çalışması için
gradlew.bat dosyasının CRLF olarak checkout edilmesi gerekir
- Gradle projeleri bu gereksinimi
.gitattributes ile zorunlu kılar
*.bat text eol=crlf
- Git’te bu davranış standart akıştır
- Dosya indekste normalize edilmiş biçimde saklanır
eol=crlf özelliği, checkout sırasında çalışma kopyasında CRLF’yi somutlaştırır
- Düzenlenen içerik tekrar kaydedilirken normalize edilir
jj’nin .gitattributes desteği olmamasının yarattığı phantom diff
jj, .gitattributes dosyasını okumadığı için dosya bazlı satır sonu kurallarını uygulayamaz
- İlgili özellik, eski bir issue olan jj-vcs/jj#53 üzerinden takip ediliyor; en azından
eol özelliği desteği tartışılıyor
- Şu anda
jj içinde kullanılabilen araç yalnızca global ayar olan working-copy.eol-conversion
- Git’teki
core.autocrlf gibi tüm dosyalara topluca uygulanır
- Yalnızca
.bat dosyalarını ayrı olarak belirlemek mümkün değildir
- Colocated repo’da sorun hemen görünür hale gelir
- Git,
gradlew.bat dosyasını LF olarak saklar ve CRLF olarak checkout eder
jj, bu özelliğe uymadığı için diskteki CRLF’yi Git’teki LF blob’a göre değişiklik olarak kaydeder
- Etkilenen Gradle projelerinde
gradlew.bat için sürekli sahte değişiklikler oluşur
- Bu sorun yalnızca Gradle ekibine özgü bir örnek değil
- Bir kullanıcı, altı haneli sayıda dosyada phantom change oluştuğu için
jj kullanmaktan vazgeçti
Önerilen geçici çözümler ve sınırları
jj’nin yazarı issue’da non-colocated workspace’i bir yol olarak önerdi
- Örnek: Git çalışma kopyasının dışında
jj git init --git-repo=<path> kullanmak
- Gradle mühendisi bu yöntemin de sorunu çözmediğini düşünüyor
jj, saklanan LF blob’dan gradlew.bat dosyasını somutlaştırırsa dosya diske LF olarak iner
- LF biçimindeki
gradlew.bat Windows’ta çalışmaz
- Global ayar
working-copy.eol-conversion = input-output ile CRLF zorunlu kılınabilir
- Ancak bu, tüm metin dosyalarını checkout sırasında CRLF olarak yeniden yazdığı için ayrı bir sorun yaratır
Çalışan ama kırılgan çözüm
- Gerçekten çalışan yöntem,
gradlew.bat dosyasını depoya CRLF haliyle commit etmek ve normalizasyonu durdurmaktır
- Kural şöyle değişir
- Eski:
*.bat text eol=crlf
- Yeni:
*.bat -text
- Böylece Git ve
jj, hem saklanan ağaçta hem de çalışma kopyasında CRLF konusunda anlaşır
- Dönüştürme ortadan kalkar
- Phantom diff de kaybolur
- Windows’ta çalışma da korunur
- Buna karşılık
*.bat -text, text eol=crlf kuralının sunduğu otomatik düzeltmeden vazgeçmek anlamına gelir
- Önceden yanlışlıkla LF gelse bile commit sırasında sessizce yeniden normalize edilirdi
- Artık LF olduğu gibi kalabilir ve
gradlew.bat Windows’ta sessizce bozulabilir
- Bu dönüşümün yalnızca bir kez yapılması gerekir ve hatalı düzenlemeler genellikle review sırasında yakalanabilir
- Yine de Gradle ekibi, tüm Gradle projelerinin CRLF’yi doğrudan commit edeceği ve hiçbir editörün bunu sessizce değiştirmeyeceği varsayımını ekosistem genelinde riske atmanın zor olduğuna karar verdi
Şimdilik korunan alternatif: git worktree
jj’nin workspace’i, tek bir depoyu paylaşan birden fazla çalışma dizini sunarak uzun CI çalışmaları veya devam eden değişikliklerin sonraki işleri engellememesini sağlar
- Gradle ekibi aynı ihtiyacı zaten
git worktree ile yeterince karşılıyor
git worktree add ../gradle-feature-x feature-x
git worktree add ../gradle-hotfix hotfix-7.6
- Bu yöntem iki checkout ve tek bir object store kullanır
- Stash veya ikinci bir clone olmadan paralel işler ve uzun süre korunan
main checkout’u birlikte yürütülebilir
- Gradle ekibi bu kalıbı yıllardır kullanıyor
jj’yi yeniden değerlendirme olasılığı
- Bu örnek, Gradle projesinde
jj’nin kendisi hakkında nihai bir karar değil
- Yalnızca
jj’nin operation log özelliği bile daha derin incelemeye değer
eol desteği çözülebilir bir sorun olarak ele alınıyor; issue’da gix-filter üzerinden uygulama tartışmaları da var
- Bu destek geldiğinde Gradle ekibi yeniden denemeyi planlıyor
- O zamana kadar
gradlew.bat nedeniyle Git kullanılmaya devam edecek ve gerekli rolü git worktree üstlenecek
1 yorum
Lobste.rs yorumları
Git’in
autocrlfayarı ve ardından gelen.gitattributesayarının en başından beri bir hata olduğunu ve bundan sonra da öyle kalacağını düşünüyorumBir sürüm kontrol sistemi, depodaki dosyaları diskteki dosyalardan farklı şekilde saklamamalı
Bir dosya biçimini zorunlu kılmak istiyorsanız bu linter’ların, commit hook’larının ve merge hook’larının işi; sürüm kontrol sisteminin rolü değil
core.{eol, safecrlf, autocrlf}ayarlarının kullanımdan kaldırılacaklar arasına alınması gerektiğini düşünüyorumSatır sonu dönüşümünün eklenmesinin tek nedeni Windows’tu; yalnızca ␍ kullanımı Git’ten önce zaten ölmüştü ve Windows dışında herkes yalnızca ␊ üzerinde karar kılmıştı
Artık ␍␊’ye gerçekten önem veren başlıca şeyin batch dosyaları olduğunu sanıyorum
Tüm diller ␍␊’yi desteklemeye çalışıyor, ama artık bunu gerektiren ya da üreten neredeyse hiçbir şey yok
Notepad hâlâ varsayılan olarak ␍␊ kullanıyorsa ya da yalnızca bunu destekliyorsa, Notepad kullanan kişi bunun sonuçlarına katlanmalı
Windows uyumluluğunda daha ilginç alan dosya modları
Git Unix modlarını aldı ve bunun izleri kaldı; bu yüzden Windows’ta çalışırken istemeden mod hataları oluşabiliyor
Araçlar yeterince iyi hâle gelip checkout sırasında otomatik olarak boşluk kullanır ya da birinin çok inatla savunduğu garip derecede belirli boşluk sayısına uydurursa, tab ve boşluk tartışmasını bırakabiliriz
Hatta daha ileri gidip sürüm kontrol sistemlerinin ham metin yerine soyut sözdizim ağacı (AST) saklaması gerektiği bile söylenebilir
Şu anda ikna etmesi zor olurdu, ama bunun çok doğal geldiği başka bir zaman çizgisini ya da geleceği hayal etmek mümkün
.batdosyasının Windows değilse nerede çalıştırılacağını bilmiyorumFarklı bir davranışın az da olsa arzu edilir olduğu bir yer var mı, o da şüpheli
Bir dosyayı ihtiyaç duyduğu satır sonu biçimiyle commit’lememek gerektiği argümanı beni ikna etmiyor
Ana fikir “birisi satır sonlarını bozup commit’ler ve kod incelemesinden geçerek bozuk bir script içeri girebilir” gibi görünüyor
Bunların hepsi doğru, ama zaten CI lint kontrolleri bunun için yok mu?
İlgili dosyada CRLF olmayan satır sonlarını tarayıp bulunursa CI’ı başarısız yaparsanız, satır sonlarını bozan değişiklik pull request aşamasını geçemez
“Sadece CI ekleyin” yanıtı yeterli değil
İlgili proje nispeten acemi birinin yaptığı Minecraft modu olabilir ve içlerinden herhangi biri
gradle.batdosyasını bozup bunu fark etmeyebilirBenim de acemilerin başlaması için CLI Git’ten çok daha iyi olduğunu söyleyerek jj’yi alternatif olarak tanıtmış olma sorumluluğum var
gradlew.battengradlew.ps1e geçmek, yanicmd.exe/batch dosyalarından PowerShell’e geçmek bir seçenek olabilir mi?Şimdi BELKİ Windows kurulu tabanının %90’ında yeterince güncel PowerShell bulunduğunu varsayabiliriz
Ama varsayılan çalıştırma izinlerini yükseltmek gerekebildiği durumlar hâlâ var ve kurumsal ortamlarda kilitli olabilir
PowerShell’i ne kadar kullandınız bilmiyorum ama “bash var, o hâlde
.shdosyasını çalıştırırsınız” gibi bir his değildiWindows sürümlerine göre özellik setleri değiştiğinden,
kshilebash4ü karşılaştırıyormuşsunuz gibi hissettiriyordu