Yasin Ateş
5 dk Medium

Sıfırdan İleri Seviyeye: Git Versiyon Kontrol Sistemi ☕️

Sıfırdan İleri Seviyeye: Git Versiyon Kontrol Sistemi ☕️
A dan Z ye Git Versiyon Kontrol Sistemi Hakkında

Git Nedir? 🤔

Git; yazılım geliştirme sürecinde dosyalarda yapılan değişiklikleri zamana bağlı olarak kaydeden, dağıtık (distributed) bir versiyon kontrol sistemidir.

Git’in Kısa Tarihi 📖

Git, Linux’un yaratıcısı Linus Torvalds tarafından 2005 yılında geliştirildi.

Linux projesi, 2002'den beri BitKeeper adlı ücretli bir versiyon kontrol sistemini ücretsiz olarak kullanıyordu. 2005'te BitKeeper, Linux geliştiricilerinden Andrew Tridgell’ın kaynak koduna ters-mühendislik uyguladığını iddia ederek ücretsiz lisansı iptal etti. Bunun üzerine Linus Torvalds, kendi versiyon kontrol sistemini yazmaya karar verdi ve Git ortaya çıktı.

Neden Versiyon Kontrolü? 🧐

Tek başımıza çalışırken dosyaları elle yedeklemek mümkün. Ancak birden fazla kişinin aynı proje üzerinde çalıştığı durumlarda; kimin, ne zaman, neyi değiştirdiğini takip etmek zorlaşır. Versiyon kontrol sistemi bu süreci otomatize eder ve şu sorunları çözer:

  • Dosyaların farklı sürümlerini güvenle saklar
  • Birden fazla kişinin aynı anda çalışmasına olanak tanır
  • Hata durumunda önceki bir sürüme kolayca geri dönülmesini sağlar
  • Kimin hangi değişikliği yaptığını kaydeder

Git Nasıl Çalışır? ⚙️

Git çalışma mantığı

Git üç temel katmandan oluşur:

  • Working Directory (Çalışma Dizini): Dosyalarımızın bulunduğu, üzerinde aktif olarak çalıştığımız yerel dizindir.
  • Staging Area (Hazırlık Alanı): Değişiklikleri tamamlayıp Git deposuna göndermeye hazır hale getirdiğimiz ara katmandır. “Commit öncesi bekleme odası” olarak düşünebiliriz.
  • Repository (Depo — Kısaca “Repo” da denir): Değişikliklerin kalıcı olarak kaydedildiği Git deposudur. Proje dizinimizdeki .git klasörüdür.

Temel iş akışı şudur:

  1. Çalışma dizininde değişiklik yaparız
  2. git add ile bu değişiklikleri staging area'ya ekleriz
  3. git commit ile staging area'daki değişiklikleri Git deposuna kaydederiz

Kurulum 💻

git-scm.com adresinden işletim sistemimize uygun sürümü indirip kurulum adımlarını tamamlayabiliriz.

Kurulumu doğrulamak için terminalde:

1git --version

Konfigürasyon (git config) 🔧

Git’i kullanmaya başlamadan önce kullanıcı bilgilerimizi tanımlamamız gerekir. Her commit’te bu bilgiler kayıt altına alınır.

★ Global Konfigürasyon

Bilgisayardaki tüm Git repository’leri için geçerli olan varsayılan konfigürasyon aşağıdaki gibi tanımlanır:

1git config --global user.name "Yasin"
2git config --global user.email "yasinatesim@gmail.com"

★ Local konfigürasyon

Yalnızca bulunduğumuz repository için geçerli olan konfigürasyon tanımıdır. Aynı isimde bir global ayar varsa, local ayar onu ezer:

1git config --local user.name "Beril"
2git config --local user.email "beril@yasinates.com"
💡 Bu örneğe göre, bilgisayardaki ana Git, tüm respository’lerde “Yasin” kullanır ancak bir tane proje özelinde local komutu globaldeki tanımı ezmiş olur ve ilgili projede “Beril” kullanılmaya devam eder.

★ Faydalı Ek Ayarlar

1# Varsayılan branch adını main olarak ayarla
2git config --global init.defaultBranch main
1# VS Code'u varsayılan editör olarak ayarla
2git config --global core.editor "code --wait"
1# Renklendirmeyi etkinleştir
2git config --global color.ui auto
1# Pull işleminde varsayılan olarak rebase kullan
2git config --global pull.rebase true

★ Git Alias (Kısayollar)

Sık kullandığımız komutlar için kısayollar tanımlayabiliriz:

1git config --global alias.st status
2git config --global alias.co checkout
3git config --global alias.br branch
4git config --global alias.cm "commit -m"
5git config --global alias.lg "log --oneline --graph --decorate --all"

Artık git status yerine git st, git checkout yerine git co yazabiliriz.

★ Konfigürasyonları Kontrol Etme

Tüm konfigürasyonları kontrol etmek için:

1git config --list

Repository Oluşturma (git init) 📂

git init komutu

Çalışma dizinimizi bir Git repository’sine dönüştürmek için terminal üzerinden ilgili dizine geldikten sonra:

1git init

Bu komut dizinimizde .git adında gizli bir klasör oluşturur. Git'in tüm verileri (commit geçmişi, branch bilgileri, yapılandırma vb.) bu klasörde saklanır. Varsayılan branch adı, Git sürümümüze ve yapılandırmamıza göre master veya main olabilir. Günümüzde GitHub gibi platformlar varsayılan olarak main kullanır. Terminalimizde parantez içinde branch adını (örneğin (main)) göreceğiz.

💡 Branch kavramını makalenin ilerleyen bölümlerinde detaylı ele aldım

Dosya Durumunu İzleme (git status) 🔍

git status komutu

Repository’deki değişikliklerin durumunu görmek için:

1git status

Bu komut; hangi dosyaların değiştiğini, hangilerinin staging area’da olduğunu ve hangilerinin henüz Git tarafından izlenmediğini (untracked) gösterir.

git init komutundan hemen sonra çalıştırırsak, henüz hiçbir commit bulunmadığını ve git add komutunu kullanmamız gerektiğini söyler. git status'u Git'in bize sürekli yol gösteren pusulası olarak düşünebiliriz; ne zaman emin olamazsak bu komutu çalıştıralım.

Staging Area’ya Değişiklikleri Eklemek (git add) ➕

Bir dosya oluşturarak başlayalım. Çalışma dizinimizde isimler.txt adında bir dosya oluşturalım:

1Eda
2Beyza
3Tuvana
4Melis

git status komutunu çalıştırdığımızda Git bu dosyayı untracked (izlenmeyen) olarak gösterecektir. Bu dosyayı staging area'ya eklemek, yani Git'in bu dosyayı izlemeye başlamasını sağlamak için:

Tek bir dosya eklemek:

1git add isimler.txt

Tüm değişiklikleri tek seferde eklemek:

1git add .
⚠️ git add . pratik olsa da istemeden alakasız dosyaları da staging area'ya ekleyebilir. Özellikle büyük projelerde önce git status ile kontrol etmek iyi bir alışkanlıktır.

Staging Area Değişikliklerini İzleme 👀

git add komutundan sonra git status komutunu tekrar çalıştıralım:

1git status

Artık dosyamızın “Changes to be committed” (commit edilmeye hazır) bölümünde listelendiğini göreceğiz. Git, staging area’daki değişikliklerin tipini otomatik olarak algılar.

