Git Nedir: Versiyon Kontrolüne Giriş ve Temel Kavramlar
Yıllar önce bir meslektaşım bana “Git öğrenmek zorunda değilsin, ama bir gün mutlaka pişman olacaksın” demişti. O zamanlar FTP ile dosya yükleyip üstüne yazarak “deployment” yaptığımızı düşününce, haklıymış. Versiyon kontrolü olmadan çalışmak, gözlerinizi kapatarak araba sürmek gibi bir şey; bir süre gidebilirsiniz, ama eninde sonunda bir şeylere çarparsınız.
Bu yazıda Git’i sıfırdan anlatacağım. Sadece komutları ezberletmek değil, arkasındaki mantığı kavratmak istiyorum. Çünkü Git’i gerçekten anladığınızda, komutlar zaten yerine oturuyor.
Versiyon Kontrolü Neden Var?
Şöyle bir senaryo düşünün: Üretim sunucunuzda çalışan bir Nginx konfigürasyon dosyası var. Bir değişiklik yapıyorsunuz, bir şeyler bozuluyor, ve bir saat önce ne yazdığınızı hatırlamaya çalışıyorsunuz. Ya da daha kötüsü, ekibinizdeki başka biri de aynı dosyayı değiştirmiş ve iki değişiklik birbirinin üzerine yazılmış.
Bu sorunları çözmek için insanlar önce elle versiyonlama yapmaya başladı:
nginx.conf
nginx.conf.bak
nginx.conf.bak2
nginx.conf.eskiyi_bozmadan_once
nginx.conf.FINAL
nginx.conf.FINAL_v2
Tanıdık geldi mi? İşte tam olarak bu kaos ortamından kurtulmak için versiyon kontrol sistemleri doğdu.
Versiyon kontrol sistemi temelde şu soruları yanıtlar:
- Bu dosya ne zaman değişti?
- Kim değiştirdi?
- Ne değiştirildi?
- Neden değiştirildi?
- Eski haline nasıl dönebilirim?
Git’in Kısa Tarihi ve Neden Git?
Git, 2005 yılında Linus Torvalds tarafından Linux kernel geliştirme sürecini yönetmek için yazıldı. O dönemde kullandıkları BitKeeper adlı araçla aralarının açılması üzerine Linus “tamam, kendininkini yaz” moduna geçti ve birkaç hafta içinde Git’in temellerini attı.
Bugün Git neredeyse her yerde karşımıza çıkıyor:
- GitHub, GitLab, Bitbucket gibi platformların tamamı Git tabanlı
- CI/CD pipeline’larınızın büyük çoğunluğu Git event’leriyle tetikleniyor
- Infrastructure as Code araçları (Terraform, Ansible playbook’ları) Git repolarında yaşıyor
- Kubernetes manifest’leri, Helm chart’ları, Docker compose dosyaları…
Kısacası, modern sistem yöneticiliği ve DevOps pratiği Git bilmeden düşünülemez.
Git’in Temel Mimarisi
Git’i anlamanın en iyi yolu, onun dağıtık (distributed) yapısını kavramaktan geçiyor. SVN gibi merkezi sistemlerin aksine, Git’te her geliştirici veya sistem yöneticisi tam bir repo kopyasına sahip. Sunucu çökse bile, yerel kopyanızda tüm tarih mevcut.
Git üç temel kavram üzerine inşa edilmiş:
Working Directory (Çalışma Dizini): Dosyalarınızı düzenlediğiniz alan. Henüz Git’e söylemediğiniz değişiklikler burada.
Staging Area (Index): Commit’e hazırladığınız değişikliklerin bekleme odası. Bu alanı anlamak Git’i kavramanın yarısı demek.
Repository (.git dizini): Git’in tüm tarih bilgisini, commit’leri, branch’leri sakladığı yer. Projenizin kök dizininde gizli .git klasörü olarak bulunur.
Kurulum ve İlk Yapılandırma
Önce sisteminize Git’i kuralım:
# Ubuntu/Debian
sudo apt update && sudo apt install git -y
# RHEL/CentOS/Rocky Linux
sudo dnf install git -y
# macOS
brew install git
Kurulumdan sonra yapmanız gereken ilk şey kimliğinizi tanımlamak. Git her commit’e bu bilgileri ekler:
git config --global user.name "Ahmet Yılmaz"
git config --global user.email "[email protected]"
git config --global core.editor "vim"
git config --global init.defaultBranch main
Bu ayarları doğrulamak için:
git config --list
--global flag’i bu ayarları ~/.gitconfig dosyasına yazar ve tüm projelerinizde geçerli olur. Belirli bir proje için farklı kimlik kullanmak istiyorsanız (mesela iş ve kişisel projeler), o projenin dizininde --global olmadan aynı komutları çalıştırın.
İlk Repository’yi Oluşturmak
İki farklı yol var: sıfırdan başlamak veya mevcut bir repoyu klonlamak.
# Yeni proje başlatmak
mkdir web-sunucu-konfigleri
cd web-sunucu-konfigleri
git init
# Mevcut bir repoyu klonlamak
git clone https://github.com/ornek/proje.git
git clone [email protected]:ornek/proje.git # SSH ile
git init çalıştırdığınızda dizinde .git klasörü oluşur. Bu klasörü silmek reponun tüm tarihini silmek demektir, dikkatli olun.
Temel İş Akışı: Add, Commit, Push
Git’teki temel iş akışını bir senaryo üzerinden anlatalım. Nginx konfigürasyonlarımızı Git ile yönetmeye başlıyoruz diyelim.
# Mevcut durumu kontrol et
git status
# Bir dosya oluştur veya düzenle
vim nginx.conf
# Değişikliği staging area'ya al
git add nginx.conf
# Ya da tüm değişiklikleri ekle
git add .
# Commit oluştur
git commit -m "Nginx upstream timeout değerleri güncellendi"
git status komutunu bir alışkanlık haline getirin. Ne yaptığınızı her zaman görmenizi sağlar. Ben terminal oturumu açtığımda neredeyse refleks olarak git status yazarım.
Commit Mesajları Hakkında Bir Not
“Değişiklikler yapıldı” veya “fix” gibi mesajlar yazan insanları gördüğümde içim sızlar. İyi bir commit mesajı, 3 ay sonra tarihe baktığınızda ne olduğunu anlamanızı sağlamalı.
Yaygın bir format:
<tip>: <kısa özet>
<isteğe bağlı detay>
Örnekler:
feat: Yeni load balancer konfigürasyonu eklendifix: SSL sertifika yenileme script'indeki path hatası düzeltildichore: Eski log rotation kuralları temizlendi
Değişiklikleri İncelemek
# Commit geçmişini görüntüle
git log
# Daha özlü görünüm
git log --oneline
# Hangi dosyaların değiştiğini göster
git log --stat
# Grafiksel branch görünümü
git log --oneline --graph --all
Son komut özellikle branch’lerle çalışırken çok işe yarıyor. Terminalde basit ama anlaşılır bir ağaç yapısı görüyorsunuz.
Belirli bir commit’te ne değiştiğini görmek için:
# Son commit'teki değişiklikler
git show HEAD
# Belirli bir commit
git show a3b4c5d
# İki commit arasındaki fark
git diff HEAD~3 HEAD
Branch Kavramı
Branch’ler Git’in en güçlü özelliklerinden biri. Bir branch’i ana koddan bağımsız bir çalışma dalı olarak düşünebilirsiniz. Production’daki yapıyı bozmadan yeni bir şey denemek istiyorsunuz? Branch açın.
# Mevcut branch'leri listele
git branch
# Yeni branch oluştur
git branch feature/yeni-cache-ayarlari
# Branch'e geç
git checkout feature/yeni-cache-ayarlari
# Oluştur ve geç (kısa yol)
git checkout -b hotfix/ssl-cert-yenileme
# Modern syntax (Git 2.23+)
git switch -c hotfix/ssl-cert-yenileme
Branch’lerde çalıştıktan sonra değişiklikleri ana branch ile birleştirmek için merge kullanırsınız:
# Ana branch'e dön
git checkout main
# Feature branch'i birleştir
git merge feature/yeni-cache-ayarlari
Gerçek dünyada branch stratejisi önemli. Küçük ekiplerde basit bir model yeterli:
mainveyamaster: Üretimdeki koddevelop: Geliştirme ortamıfeature/*: Yeni özelliklerhotfix/*: Acil düzeltmeler
Remote Repository ile Çalışmak
Yerel Git tek başına da faydalı, ama asıl güç remote repository ile ekip çalışmasına giriyor.
# Remote repository'leri listele
git remote -v
# Remote ekle
git remote add origin [email protected]:sirketim/altyapi-konfigler.git
# Değişiklikleri remote'a gönder
git push origin main
# İlk push için upstream ayarla
git push -u origin main
# Remote'daki değişiklikleri al
git pull origin main
# Sadece bilgi çek, birleştirme yapma
git fetch origin
git pull aslında git fetch + git merge kombinasyonudur. Ekip ortamında önce fetch yapıp durumu değerlendirmek, sonra merge veya rebase yapmak daha kontrollü bir yaklaşım.
.gitignore: Ne Takip Edilmemeli?
Her şeyi Git’e eklemek istemeyiz. Şifreler, API anahtarları, geçici dosyalar, büyük binary dosyalar bunların başında geliyor.
# .gitignore dosyası oluştur
cat > .gitignore << 'EOF'
# Şifreler ve hassas bilgiler
*.env
secrets/
vault-credentials.json
# Log dosyaları
*.log
logs/
# Geçici dosyalar
*.tmp
*.swp
.DS_Store
# Terraform state dosyaları (dikkatli olun, bunlarda şifre olabilir)
*.tfstate
*.tfstate.backup
.terraform/
EOF
Zaten takip edilen bir dosyayı .gitignore‘a eklemek onu otomatik olarak takipten çıkarmaz. Bunun için:
git rm --cached hassas-dosya.txt
Bu komut dosyayı diskten silmez, sadece Git takibinden çıkarır.
Geri Alma İşlemleri
Git’in en değerli özelliklerinden biri hataları geri alabilmek. Ama dikkat: bazı geri alma işlemleri geri alınamaz.
# Staging'den geri al (dosyayı değiştirmez)
git restore --staged nginx.conf
# Dosyadaki değişiklikleri geri al (DİKKAT: kalıcı)
git restore nginx.conf
# Son commit'i geri al, değişiklikleri koru
git reset --soft HEAD~1
# Son commit'i geri al, staging'i de temizle
git reset HEAD~1
# Her şeyi geri al (DİKKAT: kalıcı)
git reset --hard HEAD~1
Zaten push edilmiş commit’leri geri almak için revert kullanın. Bu yeni bir commit oluşturarak değişikliği geri alır ve tarih temiz kalır:
git revert a3b4c5d
Shared repository’de git reset ile push edilmiş commit’leri değiştirmeyin. Bu ekip arkadaşlarınızın hayatını cehenneme çevirir.
Pratik Senaryo: Altyapı Konfigürasyonlarını Git ile Yönetmek
Gerçek bir senaryo üzerinden gidelim. Şirketin Ansible playbook’larını ve Nginx konfigürasyonlarını Git ile yönetmeye başladınız:
# Repo yapısını oluştur
mkdir altyapi-repo && cd altyapi-repo
git init
mkdir -p {ansible/roles,nginx/sites-available,scripts}
# İlk commit
git add .
git commit -m "chore: Başlangıç repo yapısı oluşturuldu"
# Remote'a bağla
git remote add origin [email protected]:ops/altyapi.git
git push -u origin main
# Yeni bir Nginx virtual host ekleyeceksiniz
git checkout -b feature/yeni-api-vhost
vim nginx/sites-available/api.sirket.com.conf
git add nginx/sites-available/api.sirket.com.conf
git commit -m "feat: api.sirket.com için Nginx virtual host eklendi"
# Test ettiniz, her şey tamam
git checkout main
git merge feature/yeni-api-vhost
git push origin main
# Temizlik
git branch -d feature/yeni-api-vhost
Bu iş akışı küçük görünebilir ama bir ay sonra “bu Nginx konfigürasyonuna kim, ne zaman, neden bu satırı ekledi?” sorusuna saniyeler içinde cevap bulabilmek paha biçilemez.
Stash: “Bir Dakika Bekle” Komutu
Bir şeyler üzerinde çalışırken acil bir şey geldi ve branch değiştirmeniz gerekiyor, ama yarım kalan işinizi commit etmek istemiyorsunuz. İşte stash tam bunun için:
# Değişiklikleri geçici olarak kaydet
git stash
# Stash listesini görüntüle
git stash list
# Son stash'i geri yükle
git stash pop
# Belirli bir stash'i yükle
git stash apply stash@{2}
# Stash'e açıklama ekle
git stash push -m "Yarım kalan load balancer ayarları"
stash pop stash’i listedan silerken stash apply listede bırakır.
Sonuç
Git öğrenmek bir gecede olmuyor, ama temel mantığı kavradıktan sonra her şey yerine oturuyor. Şunu net söyleyeyim: bu yazıdaki kavramlar, günlük sistem yöneticiliği ve DevOps işlerinin yüzde seksenini karşılıyor. Geri kalanlar (rebase, cherry-pick, submodule, hook’lar) bunların üzerine inşa ediliyor.
Başlangıç için şu alışkanlıkları edinin:
- Her projede
git initile başlayın, hatta tek kişilik projelerinizde bile .gitignore‘u projenin başında oluşturun, sonradan eklemek zahmetli- Anlamlı commit mesajları yazın, ilerideki siz teşekkür edecek
git status‘u refleks haline getirin- Önemli değişikliklerden önce branch açın
Git’i gerçekten öğrenmek istiyorsanız en iyi yol altyapı konfigürasyonlarınızı, script’lerinizi, dökümanlarınızı Git ile yönetmeye başlamak. Teorik bilgi ancak pratikle anlam kazanıyor.
Serinin devamında branch stratejileri, rebase ve merge farkları, GitLab/GitHub ile CI/CD entegrasyonu gibi konulara geçeceğiz. Sorularınız için yorumlar açık.
