Skip to content

Bölüm 6 / 12

İleri Git

rebase, cherry-pick, stash, reset/revert, reflog, bisect.

17 dakikalık okuma

1. dersin çerçevesi bu derste sınanır: değişmez nesneler, hareketli ref'ler. Buradaki her komut — rebase, cherry-pick, reset, revert — ya grafa yeni düğüm ekler ya bir ref'i taşır; ikisini ayırt edebildiğin sürece hiçbiri korkutucu değildir. Ders, hattın en çok sorulan kararıyla açılır: rebase mi merge mi ve "yayımlanmış geçmiş rebase edilmez" altın kuralı. Ardından geçmişi kurgulama araçları (interactive rebase, cherry-pick, stash), geri alma ikilisi (reset ↔ revert) ve güvenlik ağı (reflog). Son iki bölüm iki senedi öder: 15-09'un "zaman ekseninde ikiye bölme"si bisect olarak, 13-10 ve 14-09'un "geçmişe girmiş sır" sorusu filter-repo ile — ve değişmeyen hükümle: push'lanmış sır rotasyondan başka çözüm tanımaz.

01Ne öğreneceksin

  • Rebase ↔ merge: rebase'in gerçekte ne yaptığı; altın kural; hangi durumda hangisi
  • Interactive rebase: pick/reword/squash/fixup/drop, autosquash, her commit'i test eden exec
  • Cherry-pick: hotfix taşıma, -x izi, çift commit riski
  • Stash: seçenekler, tuzaklar ve stash yerine ne zaman worktree
  • Reset üçlüsü (soft/mixed/hard) ↔ revert; "paylaşılanda revert, yerelde reset"
  • Reflog: güvenlik ağı; süre sınırları; nelerin gerçekten kaybolduğu
  • Bisect: ikili aramayı geçmişe uygulamak; run ile test paketiyle otomasyon
  • Geçmişten sır temizleme: filter-repo; sıralama; "rotasyon önce" hükmü

02Rebase ↔ merge ve altın kural

Özellik dalın main'den ayrıldı, main ilerledi. İki yol var. Merge (3. ders) iki ucu iki ebeveynli bir commit'te birleştirir; geçmiş neyin ne zaman olduğunu olduğu gibi anlatır, dallanma grafta görünür. Rebase ise dalının commit'lerini alır, main'in ucundan başlayarak yeniden oynatır:

önce:   A ── B ── C ── F      (main)
                   └── D ── E  (ozellik)
$ git switch ozellik && git rebase main
sonra:  A ── B ── C ── F      (main)
                        └── D' ── E'  (ozellik)

