Git Sürüm Kontrolü: Geliştiriciler için Eksiksiz Teknik Referans
Git, zaman içinde bir projenin dosya ağacının anlık görüntülerini kaydeden, herhangi sayıda katkıcının birbirinin değişikliklerinin üzerine yazmadan paralel olarak çalışmasına olanak tanıyan bir dağıtık sürüm kontrol sistemi (DVCS)‘dir. Her geliştirici, yerel makinesinde deponun tam bir kopyasını — tüm commit geçmişi dahil — barındırır; bu durum tek hata noktasını ortadan kaldırır ve tamamen çevrimdışı iş akışlarını mümkün kılar.
Nisan 2005’te Linus Torvalds tarafından Linux çekirdeği geliştirmesinde BitKeeper’ın yerini almak üzere oluşturulan Git, üç vazgeçilmez gereksinim etrafında sıfırdan tasarlandı: hız, veri bütünlüğü ve doğrusal olmayan, dağıtık iş akışları için destek. Bu tasarım hedefleri, Git’i seleflerinden kategorik olarak farklı kılan şeyi ve iki on yılı aşkın süredir baskın VCS olmaya devam etmesinin nedenini hâlâ tanımlamaktadır.
Git’in Merkezi Sürüm Kontrolünden Farkı
Git’in mimarisini anlamak, tek bir yetkili sunucunun kanonik depoyu barındırdığı ve geliştiricilerin sığ çalışma kopyaları aldığı Subversion (SVN) veya CVS gibi merkezi sistemlerle doğrudan bir karşılaştırma yapılmasını gerektirir.
| Boyut | Git (Dağıtık) | SVN (Merkezi) |
|---|---|---|
| — | — | — |
| Depo modeli | Her düğümde tam klon | İnce çalışma kopyası, geçmiş sunucuda |
| Çevrimdışı yetenek | Tam commit, branch, diff, log | Salt okunur; commit’ler sunucu gerektirir |
| Branch maliyeti | Neredeyse sıfır (işaretçi manipülasyonu) | Pahalı dizin kopyası |
| Tek hata noktası | Yok — herhangi bir klon geri yükleyebilir | Sunucu kesintisi tüm commit’leri durdurur |
| Birleştirme stratejisi | Üç yönlü birleştirme + rebase | Yalnızca üç yönlü birleştirme |
| Geçmiş bütünlüğü | SHA-1/SHA-256 içerik karma | Sıralı revizyon numaraları |
| Ağ bağımlılığı | Yalnızca push/pull/fetch için | Neredeyse her işlem |
| Kısmi checkout | Yerel olarak desteklenmiyor | Destekleniyor (seyrek checkout) |
| Öğrenme eğrisi | Başlangıçta daha dik eğri | SVN kullanıcıları için daha kolay |
| Benimseme (2024) | Profesyonel ekiplerin ~%95’i | Eski kurumsal ortamlar |
Dağıtık model, GitHub gibi bir barındırma platformu kesinti yaşasa bile her geliştiricinin yerel klonunun tüm proje geçmişinin eksiksiz ve yetkili bir yedeği olduğu anlamına gelir.
Temel Mimari: Git Aslında Neyi Depolar
Git diff’leri depolamaz. Anlık görüntüleri depolar. Her commit, o andaki tüm izlenen dosyaların tam durumunu temsil eden bir ağaç nesnesine işaret eder. Bir dosya iki commit arasında değişmemişse, Git onu kopyalamak yerine önceki blob’a bir işaretçi depolar — Git’in hem eksiksizliği hem de depolama verimliliğini bu şekilde sağlar.
Git’in nesne deposundaki (.git/objects/) dört temel nesne türü şunlardır:
- Blob — SHA karması ile adreslenen ham dosya içeriği
- Tree — dosya adlarını blob veya alt ağaç karmalarıyla eşleştiren bir dizin listesi
- Commit — bir ağaca, sıfır veya daha fazla üst commit’e, yazar meta verilerine ve bir mesaja işaretçi
- Tag — belirli bir commit’e yönelik açıklamalı işaretçi, sürüm işaretçileri için kullanılır
Her nesne değişmez ve içerik adreslidir. Herhangi bir dosyada tek bir baytın değiştirilmesi tamamen farklı bir SHA karması üretir ve bu durum ağaç ile commit nesneleri üzerinden yukarıya doğru yayılır. Git’in geçmişinin kriptografik olarak kurcalamaya karşı korumalı olmasının nedeni budur — sonraki her commit karmasını değiştirmeden geçmişteki bir commit’i sessizce değiştiremezsiniz.
Hazırlama alanı (index olarak da adlandırılır, .git/index‘de depolanır), önerilen bir sonraki commit’i tutan ikili bir dosyadır. Çalışma dizini, index, depo şeklindeki bu üç bölgeli model, Git’in en yanlış anlaşılan mimari özelliği ve çoğu başlangıç düzeyindeki karışıklığın kaynağıdır.
Git’i Kurma ve Yapılandırma
Herhangi bir komut çalıştırmadan önce kurulumunuzu doğrulayın ve kimliğinizi yapılandırın. Git, yazar bilgilerini her commit nesnesine gömer ve yanlış yapılandırılmış kimlik, paylaşılan depolarda dağınık commit geçmişlerinin en yaygın nedenlerinden biridir.
# Verify installation
git --version
# Set global identity (stored in ~/.gitconfig)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Set default branch name to 'main' (modern convention)
git config --global init.defaultBranch main
# Set preferred editor for commit messages
git config --global core.editor "vim"
# Enable colored output
git config --global color.ui auto
# Verify configuration
git config --listYapılandırma katmanlıdır: --system (tüm kullanıcılar, /etc/gitconfig), --global (mevcut kullanıcı, ~/.gitconfig) ve --local (depo, .git/config). Daha özel kapsamlar daha geniş olanları geçersiz kılar.
Temel Git Komutları: Eksiksiz Başvuru Kılavuzu
Başlatma ve Klonlama
git init, mevcut klasöre bir .git/ dizini yazarak yeni bir depo oluşturur. Herhangi bir commit oluşturmaz — depo boş başlar.
git init
git init my-project # Initialize into a new subdirectory
git init --bare repo.git # Bare repository (no working tree, used for servers)Bir bare depo, yalnızca nesne deposunu ve ref’leri içerir — çalışma dizini yoktur. Bu, birden fazla geliştiricinin push yaptığı uzak bir depo için doğru formattır. Bir VPS Hosting sunucusunda Git’i kendi barındırıyorsanız, paylaşılan depoları her zaman bare olarak başlatın.
git clone, tüm branch’ler, tag’ler ve geçmiş dahil olmak üzere uzak bir deponun tam yerel kopyasını oluşturur.
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # SSH transport (preferred for auth)
git clone --depth 1 https://github.com/user/repo.git # Shallow clone (latest commit only)
git clone --branch develop https://github.com/user/repo.git # Clone specific branchSığ klonlar (--depth), yalnızca en son duruma ihtiyaç duyduğunuz ve tam geçmişe ihtiyaç duymadığınız CI/CD pipeline’ları için kullanışlıdır. Büyük depolarda klon süresini önemli ölçüde azaltırlar, ancak git bisect gibi geçmişe bağlı bazı işlemleri engeller.
Durumu İnceleme
git status, herhangi bir iş akışında en sık çalıştırılan komuttur. Deponuzun üç bölgeli durumunu gösterir.
git status
git status -s # Short format: two-column status codes
git status -sb # Short format with branch infogit diff, bölgeler veya commit’ler arasındaki içeriği karşılaştırır.
git diff # Working directory vs. index (unstaged changes)
git diff --staged # Index vs. last commit (what will be committed)
git diff HEAD # Working directory vs. last commit (all changes)
git diff main..feature # Compare tips of two branches
git diff abc123..def456 # Compare two specific commits
git diff --stat # Show changed files and line counts onlygit log, commit grafiğini dolaşır. Filtreleme seçenekleri, Git’in en güçlü ve en az kullanılan özellikleri arasındadır.
git log
git log --oneline --graph --decorate --all # Visual branch graph
git log -p # Show patch (diff) for each commit
git log --author="Jane" # Filter by author
git log --since="2 weeks ago" # Filter by date
git log --grep="fix:" # Filter by commit message pattern
git log -- path/to/file # History of a specific file
git log --follow -- path/to/file # Follow renames--graph --oneline --decorate --all kombinasyonu o kadar evrensel olarak kullanışlıdır ki çoğu mühendis bunu takma ad olarak tanımlar:
git config --global alias.lg "log --oneline --graph --decorate --all"Hazırlama ve Commit Etme
git add filename.py # Stage a specific file
git add src/ # Stage an entire directory
git add . # Stage all changes in current directory
git add -p # Interactive patch staging (stage hunks, not whole files)
git add -u # Stage modifications and deletions, but not new filesEtkileşimli hazırlama (git add -p), Git’in en güçlü ve en az kullanılan özelliklerinden biridir. Çalışma dizininiz birden fazla ilgisiz değişiklik içerdiğinde bile kesin, atomik commit’ler yapmanızı sağlayarak bir dosya içindeki tek tek parçaları incelemenize ve seçici olarak hazırlamanıza olanak tanır.
git commit -m "feat: add OAuth2 token refresh logic"
git commit --amend # Modify the most recent commit (message or content)
git commit --amend --no-edit # Amend content without changing the message
git commit -v # Open editor showing full diff of staged changesKritik kural: Paylaşılan bir uzak sunucuya zaten push edilmiş commit’leri asla değiştirmeyin. Değiştirme işlemi commit karmasını yeniden yazar ve iş arkadaşlarını yerel branch’lerini rebase etmeye veya sıfırlamaya zorlar.
Push ve Pull
git push origin main
git push origin feature/auth # Push a specific branch
git push -u origin feature/auth # Push and set upstream tracking
git push --force-with-lease # Safer force push (fails if remote has new commits)
git push origin --delete old-branch # Delete a remote branch
git push --tags # Push all local tagsUzak geçmişi yeniden yazmanız gerektiğinde --force-with-lease‘ı --force yerine tercih edin. Son fetch’inizden bu yana başka birinin push yapıp yapmadığını kontrol ederek yanlışlıkla veri kaybını önler.
git pull origin main
git pull --rebase origin main # Fetch and rebase instead of merge
git pull --ff-only # Only fast-forward; abort if a merge commit would be createdgit fetch, çalışma dizininize veya mevcut branch’inize dokunmadan uzak değişiklikleri indirir. Bu, değişiklikleri entegre etmeden önce yukarı akış değişikliklerini incelemenin güvenli yoludur.
git fetch origin
git fetch --all # Fetch from all remotes
git fetch --prune # Remove remote-tracking branches that no longer exist upstreamBranch Oluşturma ve Birleştirme: Temel İş Akışı
Git’in branch modeli, mimarisi açısından en önemli özelliğidir. Bir branch, bir commit karmasına yönelik basitçe adlandırılmış bir işaretçidir (.git/refs/heads/‘de 41 baytlık bir dosya). Branch oluşturmak, depo boyutundan bağımsız olarak anlıktır.
Branch Yönetimi
git branch # List local branches
git branch -a # List all branches (local and remote-tracking)
git branch -v # List branches with last commit info
git branch feature/user-auth # Create a new branch
git branch -d feature/user-auth # Delete merged branch
git branch -D feature/user-auth # Force delete (even if unmerged)
git branch -m old-name new-name # Rename a branchBranch’ler Arasında Geçiş
Modern Git (2.23+), git checkout‘ın sorumluluklarını iki özel komuta ayırır:
git switch main # Switch to existing branch
git switch -c feature/payments # Create and switch in one step
git restore filename.py # Discard working directory changes to a file
git restore --staged filename.py # Unstage a file (remove from index)git checkout bunların hepsi için hâlâ çalışır, ancak git switch ve git restore daha net ve daha az belirsiz anlambilime sahiptir ve modern iş akışlarında tercih edilmelidir.
Birleştirme Stratejileri
git merge feature/user-auth # Standard merge (creates merge commit if needed)
git merge --no-ff feature/user-auth # Always create merge commit (preserves branch topology)
git merge --squash feature/user-auth # Squash all branch commits into one staged change
git merge --abort # Abort an in-progress conflicted mergeHızlı ileri sarma birleştirmesi, hedef branch kaynak branch’ten ayrışmadığında gerçekleşir — Git yalnızca işaretçiyi ileriye taşır. Birleştirme commit’i oluşturulmaz. --no-ff, bu durumda bile bir birleştirme commit’i oluşturmaya zorlar ve git log --graph‘da özellik branch’lerinin görsel geçmişini korur.
Squash birleştirme, bir özellik branch’indeki tüm commit’leri tek bir hazırlanmış değişikliğe daraltır ve bunu manuel olarak commit edersiniz. Bu, main‘da temiz bir doğrusal geçmiş üretir, ancak özellik branch’inin ayrıntılı commit geçmişini atar.
Rebase
git rebase, doğrusal bir geçmiş oluşturmak için karmalarını yeniden yazarak commit’leri bir branch’ten diğerinin üstüne yeniden oynatır.
git rebase main # Rebase current branch onto main
git rebase -i HEAD~5 # Interactive rebase: edit last 5 commits
git rebase --onto main server client # Transplant client branch onto main, excluding server
git rebase --abort # Abort a rebase in progress
git rebase --continue # Continue after resolving a conflictEtkileşimli rebase (-i), profesyonellerin commit hijyen aracıdır. Commit’leri paylaşmadan önce yeniden sıralamanıza, birleştirmenize, düzenlemenize, bırakmanıza veya bölmenize olanak tanır. Yaygın kullanım durumu: Bir pull request açmadan önce dağınık bir özellik branch’ini temizleme.
| Strateji | Geçmiş | Kullanım Durumu | Risk |
|---|---|---|---|
| — | — | — | — |
| Birleştirme (varsayılan) | Doğrusal olmayan, branch’leri korur | Uzun ömürlü özellik branch’leri | Gürültülü `git log` |
| Birleştirme `–no-ff` | Doğrusal olmayan, açık birleştirme commit’leri | Zorunlu branch topolojisi | Yukarıdakiyle aynı |
| Birleştirme `–squash` | Doğrusal, özellik başına bir commit | Temiz ana branch | Ayrıntılı geçmişi kaybeder |
| Rebase | Doğrusal, birleştirme commit’i yok | Kişisel branch’ler, PR öncesi temizlik | Karmaları yeniden yazar; paylaşılan branch’lerde tehlikeli |
| Cherry-pick | Seçici, doğrusal | Düzeltmeleri geri taşıma | Branch’ler arasında yinelenen commit’ler |
Rebase’in altın kuralı: Genel, paylaşılan bir branch’te bulunan commit’leri asla rebase etmeyin. Rebase, commit karmalarını yeniden yazar. Bir ekip arkadaşı bu commit’lere dayalı çalışma yapmışsa, geçmişleri ayrışacak ve ağrılı bir uzlaştırmayla karşılaşacaklar.
Birleştirme Çakışmalarını Çözme
Çakışmalar, iki branch’in aynı dosyanın aynı bölgesini değiştirdiğinde ortaya çıkar. Git, çakışmayı dosyada standart çakışma işaretçileriyle işaretler:
<<<<<<< HEAD
const timeout = 30000;
=======
const timeout = 60000;
>>>>>>> feature/increase-timeoutÇözüm iş akışı:
# After a conflicted merge or rebase
git status # Identify conflicted files (marked as "both modified")
# Edit each conflicted file, remove markers, keep correct content
git add resolved-file.js # Mark as resolved
git commit # Complete the merge (message is pre-populated)Karmaşık çakışmalar için üç yönlü birleştirme aracı daha net bir görünüm sağlar:
git mergetool # Launch configured merge tool (vimdiff, meld, etc.)
git config --global merge.tool vimdiffDeğişiklikleri Geri Alma: Karar Matrisi
Yanlış geri alma komutunu seçmek, geliştiricilerin iş kaybetmesinin veya paylaşılan geçmişi bozmasının en yaygın yollarından biridir. Doğru seçim iki değişkene bağlıdır: değişikliğin nerede bulunduğu ve push edilip edilmediği.
| Senaryo | Komut | Geçmişi Yeniden Yazar | Paylaşılan Branch’te Güvenli |
|---|---|---|---|
| — | — | — | — |
| Bir dosyanın hazırlamasını geri al | `git restore –staged file` | Hayır | Evet |
| Çalışma dizini değişikliklerini at | `git restore file` | Hayır | Evet |
| Son commit’i geri al, değişiklikleri hazırlanmış tut | `git reset –soft HEAD~1` | Evet | Hayır |
| Son commit’i geri al, değişiklikleri hazırlanmamış tut | `git reset HEAD~1` | Evet | Hayır |
| Son commit’i geri al, tüm değişiklikleri at | `git reset –hard HEAD~1` | Evet | Hayır |
| Push edilmiş bir commit’i güvenli şekilde geri al | `git revert <hash>` | Hayır | Evet |
| Bir dosyayı tüm geçmişten kaldır | `git filter-repo` | Evet | Hayır |
git reset --soft HEAD~1 # Undo commit, keep changes in index
git reset HEAD~1 # Undo commit, keep changes in working dir
git reset --hard HEAD~1 # Undo commit, discard all changes permanently
git revert abc1234 # Create new commit that inverts abc1234
git revert HEAD~3..HEAD # Revert last 3 commits (creates 3 revert commits)
git revert -n HEAD~3..HEAD # Stage the reversals without committing (batch revert)git reset --hard normal Git komutlarıyla geri alınamaz. Yanlışlıkla çalıştırırsanız, tek kurtarma yolunuz yaklaşık 90 gün boyunca HEAD’in işaret ettiği her konumu kaydeden git reflog‘dur.
git reflog # Show HEAD movement history with hashes
git checkout -b recovery abc1234 # Recover by creating a branch at the lost commitÜretim İş Akışları için Gelişmiş Komutlar
git stash
git stash, bağlamları değiştirmek için size temiz bir çalışma ağacı sağlayarak mevcut çalışma dizininizi ve index durumunuzu bir yığına kaydeder.
git stash # Stash tracked changes
git stash -u # Include untracked files
git stash push -m "WIP: auth refactor" # Stash with a descriptive name
git stash list # List all stash entries
git stash pop # Apply most recent stash and remove it from stack
git stash apply stash@{2} # Apply specific stash without removing it
git stash drop stash@{2} # Delete a specific stash entry
git stash branch feature/wip # Create a new branch from a stashgit cherry-pick
git cherry-pick abc1234 # Apply a single commit to current branch
git cherry-pick abc1234 def5678 # Apply multiple commits
git cherry-pick abc1234 --no-commit # Apply changes without committing
git cherry-pick main~3..main # Apply a range of commitsCherry-pick, bakım branch’lerine hata düzeltmelerini geri taşımak için standart mekanizmadır. main‘da kritik bir güvenlik açığını düzeltirseniz, ilgisiz özellikleri birleştirmeden o commit’i v2.1-stable ve v2.0-stable‘a cherry-pick edersiniz.
git bisect
git bisect, bir hatayı tam olarak hangi commit’in ortaya çıkardığını bulmak için commit geçmişinde ikili arama yapar. Git’in en güçlü ve en az bilinen hata ayıklama araçlarından biridir.
git bisect start
git bisect bad # Mark current commit as broken
git bisect good v2.3.0 # Mark a known-good commit or tag
# Git checks out the midpoint commit automatically
# Test your code, then:
git bisect good # If this commit is fine
git bisect bad # If this commit is broken
# Repeat until Git identifies the first bad commit
git bisect reset # Return to original HEAD when doneİyi ve kötü noktalar arasında 1.000 commit bulunan bir depoda, git bisect suçluyu en fazla 10 adımda bulur.
git tag
Tag’ler, belirli commit’leri önemli olarak işaretler — genellikle sürüm versiyonları.
git tag v1.4.2 # Lightweight tag (just a pointer)
git tag -a v1.4.2 -m "Release 1.4.2" # Annotated tag (recommended; stores metadata)
git tag -a v1.4.2 abc1234 # Tag a specific past commit
git push origin v1.4.2 # Push a specific tag
git push origin --tags # Push all tags
git tag -d v1.4.2 # Delete local tag
git push origin --delete v1.4.2 # Delete remote tagSürümler için her zaman açıklamalı tag’ler kullanın. Tag’i oluşturanın adını, e-postasını, tarihini ve bir mesajı depolarlar ve GPG ile imzalanabilirler. Hafif tag’ler yalnızca geçici yerel yer imleri için uygundur.
git worktree
git worktree, aynı depodan aynı anda birden fazla çalışma dizininin checkout edilmesine olanak tanır — her biri farklı bir branch’te. Bu, bir hotfix’e geçmeniz gerektiğinde çalışmayı stash etme veya commit etme ihtiyacını ortadan kaldırır.
git worktree add ../hotfix-branch hotfix/critical-auth-bug
git worktree list
git worktree remove ../hotfix-branchBu, birden fazla derleme işinin aynı deponun farklı branch’lerine birbirine müdahale etmeden eş zamanlı erişime ihtiyaç duyduğu bir CI/CD pipeline çalıştıran Dedicated Server‘da özellikle değerlidir.
Ekipler için Git İş Akışları
Doğru branch stratejisi, sürüm hızınıza ve ekip büyüklüğünüze bağlıdır. Üç baskın model mevcuttur:
Özellik Branch İş Akışı
Her özellik veya düzeltme kendi branch’inde yaşar. Geliştiriciler main‘a birleştirmek için pull request açar. Basit, çoğu ekip için etkili.
Gitflow
Uzun ömürlü main ve develop branch’lerini, ayrıca katı birleştirme kurallarına sahip kısa ömürlü feature/, release/ ve hotfix/ branch’lerini tanımlar. Açık sürümlü sürümlere sahip yazılımlar için uygundur (kütüphaneler, paketlenmiş uygulamalar).
Trunk Tabanlı Geliştirme
Geliştiriciler doğrudan main‘a commit eder (veya bir gün içinde birleştirilen çok kısa ömürlü branch’ler kullanır). Tamamlanmamış çalışmayı gizlemek için büyük ölçüde özellik bayraklarına dayanır. Sürekli dağıtım uygulayan yüksek hızlı ekipler tarafından tercih edilir.
| İş Akışı | Sürüm Hızı | Ekip Büyüklüğü | CI/CD Karmaşıklığı |
|---|---|---|---|
| — | — | — | — |
| Özellik Branch | Esnek | Herhangi | Düşük |
| Gitflow | Planlanmış sürümler | Orta–Büyük | Orta |
| Trunk Tabanlı | Sürekli dağıtım | Herhangi | Yüksek |
Git Depolarını Barındırma: Kendi Barındırma ve Yönetilen Platformlar
Veri egemenliği, uyumluluk veya özel altyapı gerektiren ekipler için kendi Git sunucusunu barındırmak uygulanabilir ve çoğu zaman gerekli bir seçimdir. Seçenekler arasında Gitea (hafif, Go tabanlı), GitLab CE (tam DevOps platformu) ve Forgejo (topluluk yönetimine sahip Gitea çatalı) bulunur.
Minimal bir kendi barındırılan Gitea örneği, 2 vCPU ve 2 GB RAM ile VPS Hosting planında rahatça çalışır. Daha büyük ekipler veya CI runner’lara sahip GitLab CE için pratik minimum 4–8 GB RAM’dir.
Kendi barındırırken Git sunucunuzu şunlarla güvence altına alın:
- SSH anahtar kimlik doğrulaması (parola kimlik doğrulamasını tamamen devre dışı bırakın)
- Geçerli sertifikalı HTTPS — aktarım sırasında kimlik bilgilerini korumak için SSL Sertifikaları gereklidir
- Git port erişimini sınırlayan güvenlik duvarı kuralları (22 veya özel SSH portu, HTTPS için 443)
.git bare depo dizinlerinin düzenli otomatik yedekleri
CI/CD entegrasyonları için webhook sırları
Web altyapısını da yöneten Git tabanlı dağıtım pipeline’ları kullanan ekipler için, kendi barındırılan bir Git sunucusunu cPanel ile VPS ile eşleştirmek, tanıdık barındırma yönetim araçlarının yanı sıra entegre dağıtım kancaları sağlar.
Git Hook’ları: Kalite Kapılarını Otomatikleştirme
Git hook’ları, Git yaşam döngüsündeki belirli noktalarda otomatik olarak çalışan betiklerdir. .git/hooks/‘de bulunurlar ve varsayılan olarak depoya commit edilmezler (bunları paylaşmak için pre-commit veya husky gibi bir araç kullanın).
Üretim iş akışları için temel hook’lar:
Hook
Tetikleyici
Yaygın Kullanım
—
—
—
`pre-commit`
Commit oluşturulmadan önce
Linter, formatlayıcı, test çalıştırma
`commit-msg`
Commit mesajı yazıldıktan sonra
Geleneksel commit formatını zorunlu kılma
`pre-push`
Uzak sunucuya push’tan önce
Tam test paketini çalıştırma
`post-receive`
Uzak sunucu push aldıktan sonra
Dağıtımı tetikleme, bildirim gönderme
`pre-rebase`
Rebase başlamadan önce
Paylaşılan branch’lerin rebase edilmesini engelleme
# Example pre-commit hook: reject commits with debug print statements
#!/bin/bash
if git diff --cached | grep -E '^+.*(console.log|debugger|print("DEBUG)'; then
echo "ERROR: Debug statement detected. Remove before committing."
exit 1
fi
Bare sunucu deposundaki post-receive hook’u, basit Git tabanlı dağıtımın temelidir: sunucuya push yapın, hook yeni HEAD’i web köküne checkout eder, derleme adımlarını çalıştırır ve servisleri yeniden başlatır — harici CI platformu gerekmez.
.gitignore: Depoları Temiz Tutma
.gitignore dosyası, Git’e hangi dosyaları ve kalıpları izlenmemiş bırakacağını söyler. Depoya commit edilmeli ve dikkatle bakımı yapılmalıdır.
# Dependencies
node_modules/
vendor/
# Build artifacts
dist/
build/
*.o
*.pyc
__pycache__/
# Environment and secrets — NEVER commit these
.env
.env.local
*.pem
*.key
config/secrets.yml
# IDE files
.idea/
.vscode/
*.swp
# OS files
.DS_Store
Thumbs.db
Kritik tuzak: Bir dosya .gitignore‘a eklenmeden önce zaten izleniyorsa, Git onu izlemeye devam edecektir. Açıkça izlemeyi kaldırmanız gerekir:
git rm --cached path/to/sensitive-file
git commit -m "chore: stop tracking secrets file"
Kimlik bilgilerini, API anahtarlarını veya özel anahtarları bir depoya asla commit etmeyin — özel bir depo olsa bile. Ortam değişkenlerini, gizli yöneticileri (HashiCorp Vault, AWS Secrets Manager) veya .gitignore‘lı .env dosyalarını kullanın.
Büyük Depolar için Performans Ayarı
Standart Git, milyonlarca dosya veya gigabaytlarca ikili varlık içeren depolarda performans düşüşü yaşar. Azaltma stratejileri:
Git LFS (Büyük Dosya Depolama): Büyük ikili dosyaları depodaki işaretçi dosyalarıyla değiştirir ve gerçek içeriği ayrı bir LFS sunucusunda depolar. Medya, ML model ağırlıkları veya derlenmiş ikili dosyalar içeren depolar için gereklidir.
Kısmi klon: git clone --filter=blob:none, commit’leri ve ağaçları indirir ancak blob’ları talep üzerine getirir. Büyük monorepo’larda başlangıç klon boyutunu önemli ölçüde azaltır.
Seyrek checkout: git sparse-checkout set path/to/subdir, çalışma ağacının yalnızca bir alt kümesini checkout eder. Bir geliştiricinin yalnızca bir servis dizininde çalıştığı monorepo’larda kullanışlıdır.
Commit-graph dosyası: git commit-graph write --reachable, commit grafiğini önceden hesaplar ve büyük geçmişlerde git log --graph ve erişilebilirlik sorguları gibi işlemleri hızlandırır.
git maintenance start: Depo işlemlerini zaman içinde hızlı tutmak için arka plan bakım görevlerini (gevşek nesne paketleme, commit-graph güncellemeleri, fetch prefetch) zamanlar.
Teknik Temel Kontrol Listesi
Git kurulumunuzu üretime hazır saymadan önce aşağıdakilerin her birini doğrulayın:
Kimlik yapılandırıldı: user.name ve user.email uygun yapılandırma kapsamında doğru şekilde ayarlandı
SSH anahtarları kullanımda: Uzak sunuculara parola kimlik doğrulaması SSH anahtar çiftleri veya token tabanlı HTTPS ile değiştirildi
.gitignore commit edildi: Gizli bilgiler, derleme çıktıları ve işletim sistemi dosyaları ilk commit’ten önce hariç tutuldu
Varsayılan branch main olarak adlandırıldı: Eski master adlandırmasından kaçınmak için init.defaultBranch global olarak ayarlandı
Commit mesajları bir kurala uyuyor: Geleneksel Commit’ler (feat:, fix:, chore:) veya commit-msg hook’u aracılığıyla zorunlu kılınan ekip tarafından kararlaştırılmış format
Genel geçmiş için git revert: git reset --hard yalnızca yerel, push edilmemiş commit’lerde kullanıldı
--force-with-lease yerine --force: Ekip arkadaşlarının push’larının yanlışlıkla üzerine yazılmasını önler
Sürümler için açıklamalı tag’ler: Hafif tag’ler değil, mesajlı git tag -apre-commit veya husky aracılığıyla paylaşılan hook’lar: Kalite kapıları ekip genelinde tutarlı şekilde uygulandıgit init --bare ile başlatıldıgit fetch --prune: Uzak izleme branch’leri gerçek uzak durumuyla senkronize tutulduSıkça Sorulan Sorular
git fetch ile git pull arasındaki fark nedir?
git fetch, çalışma dizininize veya mevcut branch’inize dokunmadan uzaktan commit’leri, branch’leri ve tag’leri yerel uzak izleme ref’lerinize (örn. origin/main) indirir. git pull ise git fetch‘ın hemen ardından git merge (veya yapılandırılmışsa git rebase) işlemidir. Değişiklikleri entegre etmeden önce yukarı akış değişikliklerini incelemek istediğinizde git fetch kullanın.
git merge yerine ne zaman git rebase kullanmalıyım?
Proje geçmişini okunabilir tutmak için bir pull request açmadan önce yerel özellik branch’inizi doğrusallaştırmak amacıyla rebase kullanın. Diğer geliştiricilerin zaten klonladığı veya üzerine çalışma dayandırdığı bir branch’i asla rebase etmeyin — yayımlanmış commit karmalarını yeniden yazmak, diğer herkesin ayrışan geçmişleri manuel olarak uzlaştırmasını zorlar.
Yanlışlıkla commit edilen hassas bir dosyayı kalıcı olarak nasıl kaldırırım?
git filter-branch‘ın modern yerini alan git filter-repo‘ı kullanın: git filter-repo --path secrets.env --invert-paths. Bu, tüm depo geçmişini yeniden yazarak dosyayı her commit’ten kaldırır. Yeniden yazdıktan sonra tüm branch’leri ve tag’leri zorla push edin, ardından açığa çıkan kimlik bilgilerini hemen değiştirin — ne kadar hızlı hareket ettiğinizden bağımsız olarak bunların ele geçirildiğini varsayın.
Ayrık HEAD durumu nedir ve nasıl kurtarılır?
Ayrık HEAD, HEAD işaretçinizin bir branch adı yerine doğrudan belirli bir commit karmasına başvurduğu anlamına gelir. Yaptığınız commit’ler hiçbir branch’e ait olmayacak ve siz uzaklaştıktan sonra erişilemez hale gelecektir. Kurtarmak için: commit’leri yeni bir branch’e eklemek üzere git switch -c new-branch-name kullanın veya bunları atmak için git switch main kullanın.
Git ikili dosyaları metin dosyalarından farklı nasıl işler?
Git, ikili dosyaları opak blob’lar olarak depolar — anlamlı satır düzeyinde diff’ler hesaplayamaz veya bunlar üzerinde otomatik birleştirme yapamaz. İkili dosyalardaki çakışmalar, bir sürümü tamamen seçerek çözülmelidir. Önemli ikili varlıklara sahip depolar için, ikili dosyaları harici olarak depolamak ve deponun kendisini yalın ve hızlı tutmak amacıyla Git LFS’yi yapılandırın.