★ Değişiklik Tipleri

Yeni Dosya (new file): Daha önce Git tarafından izlenmeyen, yeni eklenen bir dosyadır.

1Changes to be committed:
2    new file:   isimler.txt

Değiştirilmiş Dosya (modified): İçeriği değiştirilen, daha önce Git tarafından izlenen bir dosyadır.

1Changes not staged for commit:
2    modified:   isimler.txt

Değişikliği geri almak istersek:

1git restore isimler.txt

Silinmiş Dosya (deleted): Git tarafından izlenen bir dosyanın silinmesidir.

1Changes not staged for commit:
2    deleted:    isimler.txt

Silme işlemini geri almak istersek:

1git restore isimler.txt

★ Staging Area’dan Çıkarma

Yanlışlıkla staging area’ya eklenen bir dosyayı çıkarmak (unstage) için:

1git restore --staged isimler.txt
💡 Eski kaynaklarda staging’den çıkarma için git reset HEAD <dosya> görebilirsiniz. Modern Git'te bunun yerine git restore --staged önerilir.

Git’in bir dosyayı tamamen izlemeyi bırakmasını istiyorsak (dosya diskten silinmez ama Git artık takip etmez):

1git rm --cached isimler.txt

Bu komut özellikle .gitignore'a sonradan eklenen dosyaları Git takibinden çıkarmak için kullanılır.

★ “git add” Komutu Hakkında Daha Fazlası

Kısmi ekleme (-p): Dosyadaki değişiklikleri parça parça (hunk) göstererek hangilerini eklemek istediğimizi sorar:

1git add -p

Bu komut her değişiklik bloğu için bize seçenekler sunar:

  • y — Bu bloğu ekle
  • n — Bu bloğu ekleme
  • s — Bloğu daha küçük parçalara böl
  • q — Çık

Bu sayede bir dosyadaki değişikliklerin yalnızca bir kısmını staging area’ya ekleyebiliriz.

📌 git add komutunun tüm parametreleri için: git-scm.com/docs/git-add

Git’e Kaydetme (git commit) 📸

git commit komutu

Staging area’daki değişiklikleri Git’e kalıcı olarak kaydetmek için:

1git commit

Bu komutu parametresiz çalıştırdığımızda varsayılan metin editörü (genellikle Vim) açılır ve commit mesajı yazmamızı bekler. Vim’den çıkmak için :wq yazıp Enter'a basabiliriz.

★ “git commit” Komutu Parametreleri

-m parametresi — Commit mesajını doğrudan terminalde yazmaya yarar:

1git commit -m "İsimler dosyası oluşturuldu"

-a parametresi — git add kullanmadan, yalnızca değişen (modified) dosyaları doğrudan commit eder. ⚠️ Yeni (untracked) dosyaları eklemez:

1git commit -am "İsimlerde düzenleme yapıldı"

--amend parametresi — Son commit mesajını düzeltir veya son commit'e yeni değişiklikler ekler:

1git commit --amend -m "Düzeltilmiş commit mesajı"
⚠️ --amend commit hash'ini değiştirir. Push edilmiş commit'lere amend yaparsak --force push gerekir. Ekip çalışmasında dikkatli olmamızda yarar var.

📌 git commit komutunun tüm parametreleri için: git-scm.com/docs/git-commit

★ İyi Commit Mesajı Nasıl Yazılır?

💡 Bu kısım makalenin en önemli kısımlarından birisi. Çünkü Git kullanırken yapılan en yaygın hatalardan biri kötü commit mesajlarıdır. Oysa iyi yazılmış bir commit mesajı, projenin geçmişini okunabilir hale getirir ve ekip içi iletişimi ciddi şekilde kolaylaştırır.

İyi commit mesajı nasıl olmalı?

  • Kısa ve açıklayıcı (50 karakter altı ideal)
  • Ne yaptığını anlatsın
  • Açık fiiller kullanalım: “düzeltildi”, “eklendi”, “güncellendi”

Örnek:

  • ❌ Kötü: degisiklik
  • ✅ İyi: Kullanıcı giriş formunda validasyon hatası düzeltildi
💡 Genelde büyük projelerde ve ekiplerde veya open source projelerde commit mesajlarını standart hale getirmek için bazı linter araçları kullanılır.

★ Commit Mesajı Standartları (Conventional Commits)

Büyük projelerde commit mesajlarının belirli bir standartta yazılması gerekir. Bu standartlar:

  • Commit geçmişini okunabilir yapar
  • Otomatik changelog üretimini sağlar
  • CI/CD süreçleri ile entegre çalışabilir
  • Semantic versioning ile uyumludur

Bu amaçla yaygın olarak Conventional Commits standardı kullanılır.

★ Commit Formatı

1feat(auth): kullanıcı giriş sistemi eklendi
2fix(player): ses kesilme hatası düzeltildi
3docs(readme): kurulum adımları güncellendi
  • feat — Yeni özellik eklendi
  • fix — Bir hata düzeltildi
  • docs — Dokümantasyon değişiklikleri
  • style — Kod formatı değişiklikleri (lint, boşluk vb.)
  • refactor — Kod davranışını değiştirmeyen refactor
  • test — Test eklendi veya güncellendi
  • chore — Build, config veya yardımcı işler
  • ci — CI/CD pipeline değişiklikleri
  • perf — Performans iyileştirmeleri
  • build — Build sistemi veya dependency değişiklikleri

Bu standardı otomatik kontrol etmek için:

  • commitlint → commit mesajlarını lint eder
  • Commitizen → commit yazarken interaktif yardım sağlar
💡 Her commit bir branch’e, tag’e veya HEAD’e bağlı olmak zorundadır. Bağlı olmayan commit’ler Git’in çöp toplama mekanizması (garbage collection) tarafından belirli bir zaman sonra (varsayılan 90 gün) otomatik olarak silinir. Garbage collection hakkında detaylara makalenin ilerleyen kısımlarında değindim.

Commit Geçmişi Görüntüleme (git log) 📜

git log komutu

Commit geçmişini görmek için:

1git log

Örnek çıktı:

1commit a1b2c3d4e5f6 (HEAD -> main)
2Author: Rabia Kaya <rabia@example.com>
3Date:   Mon Jun 9 2025
4
5İsimler dosyası oluşturuldu

★ Sık Kullanılan Parametreler

1git log --oneline                        # Her commit tek satırda gösterilir
2git log --graph                          # Dallanma yapısı ASCII art olarak çizilir
3git log --oneline --graph --decorate --all  # Branch/tag pointer'ları ile birlikte görsel geçmiş
4git log -n 5                             # Yalnızca son 5 commit
5git log --author="Rabia"                 # Belirli bir yazara ait commit'ler
6git log -- isimler.txt                   # Belirli bir dosyanın geçmişi
7git log --follow -- isimler.txt          # Dosya yeniden adlandırılsa bile geçmişi takip eder
8git log --since="2025-01-01"             # Belirli tarihten sonraki commit'ler

git log çıktısında gördüğümüz commit hash'leri (örn. a1b2c3d), git checkout, git reset, git revert gibi komutlarda belirli bir commit'e referans vermek için kullanılır.

📌 git log komutunun tüm parametreleri için: git-scm.com/docs/git-log

Farkları Görüntüleme (git diff) 🔎

git diff komutu

Dosyalardaki değişiklikleri satır satır görmek için:

1git diff