D' ve E', D ve E'nin yeni commit'leridir: aynı değişiklik, farklı ebeveyn, dolayısıyla farklı özet (1. ders: ebeveyn commit'in içindedir). D ve E hâlâ depodadır — erişilemez ve reflog'da. Sonuç düz bir çizgidir; merge sonrası main'e fast-forward ile girer, geçmiş sanki hep sırayla yazılmış gibi okunur.

MergeRebase
GeçmişOlduğu gibi; dallanma görünürDüz; "ne zaman ayrıldı" bilgisi kaybolur
Commit'lerDeğişmez; + merge commitYeniden yaratılır (yeni özetler)
ÇatışmaBir kez, merge anındaCommit commit; aynı çatışma tekrarlayabilir (rerere, 5. ders)
Bisect / blameMerge commit'leri gürültüTemiz, doğrusal
Paylaşılan daldaGüvenliYasak

Altın kural: yayımlanmış geçmiş rebase edilmez. Neden: rebase commit'leri yeniden yarattı; o commit'leri çekmiş her ekip arkadaşının elinde eski D ve E var. Bir sonraki pull'da Git eski ve yeni commit'leri farklı görür, ikisini birleştirmeye çalışır — aynı değişiklik iki kez, çatışma ve "çift commit"li bir geçmiş. Kuralın kesin sınırı: main'i ya da başkasının da commit attığı dalı hiçbir zaman; henüz push etmediğin commit'leri her zaman; yalnız senin çalıştığın özellik dalını PR öncesi --force-with-lease ile (4. ders) — bu, çoğu ekipte kabul edilmiş sözleşmedir, ama sözleşme olduğunu bil.

Karar pratikte şöyle verilir: dalını main'e göre güncellerken rebase (düz geçmiş, tesadüfi merge commit'i yok — 4. dersin pull --rebase'i); bitmiş işi main'e katarken ekip stratejisine göre merge --no-ff, squash ya da rebase-and-fast-forward (7. ders; barındırma platformlarının PR düğmesindeki üç seçenek tam bunlardır). İleri hareket: git rebase --onto main eski-taban ozellik — dalını başka bir dalın üstünden alıp main'e taşımak, "yanlış daldan açtım" hatasının ilacı.

03Interactive rebase: geçmişi kurgulamak

2. ders "yeşilde commit" dedi; gerçek gün "WIP", "typo", "unutulan dosya" commit'leriyle geçer. Bunları PR'a taşımak inceleyenin zamanını çalar. git rebase -i main (ya da HEAD~4), dalındaki commit'leri editörde listeler ve her satır için ne yapılacağını sorar:

pick 3f2a1c0 Son gün kuralını ekle
fixup 9c8d7e6 typo
reword b4e5f60 Sınır testi ekle
squash 1a2b3c4 bir test daha
drop   5d6e7f8 debug satırı
exec   dotnet test --no-build

# pick   = olduğu gibi al      reword = mesajı düzenle
# squash = öncekiyle birleştir (mesajları birleştir)   fixup = birleştir, mesajı at
# edit   = dur, değiştirmeme izin ver   drop = çıkar   exec = komut çalıştır

Satırların sırasını değiştirmek commit'leri yeniden sıralar. Sonuç, PR'da inceleyenin okuyacağı atomik commit dizisidir: "kuralı ekle", "sınır testi ekle". Kıdem aracı exec'tir: her commit'in ardından test koşturmak, "geçmişteki her commit yeşil" garantisini verir — bisect'in (08. bölüm) çalışabilmesinin şartı. Kolaylıklar: git commit --fixup=3f2a1c0 ile düzeltmeyi hangi commit'e ait olduğunu belirterek atarsın, rebase -i --autosquash onu doğru yere kendisi yerleştirir (rebase.autoSquash true ile kalıcı). Üst üste dallanan (stacked) dallarda --update-refs (2.38) alt dalların ref'lerini de taşır. Rebase sırasında çatışma çıkarsa 5. dersin üçlüsü: düzelt, add, rebase --continue; vazgeçersen --abort. Tümü, altın kuralın altında yaşar: yalnız yayımlanmamış commit'lerde.

04Cherry-pick

git cherry-pick 3f2a1c0, tek bir commit'in değişikliğini bulunduğun dala yeni bir commit olarak uygular. Kullanım yerleri gerçektir: üretimde bulunan hatanın düzeltmesini release/1.4 dalına taşımak (hotfix), terk edilen bir daldan tek değerli commit'i kurtarmak. -x seçeneği mesaja "(cherry picked from commit ...)" satırı ekler — kaynağı izlenebilir kılar; başka bir dalda yaşamaya devam edecek commit'ler için her zaman kullanılır. -n commit atmadan yalnız çalışma alanına uygular.

Riski, çift committir: aynı değişiklik artık iki özetle iki dalda yaşar. Dal sonradan bütünüyle main'e merge edilirse Git çoğu kez aynı yamayı tanır (rebase, patch-id eşleşen commit'i atlar); ama çevresindeki kod değiştiyse çatışma çıkar ve geçmiş "bu düzeltme iki kez mi yapıldı" sorusunu üretir. Kural: cherry-pick bir istisna aracıdır; dalın tamamı zaten main'e gidecekse commit'i tek tek taşıma, dalı birleştir. git cherry main ozellik (ya da log --cherry-pick --right-only), hangi commit'lerin henüz karşı tarafa uygulanmadığını patch-id ile listeler — sürüm dallarını yönetenlerin denetim aracı.

05Stash: tezgâhı geçici boşaltmak

Yarım iş varken acil bir hata düzeltmesi gelir; commit atmak istemezsin, dal değiştirmeyi Git reddeder (3. ders). git stash çalışma alanı ve index'teki değişikliği bir kenara koyar, temiz bir alan bırakır:

