En Sevdiğim Git Commit’im (2019)
(dhwthompson.com)- GOV.UK üzerinde çalışırken ortaya çıkan Dan Carley imzalı “Convert template to US-ASCII to fix error” commit’i, küçük bir kod değişikliğinin bile ayrıntılı commit mesajı sayesinde kod tabanı için uzun ömürlü bir belgeye dönüşebileceğini gösteriyor
- İyi bir mesaj, neyin değiştiğinden çok neden değiştiğini bırakır; bu örnek de
bundle exec rakeçalıştırılırken ortaya çıkaninvalid byte sequence in US-ASCIIhatasını ve yeniden üretim koşullarını somut biçimde kaydediyor - Hata metni ve inceleme süreci birlikte bırakıldığı için, daha sonra aynı sorunla karşılaşan biri
git log --grepya da GitHub commit aramasıyla önceki çözüm kaydını bulabiliyor - Mesajda
find -exec,file --mime,iconvgibi Unix araçlarının kullanım süreci de yer alıyor; böylece incelemeyi yapanlar ve sonradan okuyanlar sorunun çözüm akışını takip edebiliyor - Her commit’in bu kadar uzun olması gerekmese de, bağlamı, inceleme sürecini ve duyguyu bile bırakan mesajlar ekibin paylaşılan kod tabanı anlayışını ve güvenini güçlendirmeye yardımcı oluyor
Küçük bir değişikliği uzun ömürlü belgeye dönüştüren commit
- Git commit mesajları iyi yazıldığında, kod tabanının yaşamı boyunca kalan güçlü bir dokümantasyon aracı olabilir
- Örnek olarak verilen commit, Government Digital Service’te GOV.UK üzerinde çalışılan dönemde yapılan bir değişiklik
- Yazarı Dan Carley, başlığı ise “Convert template to US-ASCII to fix error”
- GDS’nin açık geliştirme yaklaşımı sayesinde, normalde kurum içi kalabilecek bu tür örnekler dışarıyla da paylaşılabiliyor
Uzunluktan daha önemli olan bağlam
- Bu commit’te mesaj, yapılan kod değişikliğine kıyasla uzun; ama asıl değer uzunluğun kendisinde değil, işe yarayan bağlamda
- Aynı değişiklik başka bir yerde
change whitespace,fix buggibi kısa bir notla bırakılabilirdi - Dan, çevresindeki ekip arkadaşlarının ve sonradan okuyacak kişilerin sorunun nedenini ve çözüm sürecini anlayabilmesi için ayrıntılı bir kayıt bırakmış
Neyin değiştiğinden çok neden değiştiği
- İyi bir commit mesajı, sadece neyin değiştiğini değil, neden değiştiğini de açıklar
- Bu commit, feature branch’te
/etc/nginx/router_routes.confiçeriğiyle eşleşen bir test eklendikten sonra, çalıştırma biçimine göre sonucun değiştiğini kaydediyorbundle exec rake specveyabundle exec rspec modules/router/specile çalıştırıldığında her şey normalbundle exec rakeile çalıştırıldığında hershouldbloğu başarısız oluyor- Hata
ArgumentError: invalid byte sequence in US-ASCII
- Bu açıklama olmasaydı, hangi araçta nasıl bir parsing hatası çıktığını tahmin etmek gerekebilirdi
- İlk iş bağlamı, insanlar unuttukça, ekip değiştikçe ya da kurumdan ayrıldıkça kolayca kaybolabiliyor
Aranabilir hata kaydı
- Commit mesajının başlarında, değişikliğe yol açan hata mesajı doğrudan yer alıyor
- Aynı hatayla karşılaşan biri kod tabanında önceki kayıtları şu yollarla bulabilir
git log --grep "invalid byte sequence"- GitHub commit search
- Arama sonuçları, birden fazla kişinin bu hatayı aradığını ve sorunu ilk kimin yaşayıp nasıl müdahale ettiğinin de görülebildiğini gösteriyor
Sorun çözme sürecini bir hikâye olarak bırakmak
- Mesaj, sorunun nasıl göründüğünü, hangi sırayla incelendiğini ve sonunda nasıl düzeltildiğini izlemeyi mümkün kılacak şekilde kurgulanmış
- Örneğin
.with_content(//)matcher’ı kaldırınca hatanın kaybolduğu, spec dosyasında tuhaf karakterler olmadığı ve Puppet aynı yorumlayıcıdarequireedildiğinde durumun yeniden üretilebildiği gibi ayrıntılar yer alıyor - Commit mesajı belirli bir dosyayı, fonksiyonu ya da tek bir kod satırını değil, değişikliğin kendisini belgelediği için kod tabanının geçtiği yolculuğu kaydetmek adına çok uygun bir yer
Ekip bilgisini genişleten yan etki
- Dan, inceleme sırasında çalıştırdığı komutları da kaydetmiş; bu da ekip içinde bilgiyi hafifçe yaymanın bir yolu olabiliyor
- Okuyucu, yalnızca commit mesajından bile Unix araçlarının kullanımına dair bir şeyler öğrenebiliyor
findkomutuna-execargümanı verilerek bulunan her dosya üzerinde bir komut çalıştırılabilir- Komutun sonuna
\+eklemek, her dosya için ayrı ayrı çalıştırmak yerine birden fazla dosya adını tek birfilekomutuna vermeyi sağlar file --mime, dosyanın MIME türünü gösteririconvadlı bir araç vardır
- Bu bilgiyi yalnızca değişikliği inceleyen kişi değil, daha sonra bu commit’i bulan biri de edinir
- Yeterince zaman ve yeterince commit biriktiğinde, bu tür mesajlar ekibin bilgi çoğaltıcı mekanizmasına dönüşebilir
Empati ve güven oluşturan kayıt
- Commit’in sonunda “Now the tests work! One hour of my life I won't get back..” cümlesi yer alıyor
- Bu cümle, bir geliştiricinin bir saat boyunca sinsi bir bug’ın peşinden koşarken yaşadığı hayal kırıklığını ve sonunda çözdüğünde hissettiği tatmini aktarıyor
- Kısa vadeli hack’lerin ya da prototip kodun üretime girip kök saldığı durumlarda bile, bu tür mesajlar her değişikliğin arkasında o anki bilgiyle elinden gelenin en iyisini yapmaya çalışan bir insan olduğunu hatırlatıyor
Her commit’in uzun olması gerekmez
- Bu örnek uç bir vaka; özellikle de bu boyuttaki her commit için aynı ayrıntı düzeyini beklemek gerekmiyor
- Yine de değişikliğin arkasındaki bağlamı açıklayan, başkalarının bir şeyler öğrenmesini sağlayan ve ekibin kod tabanına dair ortak zihinsel modeline katkı sunan güçlü bir örnek
- İyi commit mesajları ve değişiklikleri yapılandırma araçlarıyla ilgileniyorsanız şu kaynaklara bakabilirsiniz
- Telling stories through your commits by Joel Chippindale
- A branch in time by Tekin Süleyman
1 yorum
Hacker News yorumları
İyi ya da kötü, GitHub kurucu ortaklarından biri ve Pro Git gibi Git kitapları yazmış biri olarak bakınca, Git commit mesajları kod dokümantasyonu için kendine özgü ama çok verimsiz bir yol
Temel sorun şu: Git, GitHub vb. çoğu araç genellikle yalnızca ilk satırı gösteriyor. Örnek commit de “US-ASCII error” gibi genel bir tek satır olarak görünüyor; yazıda övülen geri kalan içeriği ise modern araçlarda neredeyse kimse görmüyor
Git, commit mesajını projedeki herkesin okuduğu bir e-posta gövdesi olarak tasarlamıştı, ama bugün çoğunlukla böyle bir rolü yok. Bir posta listesinde patch serisi olarak tartışılmadığı sürece, başlığın ilk 50 karakteri dışında pek okunmuyor
git blameiçinde-w -C -C -Cmi yoksa iki tane-Cmi gerektiğini arayıp ilgili mesajı izleseniz bile yalnızca ilk satır görünüyor; sonunda uzun mesajı görmek için SHA’yı bulupgit showçalıştırmak gerekiyor. İyi yazılsa bile bilgiyi tekrar bulmanın çok zor olması, Git’e dair en büyük şikâyetlerimden biriGit projesinin geçmişine bakarsanız commit mesajları neredeyse her seferinde harika, ama tek bir dosyada
blameçalıştırınca bile bir fonksiyonun implementasyon bağlamını takip etmek çok zor. Jeff King’in son 10 yılda bıraktığı dokümantasyon dâhiyane seviyede; neredeyse kimsenin bunu takdir edememesi korkunçDoğru çözümü bilmiyorum ama çoğu toplulukta commit mesajlarıyla harika dokümantasyon yazmak ne yazık ki neredeyse zaman kaybına yakın. Çünkü bulması çok zor
git blame,git log,git showkullanıyorum; dosya geçmişini takip etmek kolay,git log -Gile ekleme/silme anını bulmak birkaç saniye sürüyorZor olan, commit’i bulduğunuzda mesajın yalnızca “bleh” ya da “add a thing” olması. Geliştirici 60 saniye ayırıp bunu neden yaptığını yazsa yeterdi
Tersine, bir değişikliğin neden yapıldığını ayrıntılı açıklayan bir commit mesajı bulmak gerçekten sevindirici. İyi bir commit mesajı saatler, günler sürecek işi kurtarır
GitHub da kötü commit mesajı sorununa katkıda bulunuyor. Şanslıysanız PR açıklamasında ayrıntılar vardır ama commit log’un hemen yanında değildir; çoğu zaman PR bir Jira bağlantısına, Jira bir Slack konuşması bağlantısına, Slack de bir Google dokümanı bağlantısına gider
Sektör dokümantasyon konusunda gerçekten kötü, ama Jeff King gibi insanlar doğru mücadeleyi veriyor. Sonuçta bunun teknik değil, insan problemi olduğunu düşünüyorum. Dokümantasyon yazmanın anında ödülü yok; ek iş gibi hissettiriyor ve karşılığı günler, haftalar, aylar sonra ortaya çıkıyor
Lütfen iyi commit mesajları yazın. Sadece neden yaptığınızı yazmak için 1 dakika ayırmak bile her commit’in lanet olası Chesterton’ın çiti bilmecesine dönüşmesini engeller. Bunu kolayca bulunabilen commit mesajına koyarsanız gelecekteki siz ve ben minnettar oluruz
Ek olarak, commit mesajlarını bulmanın zor olduğu iddiasına da katılmıyorum. Bir kod satırının, fonksiyonun, dosyanın tarihini takip etmekte neredeyse hiç zorlanmıyorum; commit mesajları tekrar okunmasa bile yazıldığı anda değerlidir. İyi mesaj yazmak, niyet ettiğim kodu gerçekten yazıp yazmadığımı kontrol ettirir ve kod inceleyene de değer katar
git blameseçeneklerini bulmanın zor olduğu sözü de şaka gibi geliyor. İyi bir IDE her satıra blame bilgisini iliştirir, tek düğmeyle farkı gösterir ve bu farkta bağlam satırları ya da silinmiş satırlar için özyinelemeli blame yapabilmelidir. Tig gibi araçlar tam olarak bunu yapıyorGitHub’ın commit mesajlarını görmeyi zorlaştırdığını kabul ediyorum
Commit’e eklenen dokümantasyon eğlence olsun diye yazılmıyor. Daha sonra ortada olmayabilecek birinin gönderdiği patch’i kabul etme riskini azaltan, ilgili düşünceleri görünür kılıp başkalarının onun üzerine çalışmasını sağlayan bir mekanizma. Düşünceleri saklamak kod üzerinde dışlayıcı bir sahiplik biriktirir ve bu genelde iyi bir şey değildir. Commit mesajı iş kanıtı rolü de görür; patch sayısı çok fazla olduğunda önemli hale gelebilir. Ticari projelerde öneminin bir kısmı daha düşük olabilir
Böyle bir dokümanı koyacak başka yer aslında yok. Kod yorumlarına uygun değil. Ama artık Git’in GitHub’la aynı şey olduğunu, Git’in tek amacının değişiklikleri GitHub’a yüklemek olduğunu düşünen bir geliştirici kuşağı var
Git pek iyi değil, ama diğerlerinden çok daha az kötü. Temellere dönüp sürüm kontrolünün gerçek amacını anlamamız gerekiyor
Bu yüzden mevcut topluluğa çok yardımcı olmayabilir, ama birkaç yıl sonra hata ayıklayan kişiye yardımcı olur
Genel yaklaşıma katılıyorum ama başa daha somut bir BLUF koymak iyi olurdu. Örneğin “Fix test issues caused by non-breaking space character \xa0” gibi yazmak.
Sorunun ne olduğu hemen anlaşılır; daha fazlasını öğrenmek isteyenin aşağıyı okuma özgürlüğü de kalır.
Bu yüzden kayıtlar içinde arama yapmak için iyi bir ilk satır mesajı yeterli. Hatanın kök nedenini bulmak için Narnia’ya gidip dönülen kısa hikâyenin pek ilgili olduğunu düşünmüyorum. Yine de PR açıklamasında ya da commit’in genişletilmiş mesajında biraz iç dökmek için yazılmasına karşı değilim.
Harika commit mesajları yazmanın gururunu yaşadım ama bunun başkalarına sağladığı değerden daha az eminim. Tuhaf bir hata mesajıyla karşılaşınca, yeni bir özellik eklerken ya da neredeyse herhangi bir durumda, çoğu kişinin commit mesajlarında arama yaptığını sanmıyorum.
Biraz üzücü ama güzel commit mesajlarının programcının kibrine yakın bir yanı olduğuna dair şüphem artıyor. Bunlara hayran kalan kişi çoğunlukla yazanın kendisi oluyor; başkaları fark etmeden geçip gidiyor.
Bazen böyle estetik süslemelere yer olabilir ama pratik değerinin büyük olduğundan emin değilim. Başkası “fix whitespace issue” diye commit atsa artık fazla umursamamaya başladım; bunun sayesinde daha iyi bir ekip arkadaşı olduğumu düşünüyorum.
Git ya da Linux gibi devasa dağıtık ekipleri ve sayısız commit’i olan projelerde durum farklı olabilir. Aşina olduğum projelerde katkı veren sayısı 1–100 arasında ve çoğu aynı organizasyona bağlı.
Google’da ya da Stack Overflow’da yanıt bulamadığımda, GitHub’da benzer bir şeyin PR’larda veya commit mesajlarında geçip geçmediğini de ararım. Erişebildiğim özel depolar dahil, sayısız kez faydasını gördüm. İyi commit mesajları kibri aşar; kesinlikle değeri vardır. Çok sayıda geliştirici bakmıyorsa bu onların kaybı; deneyim kazandıkça bir gün fark etmelerini umarım. Junior geliştiricilere arama yapmayı öğretmek ya da asıl yazıyı göndermek de iyi olabilir.
Ondan sonra commit mesajlarını en azından gelecekteki ben’in bu değişikliğin neden gerekli olduğunu hatırlayabileceği şekilde yazmaya çalışıyorum.
git blameyapmıyorsanız yanlış yapıyorsunuz demektir.Bariz bir hatayı düzeltmek üzereyken commit’ten hemen önce önceki commit’e bakıp, o “hata”nın bilinçli olarak eklenmiş olduğunu ve bağlı JIRA işinde benim bariz değişikliğimin neden 2 yıl önceki bir bug’ı geri getireceğinin iyi açıklandığını birkaç kez yaşadım.
git blameözelliğiyle ne olup bittiğini sık sık anlıyorum. İyi bir commit mesajı bulunca minnet duyuyorum.Commit mesajının ilk satırı,
git logun Chesterton’ın çiti ile başa çıkabilmesini sağladığı için en önemlisidir. Bu örnekte yazarın boşa salladığını düşünüyorum.İlk satıra ne yapıldığını değil, neden yapıldığını koymak asıl noktadır. Neyin değiştiğini merak eden kişi koda ya da diff’e bakabilir.
Örneğin “nginx .conf files must be in us-ascii” yazıp ardından “changed blahblah.erb to remove nonbreaking space character” koyar, sonra da geri kalan oldukça iyi commit mesajını sürdürebilirsiniz.
Bunu bir haber yazısı gibi düşünmek gerekir. Okurun herhangi bir noktada okumayı bırakabileceğini varsayıp, önem azalan ve ayrıntı artan sırayla yazmak gerekir.
Haber yazıları da başlıkta nedeni değil, ne olduğunu anlatır.
Bu durumda orijinal ilk satır tam isabet.
git logiçinde gezinirken bu commit’in testlerin işlevsel davranışını değiştirmemiş olma ihtimalinin yüksek olduğunu düşünüp geçebilirsiniz.“nginx .conf files must be in us-ascii” bir bug ya da PR başlığı olarak iyi olabilir ama farklı işler yapan birden çok commit’e karşılık gelebilir ve gerçekte ne olduğunu söylemez. Dosyalar US-ASCII’ye mi dönüştürülüyor, bir dönüştürme aracı mı yapılıyor, dokümantasyon mu güncelleniyor, test mi yazılıyor, yoksa bunların bir kombinasyonu mu belli değil. Nedenle değil, ne ile başlamak bu karmaşayı azaltır.
“The files must be in us-ascii” de olsa “Changed the files to us-ascii” de olsa çok fark etmez. İkisi de dosyaların US-ASCII’ye değiştirildiğini açıkça bildiriyor.
Bu belgeleme yönteminin dezavantajı, bir kez yazılmış bir commit mesajını fiilen değiştiremiyor olmanızdır.
Elbette
rebaseile mümkün, ama 1 yıl önce yazılmış ve zatenmainile birleştirilmiş bir şeyi gerçekten değiştirip herkesin feature branch’ine acı çektirmek ister miyiz?.mddosyalarında, Wiki’de, Confluence’ta tutulan belgelerle karşılaştırırsak, bir iş arkadaşımın yazdığını ben iyileştirebilirim, başka bir iş arkadaşım da benim yazdığımı iyileştirebilir.Bu örnekte bug düzeltilmiş ve bir daha ortaya çıkmayacak olabilir. Ama belirli bir bileşeni commit ederken tasarımını açıklama isteği doğuyor; artık bundan kaçınıyorum. İş gereksinimlerinin değişmesi gibi nedenlerle o bileşen daha sonra değişirse ne olacak? Commit belgesi yalnızca farkı mı açıklayacak? O zaman yeni bir ekip üyesinin sistemi anlamak için birden çok commit mesajı okuyup bunları zihninde birleştirmesi gerekecek.
.mddosyalarıyla ya da Wiki, Confluence ile karşılaştırmak bisikletle kazı karşılaştırmak gibidir.Bir bileşen oluşturulurken hangi hususların ve ödünleşimlerin düşünüldüğü, hatta böyle şeylerin hiç olmadığı gerçeği; özgün kusurları, sonraki evrimde oluşan kusurları ve kullanım senaryosu değişikliklerinden doğan kusurları anlamakta sık sık faydalıdır.
Yeni bir ekip üyesinin sistemi anlaması gerekiyorsa ayrı bir “güncel” belge tutulabilir. O belgenin uygulamadaki ödünleşimleri ya da ilk taslağın zaman baskısı altında yazıldığı gerçeğini ele alması gerekmez.
Commit’leri sıkıştırınca özellik ekleme anlatısı olarak kayıt daha iyi olur; birleştirme gerçek kod değişikliklerinin değişmez günlüğünü korur; yeniden yerleştirme ise ikisinden de biraz yapar.
İkisine birden sahip olamamak için bir neden yok. Bilgisayarları programlayan insanlarız; istediğimiz gibi yapabiliriz.
Git’i baştan yazacak olsaydım commit’i iki parçaya ayırırdım. Değişiklik geçmişini Git’teki gibi Merkle DAG benzeri bir yapıda değişmez bırakır, commit mesajlarını ise iş akışını açıklayan makul ve düzenlenebilir bir günlük yapmak için ayrı bir ilişkili veri deposunda tutardım. Commit’leri özellik etiketleri etrafında gruplandırmayı, yazım hatalarını düzeltmeyi ve mesajları istediğimiz gibi değiştirmeyi mümkün kılardım; alttaki fark günlüğü, yani “kodda gerçekten değişen şey” ise aynen korunurdu.
git notesile ekleme yapılabilir. Yalnız mesaj bu kadar uzunsa birinin fark etme olasılığı düşük görünüyor.Katılmadığım bir nokta var: “Her commit’ten, özellikle de bu boyuttaki bir commit’ten bu düzeyde ayrıntı beklemem” kısmı.
Deneyimime göre tam tersine, küçük ve zararsız görünen şeylerin nispeten daha uzun açıklamaya ihtiyaç duyduğu durumlar çok oluyor.
Dün
gh pr listkomutuna neden--limit=999eklediğimi üç paragrafla yazdım. Çünkü kafa karıştırıcı.--jqargümanının içinde zatenlimit(var ve toplam PR sayısının sonsuz olduğunu varsayarsak değer yükseldikçe nihai sonuç aslında daha da düşüyor.Kod yorumu da yazdım ve muhtemelen yazmaya harcadığımdan daha fazla zamanı düşünmeye ve inceltmeye harcadım. Biri bu işin gelişigüzel kod basmak olduğunu ima ettiğinde bunu bir sonraki örnek olarak hatırlasın isterim.
“This was a non-ascii whitespace character that caused
ArgumentError: invalid byte sequence in US-ASCIIwhen runningbundle exec rake” kadarı yeterli. Sonradan benzer sorunları aramak için anahtar kelimeler var, kök nedeni içeriyor ve insanların üzerinden kayıp geçme olasılığını artıracak kadar uzun değil.Bunun harika bir Git commit’i olduğunu düşünmüyorum.
O kadar metne kıyasla ilk satır olan “Convert template to US-ASCII to fix error” daha iyi olabilirdi. Hangi boşluk karakterinin hataya yol açtığını ve hatanın ne olduğunu birkaç kelimeyle daha eklemek yeterdi. Bu açıklama ve diff gerekli bağlam için yeterli.
Açıkçası geri kalanın çoğu neredeyse işe yaramaz. Zararı yok, ama değeri de büyük değil. Yazarın bu bug’ın izini sürme yolculuğunu belgelemiş olması kimin umurunda olur ki?
Yazıda, o düzeltmeden öğrenen insanların bıraktığı birkaç commit’i gösteren arama sonucu bağlantısı da var.
O commit mesajı bir bilgi hazinesidir.
Harika commit mesajları görmek istiyorsanız Linux kernel’inin Git geçmişine bakın. Orada standart budur.
İlk satır her zaman değişiklikten etkilenen alt sistemi belirtir, ardından emir kipinde tek satırlık bir özet gelir. Sonrasında üç soruya olabildiğince ayrıntılı yanıt verilir:
Örnek olarak şöyle yazılabilir: “Mevcut kod X yapıyor. T test vakası çalıştırıldığında beklenmeyen U davranışı gözlemlendi. Bunun nedeni R. F yaparak düzeltiyoruz.”
Yakın zamanda bir katkıcıdan Git mesajlarına yaklaşımımın, yani gereksinimlerimin “benzersiz” olduğu söylendi. Linux çekirdeği geçmişim kendini belli etmiş olabilir ama benim commit mesajlarımın hepsi burada gösterildiği gibi görünür.
Mevcut kodla ilgiliyse yorumlar kodla birlikte olmalı. Süreçle ilgili konular, örneğin kaldırılmış kod veya çalışmayan kod, commit içinde olmalı.
En önemlisi, commit mesajı kolaylık açısından bir issue’ya referans verebilir ama temel ayrıntıları mutlaka yeniden üretmelidir. GitHub geçicidir; Git mesajları öyle değildir.
Bağlamla dolu commit mesajı burada[1].
Bu o kadar sık oluyor ki bakımcı bu yazıyı yazmış[2].
[1] https://github.com/git/git/commit/d70f554cdf38b0b05cfaa8e8eb...
[2] https://lore.kernel.org/git/xmqqedevo8ps.fsf@gitster.g/