Bu komut, çalışma dizinindeki değişiklikler ile staging area arasındaki farkları gösterir.

★ Farklı Karşılaştırma Senaryoları

1git diff                         # Çalışma dizini vs staging area
2git diff --staged                # Staging area vs son commit
3git diff --cached                # --staged ile aynı işlevi görür
4git diff HEAD                    # Çalışma dizini vs son commit
5git diff <commit1> <commit2>     # İki commit arasındaki farklar
6git diff main..yeni-ozellik      # İki branch arasındaki farklar
7git diff -- isimler.txt          # Yalnızca belirli bir dosyanın farkları

Çıktıyı okumak:

1- Tuvana       # Silinen satır (kırmızı)
2+ Beril        # Eklenen satır (yeşil)

📌 git diff komutunun tüm parametreleri için: git-scm.com/docs/git-diff

Dosya Silme ve Taşıma (git rm & git mv) 🗑️

★ git rm

Git tarafından izlenen bir dosyayı hem diskten hem de Git takibinden silmek için:

1git rm isimler.txt
2git commit -m "isimler.txt silindi"

Dosyayı diskten silmeden yalnızca Git takibinden çıkarmak için:

1git rm --cached isimler.txt

★ git mv

Dosyayı taşımak veya yeniden adlandırmak için:

1git mv eski-isim.txt yeni-isim.txt
2git commit -m "Dosya adı değiştirildi"
💡 Git, dosya yeniden adlandırmalarını aslında içerik benzerliğinden algılar. git mv, arka planda dosyayı silip yeni isimle eklemekle aynı şeyi yapar; ancak tek komutla halletmek daha pratiktir.

Dallanma (git branch) 🌿

git branch nasıl kullanılır

Branch’ler, aynı proje üzerinde bağımsız çalışma alanları oluşturmamızı sağlar. Her branch, türetildiği branch’in o anki halinin bir kopyasıdır. Asıl kodumuzu bozmadan yeni özellikler geliştirebilir veya hataları düzeltebiliriz.

Git’in kendisi varsayılan olarak master branch adını kullanır. Ancak GitHub gibi platformlar 2020'den itibaren varsayılan branch adını main olarak belirlemiştir. Bu makalede örneklerde main kullanacağız.

★ Branch Listeleme

1git branch              # Yerel branch'leri listeler
2git branch -a           # Uzak (remote-tracking) branch'ler dahil tümünü listeler
💡 git branch -a çıktısında remotes/origin/main gibi görünen referanslar, uzak branch'in doğrudan kendisi değil; son fetch veya pull sonrası güncellenen yerel takip referanslarıdır.

★ Branch Oluşturma

1git branch yeni-isimler

Bu komutu çalıştırdıktan sonra git branch komutunu tekrar çalıştırırsak, yeni-isimler branch'inin oluştuğunu görürüz. Ancak hala main branch'indeyiz; branch'e geçiş yapmak için sonraki bölümü okuyalım.

★ Branch Silme

1git branch -d yeni-isimler     # Birleştirilmiş branch'i siler
2git branch -D yeni-isimler     # Zorla siler (birleştirilmemiş olsa bile)

★ Branch’i Yeniden Adlandırma

1git branch -m eski-ad yeni-ad

Branch ve Commit’ler Arasında Geçiş (git checkout / git switch) 🔄

Git 2.23 sürümünde git checkout komutunun iki farklı sorumluluğu (branch değiştirme + dosya geri alma) ayrıştırıldı. git switch branch geçişi, git restore dosya geri alma için önerilir. Ancak git checkout hala her iki iş için de çalışır.

★ Branch’ler Arasında Geçiş Yapmak

1git checkout yeni-isimler

veya Git 2.23+ sürümlerinde:

1git switch yeni-isimler

Kısayol, Oluştur ve Geç:

git branch komutunu ayrıca çalıştırmadan, yeni bir branch oluşturup o branch'e geçiş yapmak için:

1git checkout -b yeni-isimler
2# veya
3git switch -c yeni-isimler

★ Commit’e Geçiş Yapmak

git log çıktısında gördüğümüz herhangi bir commit hash'ini kullanarak, o commit'in durumuna geri dönebiliriz:

1git checkout a1b2c3d

⚠️ Bu komut bizi Detached HEAD durumuna geçirir. Bu durumda yaptığımız commit’ler hiçbir branch’e bağlı olmaz ve branch değiştirdiğimizde bu commit’lere erişmek zorlaşabilir. Değişikliklerimizi korumak istiyorsak yeni bir branch oluşturalım:

1git checkout -b kurtarma-branch
💡 HEAD ve Detached HEAD kavramları makalenin ilerleyen bölümlerinde detaylı olarak açıklanıyor.

★ Belirli Bir Commit’ten veya Branch’ten Dosya Almak

Belirli bir commit’teki veya branch’teki dosyanın halini çalışma dizinine getirmek için:

1# Belirli bir commit'teki dosya halini getir
2git checkout a1b2c3d -- isimler.txt
1# Başka bir branch'teki dosya halini getir
2git checkout main -- isimler.txt

Bu komut, dosyayı çalışma dizinimize ve staging area’ya kopyalar. Mevcut branch’imizden ayrılmayız.

💡 Eski kaynaklarda dosya geri alma için git checkout -- <dosya> görebilirsiniz. Modern kullanımda bunun yerine git restore önerilir.

Branch’leri Birleştirmek (git merge) 🤝

git merge komutu

Bir branch’teki değişiklikleri başka bir branch ile birleştirmek için git merge komutu kullanılır.

Örnek senaryo:

1# Yeni branch oluştur ve geçiş yap
2git checkout -b yeni-isimler
1# isimler.txt dosyasına "Rabia" ekle ve kaydet
2git add .
3git commit -m "Rabia eklendi"
1# main branch'ine geri dön
2git checkout main
1# yeni-isimler branch'ini main ile birleştir
2git merge yeni-isimler

★ Merge Türleri

Fast-Forward Merge: Hedef branch’te (main) hiçbir yeni commit yoksa Git, branch pointer’ını ilerletir. Yeni bir merge commit oluşmaz:

1main:    ABC
2                   (fast-forward)
3feature:          CDE

Fast-forward merge’ü engelleyip her zaman merge commit oluşturmak için:

1git merge --no-ff yeni-isimler

Three-Way Merge: Her iki branch’te de yeni commit varsa Git, ortak bir atayı bularak üç yönlü karşılaştırma yapar ve yeni bir merge commit oluşturur.

💡 Feature branch’imizi güncel tutmak için ana branch’ten değişiklikleri düzenli olarak alabiliriz. Bu işlem merge veya rebase ile yapılabilir:
git checkout yeni-isimler
git merge main

veya

git rebase main

Çakışmalar (Git Conflicts) ⚡

Git de Conflict durumunda ne yapmalıyız

İki branch’te aynı dosyanın aynı satırları farklı şekilde değiştirildiğinde çakışma (conflict) oluşur.

Örnek senaryo:

main branch'inde isimler.txt dosyamız şöyle olsun:

1Eda
2Beyza
3Tuvana
4Melis

1. Yeni branch oluşturup 3. satırdaki Tuvana'yı Beril olarak değiştirelim:

1git checkout -b conflict-ornek
2# isimler.txt"Tuvana" satırını "Beril" olarak değiştir
3git commit -am "Tuvana yerine Beril yazıldı"