git stash push -m "son gün kuralı yarım"   # açıklama yaz; adsız stash birikir
git stash push -u                          # izlenmeyen dosyalar da (varsayılan almaz!)
git stash push --staged                    # yalnız index'tekiler (2.35+)
git stash push -p                          # parça parça seç
git stash list                             # stash@{0}: On main: son gün kuralı yarım
git stash show -p stash@{1}                # içeriğine bak
git stash pop                              # uygula + sil     git stash apply → uygula, tut
git stash branch kurtarma stash@{0}        # stash'i yeni dalda commit'e çevir

Stash, arka planda refs/stash altında saklanan sıradan commit'lerdir (1. dersin modeli); bu yüzden pop çatışırsa Git stash'i silmez, çözümden sonra elle drop edersin. Tuzaklar: (1) varsayılan stash izlenmeyen yeni dosyaları almaz — yeni sınıf dosyan çalışma alanında kalır, sonraki dala "taşınır"; (2) stash listesi bir mezarlık olma eğilimindedir; unutulan stash, unutulmuş iştir — liste çoğu zaman boş olmalı; (3) stash dalla ilişkili değildir, başka dalda pop edilebilir ve çatışır. Alternatifler çoğu kez daha iyidir: kısa bir WIP commit'i atıp sonra reset --soft ya da fixup ile eritmek; ya da git worktree add ../hotfix main — aynı deponun ikinci bir çalışma alanı, ayrı dizinde, ayrı dalda: hiçbir şeyi kenara koymadan yan yana iki iş.

06Reset üçlüsü ↔ revert

git reset <hedef>, bulunduğun dalın ref'ini hedef commit'e taşır; üç kip, 1. dersin üç bölgesinden hangilerinin hedefe uydurulacağını seçer:

KipDal ref'iIndexÇalışma alanıTipik kullanım
--softtaşınırkalırkalırSon üç commit'i tek commit'e birleştirmek: reset --soft HEAD~3 + commit
--mixed (varsayılan)taşınırhedefe uyarkalırSon commit'i "geri aç": değişiklikler unstaged olarak durur
--hardtaşınırhedefe uyarhedefe uyarHer şeyi at, hedefe dön — commit edilmemiş iş silinir

Tehlikeli olan yalnız --hard'dır ve tehlikesi grafla ilgili değildir: ref'in bıraktığı commit'ler reflog'dadır; silinen şey, hiç commit edilmemiş çalışma alanı değişikliğidir (1. dersin son kuralı). Reset'ten önce git status temizse hard reset geri alınabilir bir işlemdir. git reset -- dosya (hedefsiz) yalnız index'i düzeltir: unstage, restore --staged'ın eşi. Reset her kipte ref'i geriye taşıdığı için geçmişi yeniden yazar — 2. dersin sınırı: yalnız yayımlanmamış commit'lerde.

Revert tam tersini yapar: geçmişe dokunmaz, hedef commit'in değişikliğini tersine çeviren yeni bir commit ekler. Ref ileri gider, hiçbir düğüm kaybolmaz, ekip arkadaşının pull'u sorunsuzdur. Merge commit'i revert ederken hangi ebeveynin "ana hat" sayılacağı söylenir: git revert -m 1 <merge> (1 = bulunduğun daldaki ebeveyn). İnce nokta: revert edilmiş bir merge'ü sonradan yeniden birleştirmek işe yaramaz — Git o commit'leri "zaten birleşmiş" sayar; çözüm revert'i revert etmektir. Kural tek cümledir: paylaşılanda revert, yerelde reset. Yazılıda "reset ile revert farkı" bu cümleyle ve tabloyla cevaplanır.

07Reflog: güvenlik ağı

Git, HEAD'in ve her dalın her hareketini yerel bir günlüğe yazar (.git/logs/, 1. dersin turu). git reflog onu gösterir:

$ git reflog
7a1b2c3 HEAD@{0}: reset: moving to HEAD~3
e4f5a6b HEAD@{1}: commit: Sınır testi ekle
d3c2b1a HEAD@{2}: commit: Son gün kuralını ekle
9f8e7d6 HEAD@{3}: rebase (finish): returning to refs/heads/ozellik
$ git reset --hard HEAD@{1}         # yanlış reset'i geri al
$ git branch kurtarma e4f5a6b       # ya da silinen dalı diriltmek

