3 puan yazan GN⁺ 2024-09-12 | 1 yorum | WhatsApp'ta paylaş
  • GitHub tarzı PR incelemesi, özgün değişikliğin üstüne düzeltme commit’lerinin kolayca yığılmasına yol açar; bu da inceleme süreci ile nihai kod geçmişinin birbirine karışması sorununu doğurur
  • İyi bir yama serisi; refactoring, yeni API ekleme ve mevcut kullanıcıları taşıma gibi mantıksal olarak ayrılmış commit’lerin sırayla okunabilmesini sağlamalıdır
  • "fix review" ya da "minor" gibi commit’ler biriktikçe değişikliğin amacı bulanıklaşır ve git blame ile git bisect kullanarak sorunun kök nedenini bulmanın maliyeti artar
  • interdiff incelemesi, yama serisinin yeni bir sürümünü yayımlar ve commit bazındaki değişiklik farklarını git range-diff main..v1 main..v2 ile karşılaştırır
  • İnceleyen kişi 500 satırın tamamını yeniden okumak yerine yalnızca 50 satırlık artımlı farkı kontrol edebilir; yazar da "address review" gibi gürültü commit’leri olmadan nihai commit yapısını koruyabilir

Kod inceleme araçları ve başlangıç noktası

  • Gerrit Code Review, Git deposuyla birlikte çalışan bir açık kaynak kod inceleme aracıdır; yamaların gönderilmesini, başkalarının kodu incelemesini ve yorum bırakmasını destekler
  • Kod inceleme yöntemleri Gerrit, GitHub ve Phabricator’la sınırlı değildir; hata takip sistemine .patch dosyası yüklemekten git send-email kullanmaya, bir meslektaşla uzun tartışmalar sonunda implementasyonu yönlendirmeye kadar çeşitlidir
  • Go programlama dili Gerrit kullanır, KDE ve LLVM Phabricator kullandı; Jujutsu ise bir dönem Gerrit kullanımını değerlendirdi
  • Linux çekirdeği e-posta tabanlı iş akışını kendine özgü bir şekilde kullanır ve birçok proje, kullanımı kolay ve başlangıç maliyeti düşük olduğu için GitHub’ı seçer
  • Asıl sorun, araçların aynı inceleme modelini sunmaması ve GitHub’ın varsayılan deneyiminin her zaman yeterli olmamasıdır

İyi bir yama serisinin koşulları

  • İdeal bir yama serisi, tek bir büyük değişikliği mantıksal adımlara bölerek sunar
    • Önce tesadüfen fark edilen bir kod temizliği yapılır
    • Sonra yeni bir API eklenir
    • Son olarak mevcut API kullanıcıları yeni API’ye taşınır
  • Her yamanın bağımsız bir gerekçesi olmalı ve sırayla uygulandığında kodun adım adım nasıl evrildiği görülebilmelidir
  • Bu yapı yalnızca yazar ve inceleyen için değil, daha sonra blame ya da bisect ile değişikliğin nedenini araştıracak bakımcılar için de avantaj sağlar
  • Gerçek yama boyutu duruma göre değişir
    • Refactoring olmayabilir
    • 100 satır olabilir
    • Temel bir API değişikliği gibi tüm çağrı noktalarının düzeltilmesi gerekiyorsa 500 satır da olabilir

GitHub tarzı “diff soup”un oluşturduğu karışık geçmiş

  • GitHub, inceleme yorumlarını yansıtırken özgün commit’lerin üstüne yeni commit’ler ekleme akışını açık ya da örtük biçimde teşvik eder
  • Örnekte, özgün 3 commit’in ardından sırasıyla Alice ve Bob’un inceleme geri bildirimleri, test ekleme ve "minor" implementasyon değişikliği commit’leri birikir
  • Commit grafiğinde yalnızca ebeveyn-çocuk ilişkileri kaldığı için, inceleme düzeltme commit’lerinin özgün commit’lerdeki hangi sorunu düzelttiği görünmez
    • Tek bir "fix review" commit’i birden fazla özgün commit’e aynı anda dokunursa kavramsal model daha da karmaşıklaşır
    • Bir düzeltme commit’inin tam olarak tek bir geri bildirimi yansıtması sağlanabilir ama bu kez fixup commit sayısı artar
  • Büyük değişiklik paketiyle inceleme düzeltmelerinin aynı kapta karıştığı bu durum diff soup olarak adlandırılır