2. main’e dönüp aynı satırı farklı bir isimle değiştirelim:

1git checkout main
2# isimler.txt"Tuvana" satırını "Rabia" olarak değiştir
3git commit -am "Tuvana yerine Rabia yazıldı"

3. Birleştirmeyi deneyelim:

1git checkout conflict-ornek
2git merge main

Git şu çakışma mesajını verir:

1CONFLICT (content): Merge conflict in isimler.txt
2Automatic merge failed; fix conflicts and then commit the result.

Dosyayı açtığımızda Git, çakışan bölümleri işaretler:

1Eda
2Beyza
3<<<<<<< HEAD
4Beril
5=======
6Rabia
7>>>>>>> main
8Melis
  • <<<<<<< HEAD ile ======= arasındaki kısım: Bizim branch'imizdeki değişiklik
  • ======= ile >>>>>>> main arasındaki kısım: Birleştirmeye çalıştığımız branch'teki değişiklik

Çakışmayı çözmek için:

  1. Dosyayı düzenleyip istediğimiz içeriği bırakalım
  2. <<<<<<<, =======, >>>>>>> işaretlerini silelim
  3. Kaydedelim ve commit edelim:
1git add isimler.txt
2git commit -m "Conflict çözüldü, Beril olarak güncellendi"

★ Hızlı Çözüm: Ours veya Theirs

Çakışmada doğrudan bir tarafı seçmek istersek:

1# Kendi branch'imizdeki değişikliği kabul et
2git checkout --ours isimler.txt
1# Birleştirilen branch'teki değişikliği kabul et
2git checkout --theirs isimler.txt
1git add isimler.txt
2git commit -m "Conflict çözüldü"

★ Birleştirmeyi İptal Etmek ( — abort)

Çakışma çıktığında henüz çözüm yapmadan birleştirme işlemini tamamen iptal etmek istersek:

1git merge --abort

Bu komut, merge işlemini iptal eder ve dosyalarımızı merge öncesindeki durumuna geri döndürür.

★ Birleştirmeye Devam Etmek ( — continue)

Çakışmaları dosya üzerinde çözdükten ve git add ile staging area'ya ekledikten sonra:

1git merge --continue

Bu komut, git commit ile aynı işlevi görür ancak devam eden bir merge işlemi olduğunu açıkça ifade eder.

💡 VS Code gibi editörler, conflict işaretlerini otomatik algılar ve “Accept Current”, “Accept Incoming”, “Accept Both” gibi butonlarla çözümü kolaylaştırır. Alternatif olarak git mergetool komutuyla yapılandırdığımız harici araçları da kullanabiliriz.
Ek olarak bir çok IDE’nin (WebsStorm, PhpStorm, PyCharm vb.) kendi merge editörü mevcut, arayüzden daha hızlı şekilde ilerlememizi sağlıyor.

Commitleri Başka Bir Branch Üzerine Yeniden Uygulama (git rebase) 🔀

git reabase komutu

Rebase, bir branch’in commit’lerini başka bir branch’in ucuna yeniden uygulayarak doğrusal (linear) bir geçmiş oluşturur.

1git checkout yeni-ozellik
2git rebase main

Bu komut şunu yapar:

  1. yeni-ozellik branch'indeki commit'leri geçici olarak kaldırır
  2. main branch'indeki son commit'leri alır
  3. yeni-ozellik'in commit'lerini main'in en son commit'inin üzerine tek tek yeniden uygular

★ Interactive Rebase

Son commit’leri düzenlemek, birleştirmek, sırasını değiştirmek veya silmek için:

1git rebase -i HEAD~3

Açılan editörde her commit’in başındaki komutu değiştirebiliriz:

1pick a1b2c3d İsimler eklendi
2pick d4e5f6g Yeni isimler düzenlendi
3pick h7i8j9k Beyza eklendi

Kullanılabilir komutlar:

  • pick — Commit’i olduğu gibi bırak
  • reword — Commit mesajını değiştir
  • squash — Bir önceki commit ile birleştir (mesajları birleştirir)
  • fixup — Bir önceki commit ile birleştir (bu commit’in mesajını siler)
  • drop — Commit’i tamamen sil
  • edit — Commit’i düzenlemek için dur

★ Rebase — onto

Bir branch’i, türetildiği branch’ten ayırıp başka bir branch’in üzerine taşımak için:

1git rebase --onto main feature bugfix
2# bugfix branch'ini feature'dan ayırıp main üzerine al

★ Rebase vs Merge

  • Merge
  1. Branch’leri birleştirir ve merge commit oluşturur
  2. Commit geçmişini değiştirmez (güvenlidir)
  3. Conflict varsa tek seferde çözülür
  • Rebase
  1. Commit’leri başka bir branch’in üzerine yeniden uygular
  2. Daha temiz bir geçmiş oluşturur
  3. Commit hash’lerini yeniden yazar
  4. Conflict oluşursa her commit için ayrı ayrı çözülür
  5. Genellikle kişisel branch’lerde kullanılır
⚠️ Başkalarının da kullandığı paylaşılan commit geçmişi bulunan branch’lerde sorunlara yol açabilir. Kendi branch’imizde (kimse kullanmıyorsa) dikkatli şekilde kullanabiliriz.

Rebase sırasında conflict çıkarsa:

1# Conflict'i dosyada çözün, ardından:
2git add .
3git rebase --continue
1# veya rebase'i tamamen iptal için:
2git rebase --abort

HEAD Kavramı 🎯

Git HEAD kavramı

HEAD, Git’te “şu anda neredeyiz?” sorusunun cevabıdır. Üzerinde çalıştığımız commit’i gösteren bir işaretçidir (pointer).

Normalde HEAD bir branch’i işaret eder ve o branch’in son commit’ine karşılık gelir:

1cat .git/HEAD
2# Çıktı: ref: refs/heads/main

Bu, “HEAD → main → son commit” anlamına gelir. Yeni bir commit yaptığımızda HEAD otomatik olarak bu yeni commit’e ilerler.

★ Detached HEAD

git checkout <commit-hash> ile doğrudan bir commit'e geçtiğimizde, HEAD artık bir branch'i değil doğrudan o commit'i işaret eder:

1git checkout a1b2c3d

Bu durumda yapılan commit’ler hiçbir branch’e bağlı olmadığından, başka bir branch’e geçtiğimizde bu commit’lere erişmek zorlaşabilir. Değişikliklerimizi korumak istiyorsak:

1git checkout -b yeni-branch-adi
💡 Detached HEAD’de yapılan commit’ler hemen yok olmaz. git reflog ile hash'lerini bulup kurtarabiliriz; ancak reflog süresi (varsayılan olarak 90 gün olarak gelir) dolduktan sonra garbage collection tarafından temizlenirler.

Etiketleme (git tag) 🏷️

Git tag komutu

Tag’ler, belirli commit’lere kalıcı etiketler (yer işaretleri) eklemek için kullanılır. Genellikle sürüm numaralarını işaretlemek için tercih edilir. Branch’lerden farkı, tag’lerin sabit olması ve hareket etmemesidir.

★ Lightweight Tag

Basit bir işaretçidir, ek bilgi saklamaz:

1git tag v1.0

★ Annotated Tag (Açıklamalı)

Yazar, tarih ve mesaj bilgisi içeren tag’dir. Sürüm etiketleri için önerilir:

1git tag -a v1.0 -m "İlk kararlı sürüm"