Her "geçmişi bozdum" senaryosunun cevabı buradadır: yanlış reset --hard, kötü giden rebase, -D ile silinen dal, amend ile ezilen commit — hepsi reflog'da bir satırdır ve satırın özetiyle bir dal ya da reset yeterlidir. Sınırlar: reflog yereldir — push edilmez, klonda yoktur, yalnız senin makinenin hafızasıdır; ve sürelidir — erişilebilir girdiler 90, erişilemez olanlar 30 gün sonra gc tarafından temizlenir (gc.reflogExpire, gc.reflogExpireUnreachable). "Git'te kolay kolay veri kaybolmaz" cümlesinin tam hâli budur: commit edilmiş hiçbir şey birkaç hafta boyunca kaybolmaz. Düşürülen stash bile bulunur: git fsck --unreachable | grep commit ile sahipsiz commit'ler listelenir, git stash apply <özet> ile geri gelir.

08Bisect: hatayı zamanda ikiye bölmek

15-09'un senedi. "Geçen ay çalışıyordu, şimdi çalışmıyor; arada 200 commit var." Her commit'i denemek 200 adım; ikili arama 8 adım. Bisect, iyi bilinen bir commit ile kötü bilinen bir commit arasında ortayı seçip sana verir; sen "iyi/kötü" dersin, o yarıyı atar:

git bisect start
git bisect bad                    # şimdiki HEAD bozuk
git bisect good v1.3.0            # bu tag'de çalışıyordu
# Git ortadaki commit'e geçer (detached HEAD, 3. ders); test et
git bisect good                   # ya da: git bisect bad   → yarıya iner, tekrarla
# ... "abc1234 is the first bad commit"
git bisect reset                  # başladığın yere dön

Kıdem hâli otomasyondur: testin varsa (15. hat) döngüyü Git kendisi çevirir:

git bisect start HEAD v1.3.0
git bisect run dotnet test --filter "FullyQualifiedName~SonGunKurali"

run, komutu her adımda çalıştırır: çıkış kodu 0 iyi, 1-127 kötü, 125 "bu commit test edilemez, atla" (derlenmeyen ara commit için betikte exit 125). Elle de bisect skip vardır. Dakikalar içinde suçlu commit ve onun diff'i elindedir — 15-09'un "tek değişkenli deney" ilkesi geçmişe uygulanmıştır. Bisect'in üç ön şartı, bu hattın iyi alışkanlıklarının getirisidir: atomik commit'ler (suçlu commit küçükse neden bir bakışta görünür), her commit'in derlenmesi (yeşilde commit + exec) ve düz ya da en azından okunur geçmiş. Sığ klonda (4. ders) geçmiş olmadığı için çalışmaz. Performans gerilemesi gibi "iyi/kötü" yerine "eski/yeni" dilinin uyduğu aramalar için --term-old/--term-new vardır.

09Geçmişten sır temizleme

13-10'un hükmünü değiştirmeden yineleyelim: push'lanmış bir sır, artık bir sır değildir. Depoya girmiş bağlantı dizesinin, API anahtarının, sertifikanın tek gerçek çözümü onu iptal edip döndürmektir; geçmişi temizlemek, rotasyonun yerine değil ardından yapılan bir hijyen işidir — çünkü sır zaten her klonda, her CI önbelleğinde ve platform önbelleğinde kopyalanmıştır. Bunu kabul ettikten sonra temizliğin mekaniği:

pip install git-filter-repo                                   # ayrı araç; filter-branch kullanımdan kalktı
git clone --mirror https://git.kurum.gov.tr/basvuru/api.git   # taze, çıplak kopyada çalış
cd api.git
git filter-repo --path config/prod-secrets.json --invert-paths # dosyayı TÜM geçmişten çıkar
git filter-repo --replace-text ../ifadeler.txt                 # ya da: metni her commit'te değiştir
git push --force --all && git push --force --tags               # her ref'i yeniden yaz

1. dersin çerçevesiyle ne olduğu açık: filter-repo, sırrı içeren blob'a bağlı her tree'yi ve o tree'lere bağlı her commit'i yeniden yazar — ilk sızıntıdan bugüne kadarki tüm özetler değişir. Bunun sonuçları, temizliğin neden nadir ve planlı bir işlem olduğunu anlatır:

  • Herkes yeniden klonlar; pull yetmez — eski nesneler yerel depolarda durur ve bir sonraki push onları geri getirebilir. Açık dallar ve PR'lar yeni özetlere göre yeniden kurulur.
  • Platform tarafında eski commit'ler özetle hâlâ erişilebilir olabilir (önbellek, çatallar, PR referansları); GitHub gibi platformlarda kalıcı temizlik için destek talebi gerekir. Bu tek başına, rotasyonun neden birinci adım olduğunu kanıtlar.
  • Yerel depoda kalıntılar reflog'dadır: git reflog expire --expire=now --all && git gc --prune=now ile ancak silinir — ayna klonda çalışmanın nedeni.
  • Sonra kök neden (15-11'in 5 neden'i): tarama neden yakalamadı? 13-10'un commit öncesi kancası ve 14-09'un boru hattı taraması kurulmamışsa sızıntı tekrarlar.

