Git'te branch'ler: git branch ile oluşturma, geçiş yapma ve silme
Git'te branch, bir commit'e işaret eden hafif bir göstericidir; HEAD ise şu anda hangi branch'te olduğunuzu gösterir. git branch branch'leri listeler, oluşturur, yeniden adlandırır ve siler; git switch aralarında geçiş yapar; git switch -c ad ise branch'i oluşturup hemen ona geçer.
Git'te branch nedir?
Git'te bir branch projenin kopyası değil, tek bir commit'in hash'ini içeren küçük bir dosyadır. Branch oluşturmak saniyenin kesirleri kadar sürer ve neredeyse hiç yer kaplamaz, çünkü Git hiçbir şeyi çoğaltmaz: tüm branch'ler repository veritabanındaki aynı nesnelere işaret eder. Commit yaptığınızda geçerli branch'in göstericisi yalnızca yeni commit'e kayar.
Bu, branch'lere bakışı değiştirir. Onlardan korkmanıza veya tasarruf etmenize gerek yoktur: her görev, düzeltme veya deney için ayrı bir branch açmak normal bir pratiktir. Deney başarısız olursa branch silinir ve ana geçmiş temiz kalır.
Branch'in bir dosya olduğunu kendi gözlerinizle görebilirsiniz:
$ cat .git/refs/heads/main
8b7d4e2a9f1c0d3e5b6a7c8d9e0f1a2b3c4d5e6f
(Büyük repository'lerde referansların bir kısmı .git/packed-refs içinde paketlenir, bu yüzden dosya olmayabilir — öz değişmez.)
Git'te HEAD: şu anda neredesiniz
HEAD, çalışma dizininize şu anda neyin «çıkarıldığını» gösteren bir göstericidir. Genellikle HEAD bir commit'e değil, bir branch'e işaret eder:
$ cat .git/HEAD
ref: refs/heads/main
Zincir şöyledir: HEAD → main → commit. Yeni bir commit, HEAD'in baktığı commit'i parent olarak alır; ardından Git, HEAD'in işaret ettiği branch'i ilerletir. Commit'lerin geçerli branch'e «düşmesinin» nedeni budur.
Doğrudan bir commit'e veya tag'e geçerseniz (git switch --detach v1.0 veya git checkout 3f2a1c9), HEAD doğrudan commit'e işaret eder. Bu duruma detached HEAD denir. Bu durumda koda bakmak güvenlidir, ancak yeni commit'ler hiçbir branch'e bağlı değildir ve geçiş yaptıktan sonra kolayca kaybolur. Bir şeyler değiştirmeye başladıysanız, tam orada bir branch oluşturun: git switch -c fix-from-old-version.
İfadelerde HEAD'i başlangıç noktası olarak kullanmak pratiktir: HEAD~1 — önceki commit, HEAD~3 — üç commit önce, HEAD^2 — bir merge commit'inin ikinci parent'ı.
Branch'leri görüntüleme: git branch
git branch # yerel branch'ler, geçerli olan * ile işaretli
git branch -v # artı her birindeki son commit
git branch -vv # artı upstream ve geride/önde olma durumu
git branch -r # uzak branch'ler (origin/...)
git branch -a # tüm branch'ler
git branch --show-current # yalnızca geçerli branch'in adı
git branch -vv çıktısı örneği:
feature/login 4c1e2d7 [origin/feature/login: ahead 2] Giriş formu
* main 8b7d4e2 [origin/main] README'yi güncelle
old-spike 1a9b3c0 Önbellek denemesi
Burada feature/login'de gönderilmemiş iki commit olduğu, main'in sunucuyla aynı olduğu ve old-spike'ın sunucuda hiç karşılığı olmadığı görülüyor.
Branch'leri filtrelemek için git branch --merged (geçerli branch'e zaten merge edilmiş — silme adayları), git branch --no-merged (henüz merge edilmemiş) ve git branch --list 'feature/*' (kalıba göre) kullanılır.
Branch nasıl oluşturulur
İki yol vardır. git branch bir branch oluşturur ama sizi geçerli branch'te bırakır:
git branch feature/login # geçerli commit'ten
git branch hotfix v1.2.0 # bir tag'den
git branch review 3f2a1c9 # belirli bir commit'ten
Çoğu zaman branch'i oluşturup hemen ona geçmek gerekir. Bunun için git switch -c (Git 2.23'te geldi) veya eski karşılığı git checkout -b vardır:
git switch -c feature/login
git switch -c hotfix origin/main # sunucunun güncel durumundan yeni branch
İyi bir alışkanlık: bir görev için branch oluşturmadan önce tabanı güncelleyin: git fetch, ardından git switch -c feature/x origin/main. Böylece branch, uzun süredir güncellenmemiş yerel main'inizden değil, güncel koddan başlar.
Branch'ler nasıl adlandırılır
Ekiplerde yerleşik kurallar: iş türüne göre bir önek ve tirelerle ayrılmış kısa bir açıklama — feature/user-avatar, fix/login-timeout, chore/update-deps, bazen görev numarasıyla: feature/SHOP-142-cart. Boşluk, ~ ^ : ? * [, art arda iki nokta ve .lock ile bitiş kullanılamaz.
Branch'e geçiş: git switch
git switch main # mevcut bir branch'e geç
git switch - # önceki branch'e dön
git switch feature/login # yerelde yoksa ama origin/feature/login varsa,
# Git yerel bir branch oluşturup uzak olana bağlar
Geçiş sırasında Git, çalışma dizinindeki dosyaları hedef branch'teki sürümle değiştirir. Commit edilmemiş değişiklikler hedef branch ile çakışmıyorsa sizinle birlikte taşınır. Çakışıyorsa Git reddeder:
error: Your local changes to the following files would be overwritten by checkout:
app.js
Please commit your changes or stash them before you switch branches.
Çözümler: commit etmek, git stash ile saklamak (sonra git stash pop ile geri almak) veya değişiklikleri bilerek merge denemesiyle taşımak: git switch -m main. --discard-changes seçeneği değişiklikleri çöpe atar — yalnızca kesinlikle gerekmediklerinden eminseniz kullanın.
Neden checkout değil de git switch? Checkout hem branch değiştirebilir hem de dosyaların üzerine yazabilir, bu yüzden hata yapmak kolaydır. Switch yalnızca tek bir şey yapar — branch'lerle çalışır, bu yüzden daha güvenlidir. checkout, switch ve restore'un ayrıntılı karşılaştırması ayrı bir makalede.
Branch nasıl yeniden adlandırılır
git branch -m new-name # geçerli branch'i yeniden adlandır
git branch -m old-name new-name # herhangi birini yeniden adlandır
git branch -M main # aynısı, mevcut branch'in üzerine yazarak
Branch zaten sunucudaysa yeniden adlandırma yalnızca yereldir. Yenisini gönderin ve eskisini silin:
git push -u origin new-name
git push origin --delete old-name
Branch nasıl silinir
git branch -d feature/login # yalnızca branch merge edildiyse siler
git branch -D old-spike # zorla siler
git push origin --delete feature/login # sunucuda siler
-d iş kaybına karşı korur: branch'te geçerli branch'te (veya onun upstream'inde) olmayan commit'ler varsa Git «The branch 'x' is not fully merged» mesajıyla reddeder. -D soru sormadan siler. Geçerli branch silinemez — önce başka bir branch'e geçin.
Yanlış şeyi mi sildiniz? Commit'ler hemen kaybolmaz. Branch'in son commit'inin hash'ini git reflog'da bulun ve geri yükleyin: git branch old-spike 1a9b3c0.
Sunucuda artık bulunmayan uzak branch'lerin eskimiş kayıtlarını git fetch --prune temizler.
Yerel branch'i uzak branch'e bağlama
Yerel bir branch'in upstream'i olabilir — karşılaştırıldığı ve senkronize edildiği uzak branch. Upstream, git push ve git pull'un argümansız çalışması ve git status'un «ahead/behind» göstermesi için gereklidir.
git push -u origin feature/login # ilk gönderimde
git branch --set-upstream-to=origin/main main # mevcut bir branch için
git branch --unset-upstream # bağlantıyı kaldır
Branch'leri birleştirme: kısaca
Branch'ler sonradan birleştirilmek için oluşturulur. İş hazır olduğunda hedef branch'e geçin ve kendi branch'inizi ona merge edin:
git switch main
git merge feature/login
Branch oluşturulduğundan beri main ilerlemediyse Git fast-forward yapar: merge commit'i olmadan main göstericisini branch'in son commit'ine taşır. Her iki branch de yeni commit'ler aldıysa three-way merge gerçekleşir: Git ortak atayı bulur, iki tarafı karşılaştırır ve iki parent'ı olan bir merge commit'i oluşturur. Ekiplerde merge genellikle sunucudaki pull request ile yapılır, yerelde ise yalnızca güncel main çekilir.
Branch kopya kağıdı
| Görev | Komut |
|---|---|
| Branch listesi | git branch -vv |
| Branch oluştur | git branch ad |
| Oluştur ve geç | git switch -c ad |
| Geçiş yap | git switch ad |
| Geri dön | git switch - |
| Yeniden adlandır | git branch -m eski yeni |
| Merge edilmişi sil | git branch -d ad |
| Zorla sil | git branch -D ad |
| Sunucuda sil | git push origin --delete ad |
| Silinebilecek branch'ler | git branch --merged |
| Silineni geri yükle | git reflog, ardından git branch ad hash |
Yeni başlayanların sık yaptığı hatalar
- Doğrudan main'de çalışmak. Commit'ler yapıldıysa ama gönderilmediyse, bulunduğunuz yerde bir branch oluşturun (
git branch feature/x), ardındanmain'i sunucudaki haline döndürün:git reset --hard origin/main(her şeyin commit edildiğini kontrol edin). - Eski main'den branch açmak. Önce
git fetch, branch'iorigin/main'den oluşturun. - Detached HEAD'de commit. Geçiş yapmadan önce branch oluşturun; zaten geçtiyseniz commit'leri
git reflog'da bulun. - Uzun ömürlü branch'ler. Bir branch ne kadar uzun süre ayrı yaşarsa merge o kadar acılı olur.
main'i düzenli olarak çekin ve işi küçük parçalar halinde merge edin.
Ekip çalışmasında branch'ler
Ekiplerin süreçleri farklıdır, ama neredeyse her yerde iki şemadan biri görülür. GitHub Flow'da her zaman yayına hazır olan tek bir uzun ömürlü main branch'i ve review ile CI kontrollerinden sonra pull request ile merge edilen kısa feature branch'leri vardır. Git Flow'da bunlara develop, release branch'leri ve hotfix branch'leri eklenir; şema daha ağırdır ve seyrek, sürümlü yayınlar yapan ürünlere uygundur.
Şemadan bağımsız olarak ortak kurallar geçerlidir: bir branch — bir görev, branch aylarca değil günlerce yaşar, pull request'ten önce branch güncel main ile güncellenir, merge'den sonra branch hem yerelde hem sunucuda silinir. Ana branch repository ayarlarıyla korunur: doğrudan push ve force push yasaktır, merge yalnızca review üzerinden yapılır.
Branch geçmişi nasıl görüntülenir
Branch'lerin birbiriyle ilişkisini anlamanın en kolay yolu grafiktir: git log --oneline --graph --all tüm branch'leri ve ayrıldıkları noktaları doğrudan terminalde çizer. Bir branch'te olup henüz main'e girmemiş commit'leri görmek için git log main..feature/login, dosyalardaki farkı görmek için git diff main...feature/login kullanın (üç nokta ortak ataya göre karşılaştırır, yani yalnızca branch'in kendi değişikliklerini gösterir).
Özet
Git'te branch, bir commit'e işaret eden ucuz bir göstericidir; HEAD ise geçerli branch'e işaret eden göstericidir. git branch branch'leri yönetir (listeleme, oluşturma, yeniden adlandırma, silme), git switch aralarında geçiş yapar, git switch -c ise ikisini birden yapar. Branch'ler, HEAD, fast-forward ve three-way merge Git kursunda canlı örneklerle ele alınıyor.
Sık sorulan sorular
Git'te kaç branch oluşturulabilir?
Pratikte istediğiniz kadar: her branch birkaç on baytlık bir referanstır, bu yüzden boyut açısından bir sınır yoktur.
Branch silinince commit'ler de silinir mi?
Hemen değil. Artık hiçbir şeyin işaret etmediği commit'ler bir süre daha saklanır ve çöp toplayıcı onları silene kadar git reflog üzerinden erişilebilir (erişilemeyen reflog kayıtları için varsayılan olarak en az 30 gün).
Geçerli branch'in hangi branch'ten oluşturulduğunu nasıl öğrenirim?
Git bunu saklamaz: branch yalnızca kendi commit'ini hatırlar. main ile ortak atayı git merge-base HEAD main komutuyla bulabilirsiniz.
Branch ile tag arasındaki fark nedir?
Branch her yeni commit ile ilerler, tag ise kalıcı olarak tek bir commit'e sabitlenir ve sürümleri işaretlemek için kullanılır.
Neden master değil de main?
Bu yalnızca varsayılan branch adıdır. Birçok servis main'e geçti; yeni repository'ler için adı git config --global init.defaultBranch main ayarıyla belirleyebilirsiniz.
Bu konu “Sıfırdan Güvenilir Geliştiriciye Git” kursunda uygulamalı olarak ayrıntılı işleniyor.
Kursa git