★ Belirli Bir Commit’e Tag Ekleme

1git tag -a v0.9 a1b2c3d -m "Beta sürümü"

★ Tag İşlemleri

1git tag                    # Tüm tag'leri listele
2git show v1.0              # Tag detaylarını göster
3git tag -d v1.0            # Yerel tag'i sil
4git push origin v1.0       # Tag'i uzak repoya gönder
5git push origin --tags     # Tüm tag'leri gönder

Değişiklikleri Geri Alma ↩️

git restore, git reset, git revert

Çalışma dizinindeki veya staging area’daki değişiklikleri geri alır:

1# Dosyayı son commit haline döndürür (çalışma dizinindeki değişiklik gider)
2git restore isimler.txt
1# Staging area'dan çıkarır ama dosya değişmez
2git restore --staged isimler.txt

★ git reset

Commit geçmişini geri almak için kullanılır. git reset, esas olarak branch'in işaret ettiği commit'i geriye taşır; kullanılan moda göre staging area ve çalışma dizini de buna uyarlanır.

Üç modu vardır:

--soft: Commit geri alınır ama değişiklikler staging area'da kalır. Commit mesajını veya commit grubunu düzeltmek istediğimizde kullanışlıdır:

1git reset --soft HEAD~1

--mixed (varsayılan): Commit geri alınır, değişiklikler çalışma dizininde kalır ama staging area'dan çıkar:

1git reset HEAD~1
2# veya
3git reset --mixed HEAD~1

--hard: Commit ve tüm değişiklikler tamamen silinir:

1git reset --hard HEAD~1
⚠️ --hard parametresi değişiklikleri kalıcı olarak siler. Dikkatli olmamızda yarar var.
Hard reset yaptığımız commit (makalenin diğer bölümlerinde bahsettiğim) “garbage collection” içinde duruyorsa, git reflog ile halen kurtarmamız mümkün. Ancak herhangi bir brach, tag veya HEAD’e bağlı olmayabilir. Garbage collection süresi default 90 gün. Yani bu durumda 90 gün içinde yaptığımız hard reset commit’lerini, biraz bulması zor olsa da kurtarabiliriz. Burada da en önemli konu, commit mesajlarını nasıl yazdığımız. Commit mesajlarını aynı ya da birbirine benzer şekilde yazdıysak vay halinize, kaybolan commit’ler için bir bardak soğuk su içebiliriz 😁

HEAD~1: Bir önceki commit. HEAD~3: Üç önceki commit. Belirli bir commit hash'i de kullanabiliriz:

1git reset --soft a1b2c3d

★ git revert

Belirli bir commit’in değişikliklerini geri alan yeni bir commit oluşturur. Geçmişi silmez, bu yüzden paylaşılan branch’lerde güvenle kullanılabilir:

1git revert a1b2c3d

Merge commit revert etmek:

Merge commit’leri revert ederken hangi parent’ı temel alacağımızı -m parametresiyle belirtmemiz gerekir:

1git revert -m 1 <merge-commit-hash>

★ Hangisini kullanmalıyız?

  • Henüz commit etmediğimiz dosya değişiklikleri → git restore
  • Henüz push etmediğimiz commit’ler → git reset
  • Push edilmiş commit’leri güvenle geri almak → git revert

Referans Geçmişi (git reflog) 🕵️

Git reflog — kaybolan commitleri geri getirme

git reflog, HEAD'in tüm hareketlerini kronolojik olarak kaydeden bir güvenlik ağıdır. git reset --hard gibi tehlikeli bir komut çalıştırdıktan sonra bile kaybolan commit'leri buradan bulabiliriz:

1git reflog

Örnek çıktı:

1a1b2c3d HEAD@{0}: reset: moving to HEAD~1
2f4e5d6c HEAD@{1}: commit: Beril eklendi
3b7a8c9d HEAD@{2}: commit: İsimler dosyası oluşturuldu

Kaybolan commit’in hash’ini bulup geri dönebiliriz:

1git reset --hard f4e5d6c
💡 reflog kayıtları varsayılan olarak 90 gün boyunca saklanır.

Değişiklikleri Rafa Kaldırma (git stash) 📦

Git stash komutu

Üzerinde çalıştığımız değişiklikleri commit etmeden geçici olarak saklamak için kullanılır. Acil bir iş çıktığında branch değiştirmemiz gerektiğinde çok işe yarar.

★ Temel Komutlar

1git stash                              # Değişiklikleri rafa kaldır
2git stash push -m "Açıklama"           # Açıklamayla birlikte sakla
3git stash -u                           # Untracked dosyaları da dahil et
4git stash --all                        # Ignored dosyalar dahil her şeyi sakla
5git stash list                         # Raftaki değişiklikleri listele
6git stash show                         # Son saklananın özetini göster
7git stash show -p                      # Son saklananın detaylı farkını göster
💡 Eski kaynaklarda git stash save "Açıklama" görebilirsiniz. Modern Git'te bunun yerine git stash push -m "Açıklama" önerilir.
⚠️ Varsayılan git stash komutu untracked dosyaları dahil etmez. Bunları da saklamak için -u parametresini kullanabiliriz.

★ Geri Getirme

1git stash pop                    # Son saklananı geri getir VE raftan sil
2git stash apply                  # Son saklananı geri getir, rafta da kalsın
3git stash apply stash@{2}        # Belirli bir stash'i geri getir

★ Temizleme

1git stash drop                   # Son saklananı raftan sil
2git stash drop stash@{1}         # Belirli bir stash'i sil
3git stash clear                  # Raftaki her şeyi temizle

★ Örnek Senaryo

isimler.txt üzerinde yeni isimler ekliyoruz. Tam o sırada acil bir düzeltme yapmamız gerekiyor:

1# Yarım kalan işi rafa kaldır
2git stash push -m "Tuvana'nın bilgilerini güncelliyordum"
1# main'e geç, düzeltmeyi yap
2git checkout main
3git commit -am "Acil düzeltme yapıldı"
1# Eski branch'e dön, kaldığın yerden devam et
2git checkout yeni-ozellik
3git stash pop

Dosya Yoksayma (.gitignore) 🙈

Git’in belirli dosya ve klasörleri izlememesi için proje kök dizininde .gitignore dosyası oluşturulur:

1# Bağımlılık klasörleri
2node_modules/
3vendor/
1# Derleme çıktıları
2dist/
3build/
4*.class
1# Ortam değişkenleri (şifreler, API key'ler vb.)
2.env
3.env.local
1# IDE dosyaları
2.idea/
3.vscode/
4*.swp
1# İşletim sistemi dosyaları
2.DS_Store
3Thumbs.db
1# Log dosyaları
2*.log
1# Derleme dosyaları
2*.o
3*.exe

★ Önemli Notlar

  • .gitignore dosyası oluşturulmadan önce Git tarafından izlenmeye başlanan dosyalar, .gitignore'a eklendiğinde otomatik olarak izlenmekten çıkmaz. Bu dosyaları izlemeden çıkarmak için:
1git rm --cached dosya-adi.txt
  • Boş klasörler Git tarafından izlenmez. Boş bir klasörü repository’ye eklemek istiyorsak içine .gitkeep adında boş bir dosya koyabiliriz. .gitkeep Git'e özgü bir özellik değil; topluluk tarafından benimsenen bir konvansiyondur. Dosya adı herhangi bir şey olabilir ama .gitkeep yaygın olarak tercih edilir.