git blame ve git bisect sinyalinin bulanıklaşması

  • git blame satır düzeyinde çalıştığı için, inceleme yansıtma commit’i mevcut satırın küçük bir bölümünü bile değiştirirse satırın kaynağı "fix alice review" gibi bir commit olarak görünebilir
  • Gerçek değişiklik nedenini bulmak için özgün commit ile inceleme düzeltme commit’lerini yeniden takip etmeyi gerektiren bir commit arkeolojisi gerekir
  • git bisectte de "minor" commit’inin gerçekten kök neden olup olmadığı ya da hatanın yeni API ilk eklendiği anda var olup sonradan mı görünür hâle geldiği belirsizleşebilir
  • Yeni API büyük bir performans artışı sağlıyorsa geri almak istenmeyebilir ya da mümkün olmayabilir
  • Regresyon haftalar sonra ortaya çıkarsa, P1 toplantısı gibi acil bir durumda yalnızca "minor" commit mesajına bakıp ek araştırma yapmanın maliyeti doğar
  • İncelemenin yalnızca iki tur sürdüğü örnekte bile geçmiş karmaşıklaşır; açık kaynak projelerde olduğu gibi çok sayıda inceleme turu olduğunda sorun daha da büyür

GitHub UX’in bu akışı güçlendirme biçimi

  • GitHub’da artımlı inceleme yapmak için üstüne yeni commit ekleme yaklaşımı fiilen en kolay yoldur
    • İnceleyen için yeni API’nin 500 satırını baştan okumaktansa +/- 10 satırlık bir "fix alice review" yamasına bakmak daha az zahmetlidir
  • PR’nin diff sekmesi varsayılan olarak tüm commit’leri tek bir diff içinde birleştirerek gösterir
    • Bu, git diff master..foo-branch görüntülemeye benzer
    • İnsanların değişiklik yazma ve okuma biçimiyle çok iyi örtüşmez
  • GitHub UX, adlandırılmış branch modeline güçlü biçimde uyumludur; bu da branch dışındaki birimler arasındaki farkları görmeyi zorlaştırır
  • Force push sonrasında PR’deki Force Push satırındaki Compare düğmesiyle diff görülebilir
    • Ancak bu yalnızca önceki branch head’i ile mevcut branch head’i arasındaki tam diffi gösterir
    • Daha ayrıntılı karşılaştırma için commit kimliklerini elle bulup URL’ye eklemek gerekir

interdiff incelemesi ve git range-diff

  • interdiff incelemesi, özgün 3 commit’in üstüne düzeltme commit’leri eklemek yerine aynı 3 commit’ten oluşan yeni bir sürüm yayımlar
  • Örneğin v1 yama serisine Bob’un yorumlarını yansıtmak gerekiyorsa, birinci ve üçüncü commit düzenlenerek v2 serisi oluşturulur
  • Sonrasında Alice’in yorumları, test ekleme ve "minor" değişikliği de aynı şekilde yansıtılsa bile nihai sonuç yine 3 commit olarak kalır
  • Eğer v1deki A, B, C commit’leri v2deki X, Y, Z commit’lerine evrildiyse, git range-diff her konumdaki commit’ler arasındaki farkı gösterir
git range-diff \
  main..v1 \
  main..v2
  • Bu komut, v1 branch’indeki 3 commit ile v2 branch’indeki 3 commit arasındaki eşleştirilmiş diffleri gösterir
    • Birinci commit diff(A, X)
    • İkinci commit diff(B, Y)
    • Üçüncü commit diff(C, Z)

interdiff yaklaşımının pratik etkisi

  • GitHub genelde diff(main, C) ya da diff(main, Z) gibi tüm branch diff’ini gösterirken, interdiff commit sürümleri arasındaki farkı gösterir
  • İnceleyen kişi daha önce gördüğü 500 satırlık API değişikliğini yeniden okumak yerine yalnızca değişen 50 satırı kontrol edebilir
  • Yazarın geçmişte "address review" gibi 30 gürültü commit’i biriktirmesi gerekmez
  • git blame, satırları daha az gürültüyle özgün değişiklik commit’lerine bağlama olasılığını artırır
  • git bisect, regresyonu yeni API commit’i gibi daha anlamlı birime işaret etme olasılığını artırır
  • Sonuç olarak temel tanılama araçlarının sinyal-gürültü oranı iyileşir

Birleştirme stratejisi ve rebase hakkında notlar

  • Yama birleştirme stratejisine ilişkin açıklama TODO olarak bırakılmıştır
  • Yaklaşım, başkalarının commit’lerini bunun üstüne kurmasının beklendiği herkese açık bir branch söz konusu değilse git rebase kullanımının sorun olmadığı yönündedir
  • interdiff inceleme sistemi, daha küçük ve daha hızlı birleştirilebilen yamaları teşvik eder
    • 5 commit’in tamamı hazır olana kadar beklemek gerekmez
    • İlk 3’ü uygunsa ve son 2’si daha fazla çalışma gerektiriyorsa yalnızca bu 3’ü birleştirmek mümkündür
  • Amaç, insanların uzun ömürlü branch’ler yerine main branch’i temel alarak çalışmasını sağlamak ve birden çok uzak branch’in birbirine dolanarak birleştirilmesi durumunu azaltmaktır
  • Linux çekirdeği gibi bazı projelerde herkese açık branch’ler başka depolarla birleştirilir ya da başka branch’lerin üstünde açıkça yayımlanır
    • Linux geliştiricileri yama serilerini oluşturup cilalarken git rebase kullanabilir
    • Ancak herkese açık branch oluşturulduktan sonra bu branch bir başkasının ağacına birleştirilebileceği için force push yapılmaz; bunun yerine yeni commit’ler içeren yeni bir branch oluşturulur