Cümle, sınav için tek satıra iner: "Depoya sızmış sır için ilk iş rotasyon, ikinci iş erişim kayıtlarının incelenmesi, üçüncü iş — gerekiyorsa — filter-repo ile geçmiş temizliği ve tüm ekibin yeniden klonlamasıdır; sırayı tersine çeviren, zaman kaybeder."

10Mini alıştırma — boz, kurtar, bul

Yaklaşık 20 dakika · önceki derslerin deposu

  1. Kurgula. Bir dalda dört commit at: gerçek değişiklik, "typo", "WIP", bir test. git rebase -i main ile typo'yu fixup, WIP'i squash yap, testi reword et; bir exec satırıyla her adımda dotnet build koştur. git log --oneline: temiz iki-üç commit; eski özetlerin reflog'da durduğunu gör.
  2. Rebase ↔ merge. Dalı iki kez main'e taşı: bir kopyada git rebase main, diğerinde git merge main; log --graph çıktılarını yan yana koy. Rebase sonrası özetlerin değiştiğini git log --format=%H ile doğrula.
  3. Boz ve kurtar. git reset --hard HEAD~2. Commit'ler gitti mi? git reflog ile bul, git reset --hard HEAD@{1} ile geri getir. Sonra bir dosyayı commit etmeden değiştir, tekrar hard reset: bu kez reflog'da var mı? Farkı bir cümleyle yaz.
  4. Revert. Bir commit'i git revert et; log'da iki commit'in de durduğunu gör. Bir merge commit'i revert -m 1 ile geri al.
  5. Stash. Yarım değişiklik + izlenmeyen yeni dosya varken git stash; status: yeni dosya hâlâ orada — -u ile tekrar. Başka dala geç, stash pop, geri dön. git worktree add ../yan main ile aynı depoyu ikinci dizinde aç, git worktree list.
  6. Bisect. Küçük bir fonksiyonu olan projede 8-10 commit at; ortalardaki birinde fonksiyonu sessizce boz. Fonksiyonu kontrol eden tek testi yaz (ya da çıkış koduyla bir betik). git bisect start HEAD HEAD~9 ve git bisect run ...; kaç adımda buldu? bisect reset.
  7. Sır temizliği (kuru prova). Depoya sahte bir gizli.txt commit'le, birkaç commit daha at. Deponun bir kopyasında git filter-repo --path gizli.txt --invert-paths çalıştır; log --all -- gizli.txt boş mu? Özetlerin tamamının değiştiğini gör. Sonra sırayı yüksek sesle söyle: gerçek olsaydı ilk iş ne olurdu?

11Kendini sına

Merge ile rebase arasındaki fark nedir? Rebase gerçekte ne yapar ve "yayımlanmış geçmiş rebase edilmez" kuralı neden vardır? Hangi durumda hangisi seçilir?

