15%

Tüm Hosting Hizmetlerinde %15 indirim

Becerilerini test et ve herhangi bir hosting planında İndirim kazan

Kodu kullanın:

Skills
Başlayın
22.10.2024

Git Reset vs. Git Checkout vs. Git Revert: Eksiksiz Teknik Kılavuz

git reset, git checkout ve git revert arasındaki farkı anlamak, sürüm kontrolüyle çalışan her geliştirici için temel bir gerekliliktir. Kısaca: git reset, HEAD işaretçisini taşıyarak geçmişi yeniden yazar; git checkout, geçmişi değiştirmeden dallar, commit’ler veya dosyalar arasında gezinir; git revert ise yeni bir ters commit oluşturarak bir commit’i geri alır ve geçmişi olduğu gibi bırakır. Yanlış komutu seçmek — özellikle paylaşılan bir dalda — ekibinizin commit geçmişini bozabilir veya geri alınamaz veri kaybına yol açabilir.

Bu kılavuz, yüzeysel sözdiziminin ötesine geçerek Git’in iç mekaniklerini, her işlemden sonra çalışma ağacınızın ve dizininizin tam durumunu ve her komutun doğru (ya da feci biçimde yanlış) seçim olduğu gerçek dünya senaryolarını açıklamaktadır.

Git Durumu Nasıl Yönetir: Üç Ağaç

Komutları karşılaştırmadan önce, Git’in durumu nasıl takip ettiğine dair sağlam bir zihinsel model oluşturmanız gerekir. Git, üç farklı katmanda çalışır:

  • Çalışma dizini — diskte gördüğünüz ve düzenlediğiniz dosyalar.
  • Hazırlama alanı (index) — bir sonraki commit’e girecek olanların anlık görüntüsü.
  • Commit geçmişi (HEAD).git/ içinde depolanan değiştirilemez commit nesnelerinin zinciri.

Git’teki her geri alma komutu bu katmanlardan birini veya birkaçını hedef alır. reset, checkout ve revert arasındaki karışıklık, neredeyse her zaman belirli bir komutun hangi katmanlara dokunduğunun bilinmemesinden kaynaklanır.

git reset: Yerel Geçmişi Yeniden Yazma

git reset, mevcut dalın HEAD işaretçisini belirtilen bir commit’e taşır. Geçirdiğiniz mod bayrağına bağlı olarak, index’i ve çalışma dizinini de güncelleyebilir. Bu bir geçmişi yeniden yazma işlemidir ve --hard ile kullanıldığında yıkıcı olarak değerlendirilmelidir.

Reset Modlarının Açıklaması

git reset --soft <commit>   # Move HEAD only; index and working tree unchanged
git reset --mixed <commit>  # Move HEAD + reset index; working tree unchanged (default)
git reset --hard <commit>   # Move HEAD + reset index + reset working tree
ModHEAD TaşınırIndex SıfırlanırÇalışma Ağacı SıfırlanırDeğişiklikler Korunur
--softEvetHayırHayırHazırlanmış ve hazırlanmamış
--mixedEvetEvetHayırYalnızca hazırlanmamış
--hardEvetEvetEvetHiçbiri — kalıcı olarak kaybolur

Pratik Kullanım Senaryoları

Push öncesinde commit’leri birleştirme. Henüz push edilmemiş üç dağınık çalışma-devam commit’iniz varsa, git reset --soft HEAD~3 bunları index’e geri çökerek tek bir temiz commit olarak yeniden commit etmenizi sağlar.

Yanlışlıkla eklenen bir dosyanın hazırlama alanından çıkarılması. git reset HEAD <file> (veya commit referansı olmadan git reset) çalıştırmak, çalışma dizinine dokunmadan bir dosyayı index’ten kaldırır — Git 2.23+’daki git restore --staged <file> ile aynı etkiye sahiptir.

Bozuk bir yerel merge’den kurtarma. git reset --hard ORIG_HEAD, bir merge’den hemen önce var olan durumu geri yükler; çünkü Git, merge öncesi HEAD‘ı otomatik olarak ORIG_HEAD‘a yazar.

Kritik Tuzak: Reset Sonrasında Push Yapmak

Zaten bir uzak sunucuya push edilmiş bir dalı sıfırlayıp ardından zorla push yaparsanız, yerel dalı o uzak sunucuyu takip eden her ortak, ayrışmış bir geçmişe sahip olur. Bu, ekip ortamlarında commit kaybının en yaygın nedenlerinden biridir. Açık bir ekip koordinasyonu olmadan paylaşılan bir dalda git reset ve ardından git push --force çalıştırmayın.