1 yorum

 
GN⁺ 2024-09-12
Hacker News yorumları
  • GitHub’da genel olarak buna benzer bir akış kullanıyorum; dezavantajı bana daha fazla iş çıkarması ve işbirlikçiler için sezgisel olmaması
    Yine de gözden geçiren kişinin yalnızca kendi geri bildirimlerinin yansıtıldığı farkı görebilmesi, git blame ve git bisecti bozmaması gibi avantajlar olduğu gibi duruyor
    İnceleme geri bildirimini işlerken git commit --fixup ile commit atıyor, push ettikten sonra inceleme yorumuna yanıt olarak fixup commit hash’ini bırakıyorum
    PR onaylanıp merge’den hemen önceki aşamaya gelince git rebase --interactive origin/main --autosquash çalıştırarak fixup commit’leri asıl commit’lerle birleştiriyor, son olarak git push --force-with-lease sonrası merge ediyorum
    İnceleme bitmeden force push yaparken dikkatli olmak gerekiyor. Bunu yaparsanız reviewer son incelemesinden sonra eklenenleri göremez hale gelir
    Terminal otomatik tamamlamasına epey bağımlıyım; git re kadar yazınca bile uzun komuta ulaşabiliyorum, ama biraz hantal. Bu akışı destekleyen ve teşvik eden bir araç olsa iyi olurdu. Yine de GitHub’a bağlıysanız bu kadarı fena değil

    • Ben de tam bunu söyleyecektim. Etkileşimli rebase, yazarın şikâyet ettiği “diff soup” sorununu oldukça büyük ölçüde çözüyor
      Ancak pratikte daha çok Git’in ileri seviye özelliklerini bilinçli olarak öğrenen, disiplinli mühendislik ekiplerinde kullanılıyor
    • ~/.gitconfig içine aşağıdaki ayarı koymak yeterli
      [rebase] autosquash = true
      Böylece sonrasında yalnızca git rebase -i origin/main ile fixup/squash commit’leri otomatik olarak yeniden sıralanır. Küçük bir ayar ama iş akışını ciddi biçimde iyileştiriyor
    • https://news.ycombinator.com/item?id=37086022
    • Fixup commit’leri de iyi bir yaklaşım ama kişisel olarak sevmiyorum. Sapling’in absorb komutu gibi, iç SCCS weave üzerinde ilgili farklara değişiklikleri otomatik olarak emen ve etkileşimli bir UI ile onaylatan yöntemin çok daha zarif olduğunu düşünüyorum
      Üzerinde birden fazla branch bulunan commit serilerini rebase ederken --update-refs gerekmesine benzer bir alan bu. İnsan neden graf ilişkilerini takip etmek, commit’leri elle yerleştirmek ve branch’leri taşımak zorunda kalsın ki? Bilgisayarlar graflarla iyi başa çıkar; işi onlara bırakmak gerekir
      git absorb da var ama Sapling uygulaması kadar sağlam değil[1]
      Asıl sorun etkileşimli rebase kullanılıp kullanılmaması değil; çoğunlukla inceleme aracının kendi kullanıcı deneyimi ve bunun teşvik ettiği döngüsel yapı. Örneğin fixup commit’leri, GitHub’ın referans noktaları arasındaki farkları gösterme sorununu çözmez; referans noktası büyükse incelemeyi tamamen mahvedebilir. Örneğin 10 yeni commit’in üstüne rebase ettiğiniz durum böyle
      Git’in kendi UX’inden de şikâyetçiyim ama orijinal yazı daha çok GitHub’a yönelik bir şikâyet gibi
      [1] İki temel algoritma arasındaki farkı gösteren örnek bu GitHub issue’sunda var: https://github.com/martinvonz/jj/issues/170
    • Git alias’ları gerçekten sihir gibi
  • Bu yöntemin ideal olduğuna %100 katılıyorum. GitHub yöntemi gerçekten berbat ve bu kadar çok insanın bunu normal kabul eder hale gelmesi trajik
    Eskiden Phabricator ile bunu böyle yapardık; tüm incelemeleri tek seferde güncelleyen komut satırı makrosu sayesinde bir ölçüde elle yapılabiliyordu. Yine de açık bir UI olsa daha iyi olurdu

    • Yazının yazarı benim; girişte “kod incelemesi genel olarak oldukça iyi bir fikirdir” ifadesini özellikle kullandım. Çünkü eskiden Phabricator ana sayfasındaki satış metinlerinden biriydi :) Özledim
  • Evet. Kafamda gerçek kod inceleme tarzı olarak hayal ettiğim şey tam olarak buydu; GitHub’ın yaptığı yöntem değil. Bunun bir adı olduğunu öğrenmek güzel
    Ek olarak, inceleme sisteminin hazır yamaları incelemenin “dışına” itebilmesi iyi olurdu. Büyük bir özellik üzerinde çalışırken yapılan küçük bir hata düzeltmesi küçük ve bağımsız bir yama olmalı; reviewer ile hızlıca uzlaşılması muhtemel
    O zaman o yamayı tüm seriden çıkarıp main’e cherry-pick etmek ve incelemeyi yeni HEAD üzerine rebase etmek isterim. Ya da güncel yama serisini main üzerine rebase edip uzlaşılan yamayı en başa yeniden sıraladıktan sonra main’i o yamaya fast-forward etmek de mümkün olabilir
    Esasen inceleme kapsamını “hâlâ tartışılmakta olan kısım” ile daraltıp, hata düzeltmelerinin hazır olur olmaz merge edilmesini sağlamak anlamına geliyor
    Karşı argüman “bunu ayrı bir inceleme/PR yap” olacaktır; ama o zaman patch set A’nın patch set B’ye bağımlı olması, B merge edildikten sonra ise main’e bağımlı hale gelmesi gibi karmaşıklıklar doğuyor

    • Sürekli tekrarlıyorum ama Gerrit bunu varsayılan olarak yapıyor :) Gerrit’te herhangi iki patch arasındaki ilişkiyi görebilirsiniz ve daha da önemlisi her patch’i ayrı ayrı gösterir. Bu yüzden A -> B -> C serisinde B küçük ve uygunsa doğrudan içeri alabilirsiniz
      Burada Attention Set gibi akıllı UX fikirleri de rol oynuyor. Temelde “sonraki eylemi yapması gereken kişi kim?” sorusunu gösterir ve sıra tabanlı bir oyun gibi çalışır. İncelemeyi az önce yaptıysanız o patch’in attention set’inde artık siz değil, yazar vardır
      Bu yüzden Gerrit UI’da o öğe kuyruğunuzun altlarına iner. Kuyruğun en üstünde attention set’inde sizin bulunduğunuz öğeler vardır. İşler doğal olarak bu şekilde gruplanır
      GitHub UX’indeki diğer sinir bozucu küçük sorunların hepsine değinmedim ama pull request listesi bile alternatiflerden kötü. Hangi öğenin hangi durumda olduğunu anlayamazsınız ve sonunda her şeyi okumanız gerekir
    • Gerrit tam olarak bunu yapabiliyor. x-b-c-d-e zincirini push ederseniz UI’da yığılmış biçimde görünür; ama b’yi main’e kolayca cherry-pick edebilir, CI’ın geçtiğini ve normal incelemenin tamamlandığını kontrol ettikten sonra kalanları onun üzerine rebase edebilirsiniz
      En alttaki x ise doğrudan submit edip kalanlarla devam edebilirsiniz
  • Kod incelemeye yönelik yeni yaklaşımlar görmek her zaman ilginç. GitHub’ın da avantajları var ama mükemmel olmaktan çok uzak
    Verilen senaryoda, üç yamayı birbirine bağımlı ayrı pull request’lere bölmeyi düşünebilirsiniz. GitHub bunu varsayılan olarak desteklemiyor ama uygun bir kod inceleme aracı, pull request’leri küçük tutarken bağımlılıkları da yönetebilmelidir. Örneğin yama 3’ün yama 2’ye, yama 2’nin de yama 1’e bağımlı olmasını sağlayabilirsiniz
    Aracın sunduğu bağımlılık takibi sayesinde, gerekirse hepsinin birlikte dağıtıma çıkması güvence altına alınabilir
    Her yamayı ayrı incelemek geri bildirimi daha net ve yanıtlamayı daha kolay hâle getirir. Pull request içinde commit’leri squash ederek tek tek değişiklikleri doğru yansıtan temiz bir commit geçmişi de oluşturabilirsiniz. Daha da ötesi, uygun bir araç pull request’leri ve incelemeleri yapay zeka ile özetleyerek, elle uğraşmadan doğru commit mesajları yazmayı da kolaylaştırabilir
    İyi bir kod inceleme aracı rebase, merge, force push gibi git işlemlerinin etkisi altında kalmamalıdır. Arkada ne kadar karmaşık git işlemi olursa olsun, inceleyen kişi yalnızca son incelemeden bu yana olan değişiklikleri görmelidir. Böylece büyük diff’i yeniden incelemek yerine yeni içeriğe odaklanabilir ve inceleme geçmişi commit geçmişinden ayrılarak temiz kalır
    Pull request’leri bu şekilde bölüp karşılıklı bağımlılıkları takip etmenin gereksinimi karşılayıp karşılamayacağını merak ediyorum

    • “Kod incelemeye yönelik yeni yaklaşım” ifadesi olumlu ve mevcut güçlü oyunculara karşı da nazik bir söz ama bu hiç de yeni bir fikir değil
      Kelimenin tam anlamıyla git’in desteklemek üzere tasarlandığı iş akışı bu ve GitHub pull request’lere sahip olduğundan beri dile getirilen eski eleştirinin özü de bu
      Bu fikrin, takvime bakınca 15 yılı aşkın süre boyunca “mailing list eskilerinin” yöntemi diye küçümsendikten sonra neden ancak şimdi moda geliştirici kültürlerine yükseldiğini merak ediyorum
      Pek çok yazılım geliştiricinin en çok kullandığı araçlardan birini doğru düzgün öğrenmeyi uzun süre reddettiği için kasıtlı olarak kötü iş akışları seçtiğini düşünüyordum. Bu yüzden şirketi git’e geçirirken böyle araçları ve akışları seçip geliştirdim. Ne de olsa IBM satın aldınız diye kovulmazsınız
    • Bildiğim kadarıyla bir seriyi ayrı PR’lara bölme yöntemi, ancak depoda commit yetkiniz varsa düzgün çalışıyor. Böylece bir PR’ı main’in değil, ana depodaki başka bir branch’in üzerine koyabilirsiniz
      Dış katkıda bulunan biri depo fork’u kullanıyorsa, üç PR sırasıyla A, A+B, A+B+C’yi kademeli olarak içerir. Bu durumda son iki PR’da, başka PR’da zaten incelenmiş kodu tekrar diff olarak görmek gerekir ve bu da incelemeyi zorlaştırır
    • Yazarın zaten bir branch’i ve onun commit’leri var. O hâlde branch’i her biri tek commit içeren üç pull request’e bölmenin amacı ne?
      Her commit bağımsız olarak incelenebilir. Commit’ler arası bağımlılık takibi de yapılabilir. Yerleşik yapay zeka olmaması da iyi bir şey. PR’ların aksine commit’ler arasında interdiff de görülebilir
      Commit’ler Git’in temel yapı taşlarıdır. Sadece commit kullanın
    • Bu thread’in başka yerlerinde de belirtildiği gibi, bu Sapling’in de izlediği yaklaşım
      GitContext’in fixup, rebase, yeniden sıralama gibi işlemlerden geçmiş commit’leri nasıl takip ettiğini merak ediyorum
    • Eski usul merge train yöntemiyle yapılamaz mı? Pull request A branch B’yi, B de master’ı işaret etsin; sonra B’yi master’a merge edip ardından A’yı tekrar master’a çevirsek olmaz mı, noktayı mı kaçırıyorum?
  • Bu yazının yazarıyım. Bana istediğinizi sorun
    Ek olarak, kurallara aykırı mı bilmiyorum ama yakın zamanda yeni bir işe ihtiyacım oldu. Geliştirme araçları ve zor problemlerle uğraşmayı seviyorum. Bu yazı hoşunuza gittiyse, geliştirme ekibinizin üretkenliğini artırmak istiyorsanız ya da harika ve zaman zaman eklektik zevkimi deneyimleyip bundan keyif almak isterseniz profilimde e-posta adresim var

    • Güzel bir kahkaha attırdığın için teşekkürler :)
      Ciddi konuşursam, özgeçmişin etkileyici. İyi ve hızlı şekilde yerleşmeni dilerim. Çok yakın zamandaki iş arama deneyimime göre mevcut işe alım piyasası ölümcül derecede hasta. Ne kadar kıdemli ve deneyimliysen, çılgın mülakat/İK uygulamaları ve açıklanmayan retler ruha o kadar daha çok acı veriyor
      Bir arkadaşım aşağıdaki bağlantıları gönderdi
      https://danluu.com/hiring-lemons/
      https://danluu.com/programmer-moneyball/
      https://danluu.com/algorithms-interviews/
      Bol şans
    • interdiff inceleme stilinin düşünce modelini ve GitHub kod inceleme yaklaşımının sorununu çok iyi özetlemişsin
      Henüz değinilmeyen bir nokta da şu: diff soup yüzünden insanlar fixup commit’lerinin “gürültüsünü” ortadan kaldırmak için squash merge stratejisini tercih etmeye başlayabiliyor. Bu da baştaki iyi, atomik 3 commit’i de birlikte çöpe atıyor
      interdiff inceleme stilinde baştaki 3 commit korunur; bunları tek tek mi yansıtacağınıza yoksa squash mı edeceğinize karar vermek tamamen commit’in kendisine ve gerçek atomikliğine bağlı olabilir
    • GitHub’ın ücretsiz kısmını kullanmış biri olarak diff soup ifadesi tam oturuyor. Ücretli sürüm daha mı iyi? GitLab Gerrit’e daha çok yaklaşabilir mi?
      GitHub’ın acısını azaltmaya çalışan harici servisler de var ve stacked diff desteği sunuyorlar ama oldukça pahalı görünüyorlar. Özellikle self-hosted Gerrit ile karşılaştırınca daha da öyle. Bu araçlara da bakıp bakmadığınızı merak ediyorum
    • Merge Request Dependencies ve Squash+Merge birleştirme stratejisi ayarlanmış GitLab hakkında ne düşündüğünü merak ediyorum
      Eskiden MR serisi desenini oldukça kolay kurduğumu hatırlıyorum. 3 MR merge edilince, her MR için tek bir squash commit’i olan 3 merge commit oluşuyordu. MR’ın commit geçmişinden bağımsızdı
      Ödünleşim, inceleme sırasında serinin ön tarafındaki branch değişirse serinin arka tarafındaki branch’e yeniden merge etmek gerekmesiydi
      Yine de inceleme sırasında insanlar commit geçmişini istedikleri gibi düzenleyebiliyordu. Nasıl olsa squash edileceği için fark etmiyordu
      Ancak bunu yapalı uzun zaman oldu ve bugünlerde GitHub’a bağlı yaşadığım için bunu pembe gözlüklerle hatırlıyor olabilirim
  • Review Board [https://www.reviewboard.org] üzerinde 2006'da zaten interdiff'i geliştirmişti. Aslında terimi ben uydurmuş ya da ona bağımsız olarak ulaşmış olabilirim
    Hâlâ ürünün ve kod inceleme sürecinin en sevdiğim yanlarından biri; insanların GitHub gibi şeylere geçerken en çok özlediklerini söyledikleri özelliklerden biri olduğunu da sık sık duyuyorum
    fix-it commit'leri bana hiçbir zaman düzgün bir alternatif gibi gelmedi
    Birincisi, üstteki değişikliğin commit serisine nasıl yansıdığını göstermiyor
    İkincisi, geçici de olsa commit grafiğini bozuyor ve incelemeyi zorlaştırıyor. İncelemeyi baştan beri takip eden biri, fix-it commit'inin düzelttiği kodu zaten okumuş olabilir; ama sonradan katılan biri, o kodun ne yapmaya çalıştığı veya yapısının nasıl olduğu konusunda kötü bir ilk izlenimle başlayabilir
    Üçüncüsü, herkes Git ya da birden fazla commit'i yönetebilen sürüm kontrol sistemleri kullanmıyor. Oyun geliştirmede Perforce, çip üreticilerinde Keysight SOS gibi özel sürüm kontrol sistemlerinin kullanıldığı çok oluyor. Böyle yerlerde fix-it commit'inin kendisi bile bir seçenek değil
    Doğru interdiff desteğine sahip bir kod inceleme sistemi varsa, bir incelemeci ilk yayımlanan inceleme isteğinden itibaren tüm güncellemeleri takip edip yalnızca değişenleri görebilir; başka bir incelemeci ise doğrudan en güncel tam değişikliğe girip fix-it serisiyle uğraşmak zorunda kalmaz. Üstelik bu, sürüm kontrol sisteminden bağımsız olarak mümkün olur
    Doğru yapılırsa, birden çok commit'ten oluşan değişikliklerle de birlikte var olabilir
    Örneğin küçük bir projeyi incelemeyi kolaylaştırmak için API handler'ı, frontend UI ve dokümantasyon olmak üzere birkaç commit'e böldüğünüzü; commit'lerin de birbirleriyle yakından ilişkili olduğu için tek bir inceleme isteği olarak gönderilmesinin uygun olduğuna karar verdiğinizi düşünebilirsiniz. Birbirleriyle daha az ilgili olsalardı, bağımlılık zinciri şeklinde birden çok inceleme isteği oluşturmak muhtemelen ideal olurdu
    İnceleme geri bildirimine göre bu commit'lerden biri veya hepsi üzerinde bir dizi değişiklik yapabilirsiniz. İnsanlar güncellemeyi incelerken fix-it commit'lerini ve o değişikliği zihinlerinde karşılık gelen özgün değişiklikle eşlemek zorunda kalmadan, her bölümün nasıl evrildiğini görebilseler iyi olur
    Bu yüzden interdiff gerçekten harika. Küçük commit'ler çok olsun ya da büyük commit'ler olsun, tek commit'lik inceleme isteği olsun ya da çok commit'li olsun, daha fazla insanın kullanması gerekiyor

    • Gerçekten müthiş. Aslında bu yazının 2. bölümünde, bizi bu tür araçlara getiren tarihsel ve politik bağlamı ele almayı planlıyorum
      2013 civarında Glasgow Haskell Compiler'ı şakayla karışık “bug raporlayıcıda .patch dosyası okuma” yönteminden Phabricator kullanımına taşıdık. Bunun birkaç nedeni vardı ama o dönemde sebep stacked diff değildi. Çünkü GitHub inceleme için o kadar kötüydü ki side-by-side diff bile yoktu. Sırf bu nedenle bile tamamen konu dışıydı; başka nedenler de vardı
      Ama bir ekibi kod inceleme aracına taşıdığım ilk sefer bu değildi. 2009'daki ilk işimde, Houston'da bir odada toplanmış çok küçük ve sıkı bağlı bir mühendis ekibindeydim; kodumu başkalarına inceletmenin ve onların yazdıklarını okumanın kod tabanını daha iyi anlamamı sağlayacağını düşünmüştüm
      Bu yüzden işe girdikten sonraki ilk birkaç ay boyunca yöneticimin başının etini yiyip ReviewBoard kurdurttum; herkes de gerçekten sevdi
      Yani RB'ye teşekkürler demek istiyorum. Hâlâ ara sıra güzel bir anı olarak aklıma gelir. Onun sayesinde kod inceleme neredeyse ilk günden itibaren kariyerimin çok büyük bir parçası oldu ve bugün hâlâ daha fazlasını yapabileceğimizi düşünüyorum
  • Genel olarak kod incelemeyi merkeze alan ve rebase odaklı Gerrit gibi sistemlerde kodun çok daha kolay incelendiğini hissettim
    En iyi yanlarından biri, birden çok patch'i üst üste koymayı yerleşik olarak desteklemesi; bu da insanların daha küçük ve incelenmesi daha kolay patch'ler hazırlamasını sağlıyor
    GitHub'ın kod incelemesi kötü bir sonradan eklenmiş özellik gibi hissettiriyor: forum thread'i gibi görünen, yer israfı yapan UI ve rebase'in ötesini takip edememesi gibi şeyler

    • Gerrit'te commit stack'i push ederken eksik bulduğum bir şey var. Tek tek commit'ler değil, stack'in tamamı hakkında konuşulacak merkezi bir yer yok
      Bu tür “büyük resim” niteliğinde ama yine de teknik tartışmalar çok sık issue tracker'da yaşanıyor. Ama nereye konması gerektiğini de bilmiyorum. Bu stack fazla geçici ve bir sonraki push'ta tamamen değişebilir
  • Bu stratejiyi savunanları birkaç kez duydum ama ikna olmadım. Üzerinde çalıştığım projelerin çoğunda feature branch tek bir commit’e squash edilip merge ediliyor, branch geçmişi de siliniyor
    Yazarın anlattığı türden bir durum olsaydı, refactoring’i, yeni API’yi ve güncellemeyi basitçe 3 commit olarak oluştururdum
    Benim için kesinlikle iyi bir pratik olan şey uzun ömürlü branch’lerden kaçınmak. Bu tür çok aşamalı commit senaryoları genelde oradan çıkıyor. Yani birinin bir özellik üzerinde günlerce, hatta bazen haftalarca çalışıp sonra hepsini tek seferde ortaya atmak istemesi durumu
    Ben her gün, hatta günde birkaç kez main’e taşımayı çok daha fazla tercih ederim. Bunu yapmanın bir yolu, devam eden commit’lerin de sorunsuzca dahil edilebilmesi için feature flag kullanmak. Sistem düzgün yapılandırılmışsa, geliştirme ve staging ortamlarında açıp test edebilme avantajı da var. Blue/green dağıtıma da bir adım mesafede
    Büyük commit’leri daha kolay review etmenin bir yolunu istemiyorum. Ekibi küçük değişiklikleri erken ve sık commit etmeye zorlamak istiyorum. Herkesin buna katılmadığını anlıyorum

    • stacked diff’i tercih edenler, boyutundan bağımsız olarak değişiklikleri daha hızlı entegre etmeyi kolaylaştırdığını söylüyor
      Bunun nedenlerinden biri, GitHub PR’larından farklı olarak stack’in yalnızca bir kısmının uygulanabilmesi. Yazıdaki örnek üzerinden bakarsak, “küçük refactoring” diff’i hazırsa, “yeni API” ve “API kullanıcılarının migration’ı” diff’lerini birlikte almadan önce onu içeri alabilirsiniz
      Branch yerine commit merkezli düşününce, uzun ömürlü branch’lere kıyasla toplam commit’lerin daha küçük olması gibi bir etkisi oluyor
    • feature branch’i tek bir commit’e squash edip branch geçmişini silmek korkunç
      Bunu yapınca git blame ve git bisect fiilen işe yaramaz hale geliyor
      Bir regresyon varsa git bisect bunu tek bir patch’e kadar daraltabilir. Bu yüzden belirli bir özellik için git geçmişinde 8000 satırlık tek bir patch yerine 160 satırlık 50 patch olması daha iyidir
      Bir kod satırı şüpheli görünüyorsa, git blame ya da art arda çalıştırılan git blame komutlarının beni 8000 satırlık bir commit’e değil, ayrıntılı commit mesajı olan 160 satırlık bir commit’e götürmesini isterim
      Orijinal commit’lerin sırası da korunmalı. Yıllar sonra yalnızca tek tek commit mesajlarını sırayla okumak bile özgün tasarımı anlamakta çok yardımcı olabilir. Elbette orijinal patch set’i bağımlılık sırasına göre düzenlenmiş olmalı, her aşamada derlenebilmeli vb.; yani özellik implementasyonunun üstünde ayrı bir geliştirme aşaması gerekir. Kod mantıksal adımlar halinde sunulmalı
  • İlginç. İş yerinde PR’ları yazarın commit’leri kullandığı şekilde kullanıyoruz ve en sonunda gerçekten squash-and-merge yapıyoruz
    Ama bu yöntemde öndeki PR’ı her değiştirdiğinizde arkadaki PR’ları rebase etmeniz gerekiyor. Oldukça zahmetli; “force-push yasak” kuralına da takılıyor, mühendislerin öğrenmesi uzun sürüyor ve GitHub UI’daki mevcut code review yorumlarını bozma eğiliminde. Yine de iki üç PR için fena çalışmıyor
    Bizim akışımızda commit’ler iş biriminden çok kayıt noktalarına benziyor
    stash’i de çok kullanıyoruz, Emacs’in undo-tree-mode’unu da. Böylece kaynak kod geçmişini izlemek için dört yöntem oluyor; kulağa tekrar gibi geliyor ama pratikte gayet iyi işliyor
    Git’te bunu yönetmenin kullanılabilirliği oldukça kötü. Phabricator daha iyiydi ama yine de gereksiz yere zordu. Belki yeni bir sürüm kontrol aracı commit ve branch’ten daha üst düzey kavramları birinci sınıf olarak destekleyebilir; belki de bu onu kullanmayı daha da kötü hale getirir

    • Commit’leri PR gibi kullanıyorsunuz. Bu yüzden PR bağımlılıkları işi karmaşıklaştırıyor
      Git’ten daha iyi bir araç olsa iyi olur muydu? Elbette ben de daha az kusurlu ve daha kullanıcı dostu bir araç isterim. Ama geçici bir çözüm olarak commit’leri commit gibi ele almaya ne dersiniz? İşi kendi kendinize zorlaştırmayın
      GitHub’ın insanlara PR gözlüğü taktırmadaki sorumluluğunun ne kadar büyük olduğunu merak ediyorum
    • jj, sapling, mercuriala bakmanız iyi olur
  • Blog yazısı güzeldi; code review’un nasıl çalışması gerektiğini gerçekten düşünen insanları görmek sevindirici
    Farklı artı ve eksileri olan dört code review sistemini epey kullandım: Critique(Google içi), Gerrit(Google’da kullandık ama dışarıdakiyle aynı), GitHub ve kendi yaptığım CodeApprove
    Critique açık ara en iyisiydi, ama bu Google’ın monorepo’suna, kendi sürüm kontrol sistemine ve custom lint/test araçlarına mükemmel şekilde uyarlandığı için mümkündü. CodeApprove, bu avantajları mümkün olduğunca GitHub’a taşımak için tasarlandı ama pratikte ona yaklaşmak zor
    Gerrit reviewer deneyimi açısından ikinci en iyisiydi, ama author olarak her zaman hoşlanmadım. Doğru yöntemden çok yanlış yapma yolu varmış gibi görünüyordu ve UI da özellikle güzel değil
    GitHub author için çok dostça ve bizim düşündüğümüz şekilde çalışıyor. Kod yazıyorsunuz, feedback alıyorsunuz, daha fazla kod yazıyorsunuz. PR sonunda squash and merge yaparsanız yazarın bahsettiği geçmiş sorunu olmaz
    Ama reviewer’lar ya da ekip için pek dostça değil. Artımlı diff vurgulanmıyor, diff ve konuşma farklı sekmelerde, force push ve rebase geçmişi yok ediyor. Yorumlar “outdated” diye kayboluyor, diff penceresi dışındaki dosyalara yorum bırakamıyorsunuz, büyük dosyalar varsayılan olarak gizleniyor ve daha pek çok sorun var. GitHub’ın bunu pek umursamadığı açık; belki de benim bilmediğim bir şey biliyorlardır
    Sonuçta en sinir bozucu olan, birçok ekibin sürüm kontrol platformuna gömülü code review aracını olduğu gibi kabul etmesi. Dizüstü bilgisayarda varsayılan gelen IDE’yi aynen kullanmak gibi. Bugün çok daha iyi seçenekler var. CodeApprove dışında sevdiğim araçlar GitContext, Reviewable, Graphite; ayrıca en az altı tane daha harika seçenek sayabilirim. Varsayılanı kabul etmemek gerekir

    • GitHub’ın reviewer’lara ve ekiplere dostça olmaması sorun
      Reviewer’lar ve maintainer’lar contributor’lardan çok daha kıt. İş akışı ve UI’ın review throughput’unu optimize etmesi gerektiğini düşünüyorum
      Bahsedilen diğer üç aracı hiç kullanmadım; bu yüzden iddiam genel bir değerlendirme