★ Global .gitignore

Tüm projelerimizde geçerli olacak global bir .gitignore dosyası tanımlayabiliriz. Bu, .DS_Store, Thumbs.db, editör geçici dosyaları gibi sisteme özel dosyalar için kullanışlıdır:

1git config --global core.excludesfile ~/.gitignore_global

Ardından ~/.gitignore_global dosyasına global kurallarımızı ekleyelim.

📌 Farklı proje türleri için hazır .gitignore şablonları: github.com/github/gitignore

Uzak Repository (Remote) 🌐

git clone, git push, git pull, git fetch komutları

Şu ana kadar tüm işlemler yerel makinemizde gerçekleşti. Projemizi GitHub, GitLab veya Bitbucket gibi platformlarda barındırmak ve başkalarıyla paylaşmak için uzak (remote) repository kullanılır.

★ HTTPS vs SSH

Uzak repository’ye bağlanırken iki yöntem kullanılır:

1# HTTPSKullanıcı adı/şifre veya token ile kimlik doğrulama
2git remote add origin https://github.com/kullanici/proje.git
1# SSHSSH key ile kimlik doğrulama (daha pratik)
2git remote add origin git@github.com:kullanici/proje.git
💡 SSH kullanmak için önce SSH key oluşturmamız ve platformumuza (GitHub, GitLab vb.) eklememiz gerekir. Detaylı adımlar için: docs.github.com/en/authentication/connecting-to-github-with-ssh

★ Uzak Repo Ekleme

1git remote add origin https://github.com/kullanici/proje.git

Burada origin, uzak repository'nin yerel takma adıdır. Geleneksel olarak origin kullanılır ancak istediğimiz herhangi bir isim verebiliriz.

★ Remote-Tracking Branch Kavramı

origin/main gibi referanslar, uzak repodaki main branch'inin yerelde tutulan takip kopyasıdır. Bu, doğrudan uzak sunucunun canlı hali değil; son fetch veya pull sonrası güncellenen yerel referanstır. Bu sayede çevrimdışıyken bile uzak branch'in en son bilinen durumunu görebiliriz.

★ Uzak Repoları Listeleme

1git remote -v

Örnek çıktı:

1origin  https://github.com/kullanici/proje.git (fetch)
2origin  https://github.com/kullanici/proje.git (push)

★ Uzak Repo URL Değiştirme

1git remote set-url origin https://github.com/kullanici/yeni-proje.git

★ Uzak Repo Kaldırma

1git remote remove origin

Klonlama (git clone) 📥

Uzak bir repository’yi yerel makinemize kopyalamak için:

1git clone https://github.com/kullanici/proje.git

Bu komut:

  1. Proje adında bir klasör oluşturur
  2. .git klasörünü oluşturur
  3. Tüm geçmişi ve dosyaları indirir
  4. origin remote'unu otomatik olarak ayarlar

★ Ek Parametreler

1# Belirli bir branch'i klonla
2git clone -b branch-adi https://github.com/kullanici/proje.git
1# Farklı bir klasör adıyla klonla
2git clone <a href="https://github.com/kullanici/proje.git">https://github.com/kullanici/proje.git</a> benim-projem
1# Yalnızca son commit'i klonla (büyük projelerde hız için)
2git clone --depth 1 <a href="https://github.com/kullanici/proje.git">https://github.com/kullanici/proje.git</a>

Değişiklikleri Çekme (git fetch & git pull) ⬇️

★ git fetch

Uzak repository’deki değişiklikleri indirir ama yerel dosyalarımıza birleştirmez. Değişiklikleri önce incelemek istediğimizde kullanışlıdır:

1git fetch origin

Fetch sonrası uzak branch’teki değişiklikleri incelemek için:

1git diff main origin/main

Beğenirsek birleştiririz:

1git merge origin/main

★ git pull

fetch + merge işlemini tek komutla yapar. Uzak repository'deki değişiklikleri hem indirir hem yerel branch'imizle birleştirir:

1git pull origin main

Daha temiz bir geçmiş için rebase ile pull:

1git pull --rebase origin main
💡 git pull --rebase'i varsayılan davranış yapmak için:
git config --global pull.rebase true

★ Pull vs Fetch

  • git fetch: İndirir ama birleştirmez, daha güvenlidir çünkü önce inceleme şansı verir, inceleyip sonra birleştirmek istediğimizde kullanırız
  • git pull: İndirir ve otomatik birleştirir, conflict çıkabilir, hızlıca güncellemek istediğimizde kullanırız
💡 git pull = git fetch + git merge

Değişiklikleri Gönderme (git push) ⬆️

Yerel commit’lerimizi uzak repository’ye göndermek için:

1git push origin main

★ İlk Push için Upstream Ayarlama

Yeni bir branch’i ilk kez gönderirken -u (upstream) parametresi kullanılır. Bu, yerel branch ile uzak branch arasında kalıcı bir bağlantı (tracking relationship) kurar. Bu sayede sonraki push'larda yalnızca git push yazmamız yeterli olur:

1git push -u origin yeni-ozellik

Mevcut bir branch’in upstream’ini değiştirmek veya ayarlamak için:

1git branch --set-upstream-to=origin/main main

★ Diğer Parametreler

1git push origin --delete branch-adi    # Uzak branch'i sil
2git push --force                       # veya -f  ⚠️ kullanırken ekstra dikkat etmekte fayda var
3git push --force-with-lease            # Daha güvenli zorla gönderme
⚠️ --force parametresi uzak repository'deki geçmişi yeniden yazar. Ekip arkadaşlarımızın çalışmalarını kaybettirebilir. --force-with-lease tercih edersek; uzak branch'te bizim bilmediğimiz bir commit varsa push'u reddeder.

Fork ve Pull Request 🍴

Open source projeye katkıda bulunma

★ Fork

Başka birinin repository’sini kendi GitHub/GitLab hesabımıza kopyalamaktır. Platformun arayüzündeki Fork butonu ile yapılır. Fork, orijinal repo ile bağlantısını korur.

★ Pull Request (PR) / Merge Request (MR)

Fork’ladığımız veya oluşturduğumuz branch’teki değişikliklerin ana repository’ye kabul edilmesi için açılan istektir. GitHub’da Pull Request, GitLab’da Merge Request olarak adlandırılır.

Tipik iş akışı:

  1. Repository’yi fork’layalım
  2. Yerel makinemize klonlayalım
  3. Yeni bir branch oluşturalım
  4. Değişikliklerimizi yapalım, commit edelim
  5. Fork’umuza push edelim
  6. Platform üzerinden Pull Request açalım
  7. Kod incelemesi (code review) yapılır
  8. Onaylanırsa ana branch’e birleştirilir

Branching Stratejileri 🗺️

Ekiplerin Git’i nasıl kullandığına dair yaygın stratejiler:

★ Git Flow