# Dangerous on shared branches — use only on private/local branches
git reset --hard HEAD~2
git push --force origin feature/my-branch

git checkout: Geçmişi Değiştirmeden Gezinme

git checkout, çalışma ağacını bir dal, belirli bir commit veya tek bir dosyayla eşleşecek şekilde değiştiren çok amaçlı bir komuttur. Commit geçmişini değiştirmez. Git 2.23 ve sonrasında sorumlulukları git switch (dallar için) ve git restore (dosyalar için) olarak ikiye ayrılmıştır; ancak git checkout tamamen işlevsel olmaya devam etmekte ve üretim ortamlarında hâlâ yaygın biçimde kullanılmaktadır.

Sözdizimi Referansı

git checkout <branch_name>          # Switch to an existing branch
git checkout -b <new_branch>        # Create and switch to a new branch
git checkout <commit_hash>          # Enter detached HEAD state at a specific commit
git checkout -- <file_name>         # Discard working directory changes to a file
git checkout <commit_hash> -- <file> # Restore a single file from a specific commit

Detached HEAD Durumu: Gerçekte Ne Anlama Gelir

git checkout <commit_hash> çalıştırdığınızda Git, HEAD‘ı bir dal referansı yerine doğrudan bir commit nesnesine işaret edecek şekilde taşır. Buna detached HEAD durumu denir. Bu durumda yaptığınız commit’ler hiçbir daldan erişilemez — yetim kalırlar ve onları yakalamak için bir dal oluşturmazsanız Git tarafından sonunda çöp toplanır.

git checkout 4f7a2c1          # HEAD now points directly to commit 4f7a2c1
git checkout -b hotfix/patch  # Rescue those commits by creating a branch

Gerçek dünyada sık karşılaşılan bir senaryo: bir geliştirici bir gerilemeyi test etmek için eski bir commit’i kontrol eder, yanlışlıkla bir düzeltme yapar, commit’ler ve ardından main‘a geri döner — düzeltme hiçbir zaman bir dala bağlanmadığı için tamamen kaybolur.

Geçmişten Tek Bir Dosyayı Geri Yükleme

git checkout‘un en az kullanılan biçimlerinden biri, hedefli dosya geri yüklemedir:

git checkout HEAD~3 -- src/config/database.php

Bu, database.php‘ı üç commit önceki haliyle doğrudan index’inize ve çalışma dizininize çeker; başka hiçbir dosyaya dokunmaz ve HEAD‘ı taşımaz. Tam bir dal geçişinin cerrahi eşdeğeridir.

git revert: Paylaşılan Geçmiş için Güvenli Geri Alma

git revert, belirtilen bir commit’in ters farkını uygulayan yeni bir commit oluşturur. Orijinal commit, geçmişte dokunulmadan kalır. Bu, zaten paylaşılan bir uzak dala push edilmiş commit’ler için tek güvenli geri alma mekanizmasıdır; çünkü geçmişi yeniden yazmaz — onu genişletir.

Sözdizimi Referansı

git revert HEAD                  # Revert the most recent commit
git revert <commit_hash>         # Revert a specific commit by hash
git revert HEAD~3..HEAD          # Revert a range of commits (creates multiple revert commits)
git revert -n <commit_hash>      # Stage the revert without committing (--no-commit)

–no-commit Bayrağı: Geri Almaları Toplu Hale Getirme

Birden fazla commit’i geri alırken, her orijinal commit için bir geri alma commit’i oluşturmak günlüğü kirletebilir. -n (veya --no-commit) bayrağı, tüm geri almaları commit yapmadan hazırlar ve bunları tek bir geri alma commit’inde bir araya getirmenizi sağlar:

git revert -n HEAD~4..HEAD
git commit -m "Revert: roll back broken authentication refactor"

Merge Commit Geri Almaları Ekstra Dikkat Gerektirir

Bir merge commit’ini geri almak, ana hat ebeveynini -m bayrağıyla belirtmeyi gerektirir; çünkü Git’in merge’in hangi tarafını “doğru” geçmiş olarak ele alacağını bilmesi gerekir:

git revert -m 1 <merge_commit_hash>