Merge iki ucu iki ebeveynli bir commit'te birleştirir; commit'ler değişmez, dallanma grafta görünür, çatışma bir kez merge anında çıkar, paylaşılan dalda güvenlidir. Rebase dalın commit'lerini hedef dalın ucundan başlayarak yeniden oynatır: her commit aynı değişiklikle ama farklı ebeveynle yeniden yaratılır, dolayısıyla yeni özet alır; eskiler erişilemez olup reflog'da kalır; sonuç düz bir çizgidir, "ne zaman ayrıldı" bilgisi kaybolur, çatışma commit commit çıkabilir (rerere yardım eder), bisect ve blame temiz çalışır. Altın kural, commit'lerin yeniden yaratılmasından çıkar: rebase edilen commit'leri çekmiş herkesin elinde eski özetler vardır; sonraki pull'da Git eski ve yeni commit'leri farklı görüp birleştirmeye çalışır — aynı değişiklik iki kez, çatışma ve çift commit'li geçmiş. Sınır: main'i ya da başkasının da commit attığı dalı asla; push edilmemiş commit'leri her zaman; yalnız senin çalıştığın özellik dalını PR öncesi --force-with-lease ile — ekip sözleşmesi olarak. Karar: dalı main'e göre güncellerken rebase (düz geçmiş, tesadüfi merge commit'i yok — pull --rebase); bitmiş işi main'e katarken ekip stratejisi (merge --no-ff, squash ya da rebase-fast-forward — PR düğmesinin üç seçeneği). rebase --onto dalı yanlış tabandan doğru tabana taşır.

git reset'in üç kipi neyi etkiler? reset ile revert farkı nedir, hangisi paylaşılan dalda kullanılır? reset --hard'da gerçekten ne kaybolur?

Reset, bulunduğun dalın ref'ini hedef commit'e taşır; kip, üç bölgeden hangilerinin hedefe uydurulacağını seçer: --soft yalnız ref (index ve çalışma alanı kalır — son üç commit'i tek commit'e birleştirmek için); --mixed (varsayılan) ref ve index (değişiklikler unstaged olarak durur — son commit'i geri açmak); --hard ref, index ve çalışma alanı (her şey hedefe döner). Hedefsiz reset -- dosya yalnız unstage eder. Reset ref'i geriye taşıdığı için geçmişi yeniden yazar; yalnız yayımlanmamış commit'lerde kullanılır. Revert geçmişe dokunmaz: hedef commit'in değişikliğini tersine çeviren yeni bir commit ekler; ref ileri gider, hiçbir düğüm kaybolmaz, ekip arkadaşının pull'u sorunsuzdur — bu yüzden paylaşılan dalda revert, yerelde reset. Merge commit'i revert ederken -m 1 ile ana hat ebeveyni seçilir; revert edilmiş merge'ü yeniden birleştirmek işe yaramaz (Git commit'leri birleşmiş sayar), çözüm revert'i revert etmektir. --hard'ın tehlikesi grafla ilgili değildir: ref'in bıraktığı commit'ler reflog'dadır ve geri getirilebilir; gerçekten kaybolan, hiç commit edilmemiş çalışma alanı değişikliğidir — hiçbir nesneye girmediği için reflog bile kurtaramaz. Reset öncesi status temizse hard reset geri alınabilir bir işlemdir.

Reflog nedir, neyi kurtarır, sınırları nelerdir? Stash'in tuzakları ve alternatifleri nelerdir? Cherry-pick ne zaman kullanılır, riski nedir?

Reflog, HEAD'in ve her dalın her hareketinin yerel günlüğüdür (.git/logs): yanlış hard reset, kötü giden rebase, -D ile silinen dal, amend ile ezilen commit — hepsi bir satırdır; satırın özetiyle reset --hard HEAD@{n} ya da branch ad <özet> geri getirir; düşürülen stash bile fsck --unreachable ile bulunup stash apply edilir. Sınırları: yereldir — push edilmez, klonda yoktur; ve sürelidir — erişilebilir girdiler 90, erişilemezler 30 gün sonra gc ile silinir. Yani commit edilmiş hiçbir şey birkaç hafta kaybolmaz; commit edilmemiş olan reflog'a hiç girmez. Stash, çalışma alanı ve index'i refs/stash altında sıradan commit'ler olarak kenara koyar. Tuzakları: varsayılan izlenmeyen dosyaları almaz (-u gerekir); liste mezarlığa döner — unutulan stash unutulmuş iştir; dalla ilişkili değildir, başka dalda pop çatışır; pop çatışırsa stash silinmez, elle drop gerekir. Alternatifler: kısa WIP commit'i atıp sonra soft reset ya da fixup ile eritmek; git worktree add ile aynı deponun ikinci çalışma alanını ayrı dizinde açmak. Cherry-pick tek commit'in değişikliğini yeni commit olarak uygular: hotfix'i sürüm dalına taşımak, terk edilen daldan tek commit kurtarmak; -x kaynağı mesaja yazar. Riski çift commit'tir: aynı değişiklik iki özetle iki dalda; sonraki merge'de çevre değiştiyse çatışma ve "iki kez mi yapıldı" geçmişi. İstisna aracıdır; dalın tamamı gidecekse dal birleştirilir. git cherry uygulanmamış commit'leri patch-id ile listeler.

git bisect nasıl çalışır ve nasıl otomatikleştirilir; hangi alışkanlıklar onu mümkün kılar? Depoya sızmış bir sır için doğru sıra nedir ve geçmiş temizliği neden tek başına yetmez?

Bisect, bilinen iyi ve bilinen kötü commit arasında ikili arama yapar: ortadaki commit'e geçer (detached HEAD), sen iyi/kötü dersin, yarıyı atar; 200 commit 8 adımda daralır ve "first bad commit" ile diff'i elindedir — tek değişkenli deneyin geçmişe uygulanması. bisect run <komut> döngüyü otomatik çevirir: çıkış kodu 0 iyi, 1-127 kötü, 125 "test edilemez, atla" (derlenmeyen ara commit); elle bisect skip; sonunda bisect reset. Ön şartları hattın alışkanlıklarıdır: atomik commit'ler (suçlu küçükse neden görünür), her commit'in derlenmesi (yeşilde commit + interactive rebase'de exec), okunur geçmiş; sığ klonda çalışmaz. Sızmış sır için sıra: (1) sırrı derhal iptal et ve döndür — tek gerçek çözüm; (2) erişim kayıtlarında kötüye kullanım ara; (3) yeni sırrı kasaya koy; (4) gerekiyorsa git filter-repo ile (--path --invert-paths ya da --replace-text; filter-branch kullanımdan kalktı; ayna klonda çalış) geçmişi yeniden yaz, tüm ref'leri zorla push et, reflog'u expire + gc ile temizle; (5) kök neden: tarama neden yakalamadı. Temizlik tek başına yetmez çünkü sır zaten her klonda, CI önbelleğinde ve platform önbelleğinde kopyalanmıştır; eski commit'ler platformda özetle erişilebilir kalabilir; filter-repo tüm özetleri değiştirdiği için herkesin yeniden klonlaması gerekir, pull eski nesneleri geri getirebilir. Push'lanmış sır rotasyondan başka çözüm tanımaz; sırayı tersine çeviren zaman kaybeder.

12Sınav köşesi

Yazılıda nasıl sorulur

(1) git merge ile git rebase arasındaki fark nedir; rebase hangi durumda kullanılmamalıdır? (2) git reset ile git revert farkı nedir? (3) reset --soft, --mixed ve --hard neyi etkiler? (4) git stash ne işe yarar? (5) git cherry-pick nedir, ne zaman kullanılır? (6) Interactive rebase ile neler yapılabilir? (7) git reflog nedir, hangi durumda kullanılır? (8) git bisect nasıl çalışır? (9) Yanlışlıkla silinen bir branch nasıl geri getirilir? (10) Depoya commit edilmiş bir parola nasıl temizlenir; ilk yapılması gereken nedir?

Sözlüde nasıl anlatılır — 2 dakikalık taslak

Düzen: (1) Çerçeve — "Git'te nesneler değişmez, ref'ler hareket eder; ileri komutların hepsi ya yeni düğüm üretir ya ref taşır. Bunu bilince hiçbiri korkutucu değildir." (2) Rebase ↔ merge — "Rebase commit'leri hedefin üstünde yeniden yaratır, düz geçmiş verir; merge dallanmayı korur. Dalımı güncellerken rebase, bitmiş işi main'e katarken ekip stratejisi. Altın kural: yayımlanmış geçmişi rebase etmem; kendi dalımı PR öncesi interactive rebase ile temizler, force-with-lease ile gönderirim." (3) Geri alma — "Paylaşılanda revert, yerelde reset. Hard reset'in tehlikesi commit edilmemiş iştir; commit edilmiş her şey reflog'dadır, birkaç hafta boyunca geri gelir." (4) Araçlar — "Hotfix'i sürüm dalına cherry-pick -x ile taşırım ama istisna olarak; stash yerine çoğu kez WIP commit ya da worktree kullanırım." (5) Kıdem vuruşu — "Regresyonu bisect run ile test paketine buldururum — bu, atomik ve yeşil commit'lerin getirisidir. Depoya sızan sır için ilk iş rotasyondur; filter-repo ile geçmiş temizliği ancak ondan sonra, tüm ekibin yeniden klonlamasıyla yapılır — çünkü push'lanmış sır zaten her klonda ve önbellektedir."