En yaygın ve kapsamlı strateji. Uzun süreli projelerde tercih edilir:

  • main — Yayınlanan kararlı sürüm
  • develop — Geliştirme branch’i
  • feature/* — Yeni özellikler için
  • release/* — Sürüm hazırlığı için
  • hotfix/* — Acil düzeltmeler için

★ GitHub Flow

Basit ve sürekli dağıtım (CD / continuous deployment) yapan ekipler için:

  • main — Her zaman dağıtılabilir durumda
  • feature branch — Yeni özellik veya düzeltme
  • Pull Request — Kod incelemesi ve birleştirme

★ Trunk-Based Development

Kısa ömürlü branch’ler kullanılır ve sürekli olarak ana branch’e (trunk) merge edilir. Büyük ekiplerde sürekli entegrasyon (CI) ile birlikte kullanılır.

💡 Hangi stratejiyi kullanacağımız ekip büyüklüğüne, proje türüne ve dağıtım sıklığına bağlıdır. Küçük ekipler için GitHub Flow genellikle yeterlidir.

Seçerek Alma (git cherry-pick) 🍒

Git cherry pick komutu

Başka bir branch’ten tüm branch’i birleştirmek yerine, yalnızca belirli bir commit’i kendi branch’imize almak için:

1git cherry-pick a1b2c3d

Örnek senaryo:

yeni-ozellik branch'inde 5 commit var ama yalnızca birinde yapılan hata düzeltmesini main'e almak istiyoruz:

1git checkout main
2git cherry-pick f4e5d6c

Birden fazla commit almak için:

1git cherry-pick a1b2c3d f4e5d6c

Cherry-pick sırasında conflict çıkarsa, normal merge conflict’te olduğu gibi çözüp devam edelim:

1git add .
2git cherry-pick --continue
1# veya iptal edelim:
2git cherry-pick --abort

Satır Bazında Geçmiş (git blame) 🔬

Git Blame komutu

Bir dosyanın her satırını en son kimin, ne zaman değiştirdiğini görmek için:

1git blame isimler.txt

Örnek çıktı:

1a1b2c3d4 (Beril Dumanlı     2025-01-10) Eda
2f4e5d6c7 (Sitare Demir      2025-02-15) Beyza
3b7a8c9d0 (Arya Çelik        2025-03-22) Tuvana
4a1b2c3d4 (Beril Dumanlı     2025-01-10) Melis
💡 Yukarıdaki örnekte ilk ve son satır aynı kişi tarafından değiştirilmiş farklı satırlar. Arada kalan 2 ve 3. satır ise farklı kişiler taradından değiştirilmiş satırlar

★ Ek Parametreler

1git blame -L 5,10 isimler.txt     # Yalnızca 5-10 arası satırlar
2git blame -e isimler.txt           # Email adresiyle göster
3git blame -w isimler.txt           # Boşluk değişikliklerini yoksay

Bir hatanın veya değişikliğin kaynağını bulmak için kullanışlıdır.

Arama (git grep) 🔎

Repository’deki dosyaların içeriğinde metin aramak için:

1git grep "Beril"

Örnek çıktı:

1isimler.txt:Beril
2notlar.txt:Beril'in notu eklendi

★ Ek Parametreler

1git grep -n "Beril"                  # Satır numarası ile göster
2git grep -c "Beril"                  # Her dosyada kaç eşleşme var
3git grep -i "beril"                  # Büyük/küçük harf duyarsız ara
4git grep "Beril" -- "*.txt"          # Yalnızca .txt dosyalarında ara
5git grep "Beril" a1b2c3d             # Belirli bir commit'teki dosyalarda ara
💡 git grep, grep'ten farklı olarak yalnızca Git tarafından izlenen dosyalarda arar. .gitignore'da listelenen dosyaları atlar, örneğin bir Node.js projesinde node_modules gibi klasörlerde boşuna aramaz ve çok daha hızlıdır. Çünkü node_modules klasörünü genelde .gitignore ‘a yazarız
node_modules gibi klasörlerde boşuna aramaz ve çok daha hızlıdır.

İkili Arama ile Hata Bulma (git bisect) 🐛

Git bisect komutu

Projemizde bir hata var ama hangi commit’te ortaya çıktığını bilmiyoruz. git bisect, ikili arama (binary search) algoritmasıyla yüzlerce commit arasından hatayı oluşturan commit'i hızlıca bulur.

★ Kullanım

1# Bisect'i başlat
2git bisect start
1# Şu anki commit'in hatalı olduğunu belirt
2git bisect bad
1# Çalıştığından emin olduğumuz eski bir commit'i belirt
2git bisect good a1b2c3d

Git otomatik olarak ortadaki bir commit’e checkout yapar. Projeyi test edelim:

1# Eğer hata bu commit'te de varsa:
2git bisect bad
1# Eğer bu commit'te hata yoksa:
2git bisect good

Git, her adımda arama alanını yarıya indirir. Birkaç adımda hatalı commit’i bulur:

1f4e5d6c is the first bad commit

İşimiz bittiğinde:

1git bisect reset
💡 128 commit varsa git bisect en fazla 7 adımda hatalı commit'i bulur. (log₂128 = 7)

Commit Detaylarını Görüntüleme (git show) 🔍

Tek bir commit’in detaylarını (yazar, tarih, mesaj ve yapılan değişiklikler) görmek için:

1git show              # Son commit'in detayları
2git show a1b2c3d      # Belirli bir commit'in detayları
3git show v1.0          # Tag'in işaret ettiği commit'in detayları

git log geçmişin listesini gösterirken, git show tek bir commit'in tam içeriğini (diff dahil) gösterir.

İzlenmeyen Dosyaları Temizleme (git clean) 🧹

Git tarafından izlenmeyen (untracked) dosyaları çalışma dizininden silmek için:

1git clean -n           # Neler silinecek önce göster (dry-run)
2git clean -f           # İzlenmeyen dosyaları sil
3git clean -fd          # Dosya ve klasörleri sil
4git clean -fdx         # .gitignore'daki dosyalar dahil her şeyi sil
⚠️ git clean geri alınamaz. Silmeden önce mutlaka -n (dry-run) ile kontrol edelim.

Git Hooks🪝

Hooks, belirli Git olaylarında otomatik olarak çalışan script’lerdir. .git/hooks/ klasöründe bulunurlar.

★ Sık Kullanılan Hook’lar

  • pre-commit — Commit öncesi çalışır (lint, format kontrolü)
  • commit-msg — Commit mesajı yazıldıktan sonra çalışır (mesaj formatı kontrolü)
  • pre-push — Push öncesi çalışır (test çalıştırma)
  • post-merge — Merge sonrası çalışır (bağımlılık güncelleme)

★ Örnek: Commit Öncesi Lint Kontrolü

.git/hooks/pre-commit dosyası oluşturalım ve çalıştırılabilir yapalım:

1#!/bin/sh
2npm run lint
3if [ $? -ne 0 ]; then
4  echo "Lint hataları var. Commit iptal edildi."
5  exit 1
6fi
1chmod +x .git/hooks/pre-commit
💡 .git/hooks/ klasöründeki hook'lar repository ile paylaşılmaz. Ekip genelinde hook paylaşımı için Husky gibi araçlar kullanılabilir.

Alt Projeler (Submodule & Subtree) 📦

Büyük projelerde başka repository’leri kendi projemize dahil etmemiz gerekebilir.

★ git submodule

Bir repository içinde başka bir repository’yi referans olarak tutar. Alt proje bağımsız kalır, sadece belirli bir commit’e işaret edilir:

1git submodule add https://github.com/kullanici/kutuphane.git libs/kutuphane
2git commit -m "Kütüphane submodule olarak eklendi"

Submodule içeren bir repo klonlandığında alt projeler otomatik inmez:

1git clone --recurse-submodules <url>
2# veya klonladıktan sonra:
3git submodule update --init --recursive

★ git subtree

Başka bir repository’nin kodunu doğrudan projemize kopyalar. Submodule’dan daha basittir ama repo boyutunu artırır:

1git subtree add --prefix=libs/kutuphane https://github.com/kullanici/kutuphane.git main --squash
💡 Submodule daha yaygın kullanılır ancak yönetimi karmaşıktır. Subtree daha basit bir alternatiftir. İhtiyacımıza göre tercih edebiliriz

Git Garbage Collection (git gc) 🗑️

Git, iç yapısında kullanılmayan nesneleri (commit, blob, tree) biriktirir. git gc bu nesneleri temizler ve repository'yi optimize eder:

1git gc

★ Ne Zaman Çalışır?

  • Git bazı komutlarda (git merge, git rebase vb.) otomatik olarak gc tetikler
  • Manuel olarak da çalıştırabiliriz

★ Neler Temizlenir?

  • Hiçbir branch, tag veya HEAD tarafından referans edilmeyen orphan (yetim) commit’ler
  • reflog süresi dolan kayıtlar (varsayılan 90 gün)
  • Kullanılmayan Git objeleri
1git gc --aggressive       # Daha derin optimizasyon (yavaş ama etkili)
2git gc --prune=now        # Tüm erişilemeyen objeleri hemen sil
⚠️ Normal şartlarda git gc'yi manuel çalıştırmamız gerekmez. Git bunu arka planda otomatik olarak yapar.

📌 Detaylı bilgi: git-scm.com/docs/git-gc

Git Internals: Kısa Bir Bakış 🧬

Git Internals kısa bakış atalım

Git’in .git klasörünün içinde neler olduğuna kısaca bakalım:

1.git/
2├── HEAD              # Şu anki branch'e referans
3├── config            # Repository yapılandırması
4├── objects/          # Tüm Git objeleri (commit, tree, blob)
5├── refs/             # Branch ve tag referansları
6│   ├── heads/        # Yerel branch'ler
7│   └── tags/         # Tag'ler
8├── hooks/            # Otomatik tetiklenen script'ler
9└── index             # Staging area verisi

★ Git’in Üç Temel Objesi

  • Blob — Dosya içeriğini saklar (dosya adını saklamaz)
  • Tree — Bir dizinin yapısını saklar (hangi blob hangi dosya adına karşılık geliyor)
  • Commit — Bir anlık görüntüyü (snapshot) temsil eder; tree, yazar, tarih ve mesaj bilgisini içerir

Git, geleneksel olarak her objeyi SHA-1 hash’i ile tanımlar. Bu hash, objenin içeriğinden üretilir. Yeni sürümlerde SHA-256 desteği de bulunmaktadır.

1# Bir objenin içeriğini görmek için:
2git cat-file -p a1b2c3d
1# Objenin tipini görmek için:
2git cat-file -t a1b2c3d
💡 Git Internals konusu başlı başına kapsamlı bir konu olduğu için bu konuyu ayrı bir makalede detaylı olarak ele alacağız.

Git Komutlarını Özetleyelim 📋

Git komutları özet tablosu

★ Temel Komutlar

  • git init — Yeni repository oluşturur
  • git clone <url> — Uzak repoyu klonlar
  • git status — Durumu gösterir
  • git add <dosya> — Staging area'ya ekler
  • git add . — Tüm değişiklikleri ekler
  • git commit -m "mesaj" — Commit oluşturur
  • git commit -am "mesaj" — Değişen dosyaları ekler ve commit oluşturur
  • git show <hash> — Commit detaylarını gösterir

★ Dosya İşlemleri

  • git rm <dosya> — Dosyayı siler ve staging'e ekler
  • git rm --cached <dosya> — Git takibinden çıkarır (disk silinmez)
  • git mv <eski> <yeni> — Dosyayı taşır/yeniden adlandırır
  • git clean -fd — İzlenmeyen dosya ve klasörleri siler

★ Geçmiş ve Farklar

  • git log — Commit geçmişini gösterir
  • git log --oneline --graph --decorate --all — Görsel commit geçmişi
  • git diff — Dosya farklarını gösterir
  • git blame <dosya> — Satır satır kimin değiştirdiğini gösterir
  • git reflog — HEAD hareket geçmişini gösterir
  • git shortlog -sn — Kişi bazlı commit sayıları

★ Dallanma ve Birleştirme

  • git branch <ad> — Yeni branch oluşturur
  • git branch -d <ad> — Branch siler
  • git checkout <branch> — Branch'e geçiş yapar
  • git checkout -b <ad> — Oluştur ve geç
  • git switch <branch> — Branch'e geçiş yapar (modern)
  • git merge <branch> — Branch'leri birleştirir
  • git merge --no-ff <branch> — Her zaman merge commit oluşturur
  • git merge --abort — Birleştirmeyi iptal eder
  • git rebase <branch> — Commit'leri yeniden temellendirir
  • git rebase --onto <yeni-temel> <eski-temel> <branch> — Branch'i farklı bir temele taşır
  • git cherry-pick <hash> — Belirli commit'i alır

★ Geri Alma

  • git restore <dosya> — Dosya değişikliğini geri alır
  • git restore --staged <dosya> — Staging'den çıkarır
  • git reset --soft HEAD~1 — Commit'i geri alır, değişiklikler staging'de
  • git reset --hard HEAD~1 — Commit ve değişiklikleri tamamen siler
  • git revert <hash> — Geri alma commit'i oluşturur

★ Geçici Saklama

  • git stash — Değişiklikleri geçici saklar
  • git stash push -m "mesaj" — Açıklamayla saklar
  • git stash -u — Untracked dosyalar dahil saklar
  • git stash pop — Son saklananı geri getirir
  • git stash list — Saklananları listeler

★ Uzak Repository

  • git remote add <ad> <url> — Uzak repo ekler
  • git remote -v — Uzak repoları listeler
  • git fetch — Uzak değişiklikleri indirir
  • git pull — İndirir ve birleştirir
  • git pull --rebase — İndirir ve rebase ile birleştirir
  • git push — Uzak repoya gönderir
  • git push -u origin <branch> — Branch'i ilk kez gönderir
  • git push --force-with-lease — Güvenli zorla gönderme

★ Etiketleme ve Arama

  • git tag <ad> — Etiket ekler
  • git tag -a <ad> -m "mesaj" — Açıklamalı etiket ekler
  • git grep "metin" — Dosya içeriğinde arar
  • git bisect start — İkili arama ile hata bulur

★ Yapılandırma Kısayolları

  • git config --global alias.st status — git st kısayolu
  • git config --global alias.co checkout — git co kısayolu
  • git config --global alias.br branch — git br kısayolu
  • git config --global alias.lg "log --oneline --graph --decorate --all" — git lg kısayolu

📬 Geri Bildirim

Makaleyi yazarken, Kaynakları belirleme ve araştırma için kendi notlarımı yazım denetimi ve ek araştırma için “Claude Opus 4.6” modelini kullandım. Resimleri üretmek için ise “Gemini 3 Pro Preview 2k (Nano Banana Pro)” modelini kullandım.

Yazı ile ilgili tavsiye, öneri, eleştirileri dikkate alıyorum. İletişime geçmek isterseniz bana websitemdeki sosyal medya adreslerimden veya Linkedin üzerinden ulaşabilirsiniz.

Sevgiyle kalın, Yasin 🤗

📚 Makaleyi Yazarken Kullandığım Kaynaklar