Burada -m 1, birinci ebeveyni (genellikle merge ettiğiniz dal) ana hat olarak belirler. Bu bayrağı bir merge commit’inde atlamak Git’in hata vermesine neden olur. Bu, CI/CD pipeline’larında hatalı bir sürüm merge’ini geri alırken sık karşılaşılan bir engel noktasıdır.

Yan Yana Karşılaştırma: Reset – Checkout – Revert

Kriter`git reset``git checkout``git revert`
Commit geçmişini değiştirirEvetHayırHayır (üzerine ekler)
Çalışma dizinini etkiler--hard veya --mixed ileEvetEvet (yeni commit aracılığıyla)
Hazırlama alanını (index) etkilerEvet (--soft hariç)Yalnızca dosya formuylaHayır
Paylaşılan/uzak dallarda güvenliHayırEvet (salt okunur)Evet
Yeni bir commit oluştururHayırHayırEvet
Geri alınabilirKısmen (ORIG_HEAD aracılığıyla)EvetEvet
Merge commit’lerini işlerHayırEvet (gezinme)Evet (-m ile)
Git 2.23+ modern eşdeğeriAynıgit switch / git restoreAynı

Her Komutu Ne Zaman Kullanmalı: Karar Matrisi

git reset şu durumlarda kullanın:

  • Yerel, push edilmemiş bir dalda çalışıyorsunuz ve commit’leri temizlemek, birleştirmek veya atmak istiyorsunuz.
  • Bir commit öncesinde dosyaların hazırlama alanından çıkarılması gerekiyor.
  • Paylaşılmamış yerel bir merge’i geri almak istiyorsunuz.
  • Bir özellik dalında tek geliştiricisiniz ve pull request açmadan önce geçmişini yeniden yazmak istiyorsunuz.

git checkout şu durumlarda kullanın:

  • Aktif geliştirme sırasında dallar arasında geçiş yapmanız gerekiyor.
  • Hiçbir şeyi değiştirmeden geçmişteki bir commit’teki depo durumunu incelemek istiyorsunuz.
  • Belirli bir commit’teki durumuna tek bir dosyayı geri yüklemeniz gerekiyor.
  • Geçmişte belirli bir noktadan yeni bir dal oluşturuyorsunuz.

git revert şu durumlarda kullanın:

  • Bir commit zaten uzak veya paylaşılan bir dala push edilmiş.
  • Bir ekipte çalışıyorsunuz ve şeffaf, denetlenebilir bir geçmiş sürdürmeniz gerekiyor.
  • En son olmayan belirli bir commit’i geri almanız gerekiyor (doğrusal olmayan geri alma).
  • Projeniz, geçmiş silmenin yasak olduğu uyumluluk veya denetim izleri gerektiriyor.

Gelişmiş Senaryo: git reset –hard’dan Kurtarma

Yanlışlıkla git reset --hard çalıştırıp commit’leri kaybettiyseniz, bunlar hemen kaybolmuş değildir. Git’in reflog‘u, sert bir sıfırlamadan sonra bile HEAD‘ın işaret ettiği her konumu kaydeder:

git reflog
# Output example:
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# 7e8f9a0 HEAD@{1}: commit: Add payment gateway integration
# ...

git reset --hard HEAD@{1}   # Restore to the commit before the accidental reset

Reflog girişleri varsayılan olarak 90 gün sonra sona erer (gc.reflogExpire), dolayısıyla bu kurtarma penceresi sonsuz değildir. Gitea veya GitLab gibi kendi barındırdığı bir Git servisi çalıştıran bir üretim sunucusunda veya VPS Hosting ortamında, tam olarak bu süre sonu nedeniyle .git dizininizin düzenli yedekleme rutinlerine dahil edildiğinden emin olmalısınız.

Git Altyapınızı Barındırma

Kendi barındırdığınız bir Git sunucusu çalıştırmak — ister GitLab CE, ister Gitea, ister Gogs olsun — güvenilir depolama G/Ç’si ve tutarlı çalışma süresi gerektirir. Tek bir bozuk paket dosyası veya bir git gc döngüsü sırasında kesintiye uğrayan bir push, depo bütünlüğüne zarar verebilir. Birden fazla depoyu yöneten ekipler için, Dedicated Server yalıtılmış kaynaklar, Git’in core.packedGitWindowSize ve pack.threads ayarlarını ince ayarlamak için tam root erişimi ve büyük monorepo’lar için gereken NVMe verimi sağlar.

Git hook’larını, CI betiklerini ve dağıtım pipeline’larını çalıştırmak için temiz bir Linux ortamına ihtiyaç duyan küçük ekipler veya bireysel geliştiriciler için, cPanel ile VPS, tam SSH erişiminin yanı sıra yönetilen bir kontrol düzlemi sunar — Git sunucu tarafı hook’larını ve erişim kontrollerini yapılandırma esnekliğini korurken manuel sunucu yönetiminin yükünü ortadan kaldırır.

İş akışınız git push tarafından tetiklenen otomatik dağıtımları içeriyorsa, sunucunuzu geçerli bir SSL Sertifikası ile güvence altına almak zorunludur — hem webhook yüklerini şifrelemek hem de sertifika doğrulamasını devre dışı bırakmadan HTTPS tabanlı Git uzak sunucularını doğrulamak için.

Temel Teknik Çıkarımlar

  • git reset --hard, reflog süresi dolmuşsa üç komut arasında kalıcı, kurtarılamaz veri kaybına yol açabilecek tek komuttur.
  • git revert, zorla push gerektirmeden bir git push‘dan sonra kullanılması güvenli olan tek komuttur.
  • git checkout <hash>‘dan kaynaklanan detached HEAD durumu commit’leri silmez — ancak bu durumda yapılan yeni commit’ler, hemen git checkout -b <new_branch> çalıştırmazsanız yetim kalır.
  • git revert üzerindeki -n bayrağı, aynı anda birden fazla commit’i geri alırken temiz bir günlük tutmak için kritik öneme sahiptir.
  • Git 2.23+, netlik için git checkout‘u git switch ve git restore olarak ikiye ayırır — orijinal komutu anlamak, her iki modern alternatifi de hemen sezgisel hale getirir.
  • Herhangi bir geri alma işlemi çalıştırmadan önce git status ve git log --oneline -5 ile mevcut dalınızı doğrulayın.
  • Paylaşılan altyapıda, sunucu düzeyinde main ve release dallarında git push --force‘ı engellemek için dal koruma kurallarını uygulayın (GitHub, GitLab ve Gitea’nın tümü bunu destekler).

Sıkça Sorulan Sorular

git reset --soft ile git reset --mixed arasındaki fark nedir?

Her ikisi de HEAD‘ı belirtilen commit’e taşır; ancak --soft değişikliklerinizi index’te hazırlanmış halde bırakırken, --mixed (varsayılan) index’i de temizler ve değişiklikleri yalnızca çalışma dizininde bırakır. Her ikisi de diskteki dosyalara dokunmaz.

git reset --hard‘dan sonra commit’leri kurtarabilir miyim?

Evet, reflog süre sonu penceresi içinde (varsayılan olarak 90 gün). Kayıp durumun commit hash’ini bulmak için git reflog çalıştırın, ardından geri yüklemek için git reset --hard <hash> veya git checkout -b recovery <hash> çalıştırın.

Bir merge commit’inde git revert neden -m bayrağını gerektirir?

Bir merge commit’inin iki ebeveyni vardır. Git, ana hattı belirtmeden hangi ebeveynin farkını tersine çevireceğini belirleyemez. -m 1, Git’e birinci ebeveyni gövde olarak ele almasını söyler ve birleştirilen dalın getirdiği değişiklikleri geri alır.

git checkout -- <file> ile git restore <file> aynı şey midir?

İşlevsel olarak evet — her ikisi de bir dosyadaki hazırlanmamış çalışma dizini değişikliklerini index’ten geri yükleyerek atar. git restore, Git 2.23’te daha az belirsiz bir alternatif olarak tanıtılmıştır; ancak git checkout -- <file> tüm Git sürümlerinde aynı sonuçları üretir.

Bir dalda git reset‘ı kesinlikle hiçbir zaman kullanmamalı mıyım?

Diğer geliştiricilerin zaten klonladığı veya çektiği herhangi bir dalda git reset‘ı (özellikle --hard veya --mixed ile) asla kullanmayın. Bunu yapmak, yerel geçmişlerini uzak sunucudan ayırır; her ortak, zorla sıfırlama veya yeniden klonlama yapmak zorunda kalır — ve yalnızca kendi makinelerinde bulunan commit’lerin sessizce kaybolması riskini doğurur.

15%

Tüm Hosting Hizmetlerinde %15 indirim

Becerilerini test et ve herhangi bir hosting planında İndirim kazan

Kodu kullanın:

Skills
Başlayın