Dosya Takibi
Giriş: Neden Derinlemesine Öğreniyoruz?
Önceki derste git add . ile tüm dosyaları staging'e aldık. Çalıştı. Ama gerçek dünyada her zaman "tüm değişiklikleri ekle" demezsin. Bazen:
Bir dosyanın sadece belirli satırlarını commit'lemek istersin
Bir dosyayı Git'in izlemesinden tamamen çıkarmak istersin
Bir dosyayı taşımak veya yeniden adlandırmak istersin
Belirli dosya türlerini asla izlememek istersin
Bu ders, dosya takibinin inceliklerini öğreterek seni "git add ." otomatizminden kurtaracak. Commit'lerini cerrahi hassasiyetle kontrol edebileceksin.
🎬 Analoji: Bavul Hazırlamak
Tatile gidiyorsun ve bavulunu hazırlıyorsun. İki yaklaşım var:
Tembel yaklaşım: Dolaptaki her şeyi bavula at → Bavul çok ağır, gereksiz şeyler dolu
Akıllı yaklaşım: Tek tek seç — "bu tişörtü al, bu pantolonu al, ceketi bırak" → Bavul düzgün, sadece gereken var
git add . = tembel yaklaşım. Her zaman işe yarar ama her zaman doğru değildir.
git add -p = akıllı yaklaşım. "Bu değişikliği al, bunu bırak" diyerek parça parça ekleme yaparsın.
git add — Detaylı İnceleme
Temel Kullanımlar (Hatırlatma)
git add dosya.txt # Tek dosya
git add dosya1 dosya2 # Birden fazla dosya
git add . # Geçerli dizin ve alt dizinler (tüm değişiklikler)
git add -A # Tüm repo genelinde tüm değişiklikler
git add *.js # Glob pattern — tüm .js dosyaları
git add src/ # Bir klasör ve içindekilergit add . vs git add -A — İnce Fark
# Proje yapısı:
my-project/
├── src/
│ ├── app.js (modified)
│ └── utils.js (new)
├── README.md (deleted)
└── test.js (modified)
# src/ dizinindeyken:
$ cd src/
$ git add .
# Sadece src/ altındaki değişiklikleri ekler
# README.md'nin silinmesi EKLENMEMİŞ olabilir (eski Git versiyonlarında)
# Herhangi bir yerden:
$ git add -A
# Tüm repo genelindeki tüm değişiklikleri ekler
# Silme, ekleme, düzenleme — hepsiModern Git versiyonlarında (2.x+) git add . da silinmeleri ekler. Ama alışkanlık olarak -A daha güvenlidir.
Interactive Mode: git add -i
Git'in interaktif staging modu, bir menü sunar:
$ git add -i
staged unstaged path
1: unchanged +3/-1 index.html
2: unchanged +7/-0 style.css
3: unchanged +2/-0 app.js
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>Seçenekler:
update (2): Dosya seçip staging'e al
revert (3): Staging'den çıkar
patch (5): Satır satır seçim yap
diff (6): Staging'deki farkları göster
Patch Mode: git add -p — Cerrah Gibi Commit'le
Bu, Git'in en güçlü ve en az bilinen özelliklerinden biri. Bir dosyadaki değişiklikleri parça parça (hunk) seçerek staging'e alabilirsin.
Örnek senaryo: app.js'de hem bir bug fix yaptın hem yeni bir özellik ekledin. Bunları ayrı commit'lemek istiyorsun.
$ cat app.js
document.addEventListener('DOMContentLoaded', () => {
console.log('Uygulama başlatıldı');
// Bug fix: null check eklendi
const user = getUser();
if (user !== null) {
displayProfile(user);
}
// Yeni özellik: Dark mode
const darkModeBtn = document.getElementById('dark-mode');
darkModeBtn.addEventListener('click', () => {
document.body.classList.toggle('dark');
});
});$ git add -p app.js
diff --git a/app.js b/app.js
--- a/app.js
+++ b/app.js
@@ -1,3 +1,9 @@
document.addEventListener('DOMContentLoaded', () => {
console.log('Uygulama başlatıldı');
+
+ // Bug fix: null check eklendi
+ const user = getUser();
+ if (user !== null) {
+ displayProfile(user);
+ }
+
+ // Yeni özellik: Dark mode
+ const darkModeBtn = document.getElementById('dark-mode');
+ darkModeBtn.addEventListener('click', () => {
+ document.body.classList.toggle('dark');
+ });
});
(1/1) Stage this hunk [y,n,q,a,d,s,e,?]?Burada Git sana bir "hunk" (değişiklik parçası) gösteriyor ve seçenekler sunuyor:
y = yes, bu hunk'ı staging'e al
n = no, bu hunk'ı atla
q = quit, çık (geri kalanları ekleme)
a = all, bu dosyadaki tüm hunk'ları ekle
d = bu dosyadaki hiçbir hunk'ı ekleme
s = split, bu hunk'ı daha küçük parçalara böl
e = edit, hunk'ı elle düzenle
? = yardım`s` (split) ile hunk'ı bölersek:
(1/1) Stage this hunk [y,n,q,a,d,s,e,?]? s
Split into 2 hunks.
# Hunk 1: Bug fix
@@ -1,3 +1,9 @@
document.addEventListener('DOMContentLoaded', () => {
console.log('Uygulama başlatıldı');
+
+ // Bug fix: null check eklendi
+ const user = getUser();
+ if (user !== null) {
+ displayProfile(user);
+ }
(1/2) Stage this hunk [y,n,q,a,d,e,?]? y ← Bug fix'i al
# Hunk 2: Dark mode
+
+ // Yeni özellik: Dark mode
+ const darkModeBtn = document.getElementById('dark-mode');
+ darkModeBtn.addEventListener('click', () => {
+ document.body.classList.toggle('dark');
+ });
(2/2) Stage this hunk [y,n,q,a,d,e,?]? n ← Bunu şimdilik almaŞimdi:
$ git commit -m "fix: Kullanıcı profili null check eklendi"
# Sonra dark mode'u da commit'le
$ git add -p app.js
# Bu sefer dark mode hunk'ını y ile kabul et
$ git commit -m "feat: Dark mode toggle eklendi"İki temiz, ayrı commit. Profesyonel!
💡 İpucu:
git add -palışkanlığını erken edin. Başta yavaş hissedebilir ama bir süre sonra doğal gelir. Commit'lerin temiz ve anlamlı olması, code review'da büyük fark yaratır. Ekip arkadaşların sana teşekkür edecek.
git rm — Dosya Silme
Git'ten bir dosyayı silmenin birden fazla yolu var ve aralarındaki farkı bilmek önemli.
Normal Silme vs Git ile Silme
# Yol 1: Önce dosyayı sil, sonra Git'e bildir
$ rm gereksiz.txt
$ git add gereksiz.txt # veya git add -A
$ git commit -m "gereksiz.txt silindi"
# Yol 2: Git ile bir adımda sil (önerilen)
$ git rm gereksiz.txt
rm 'gereksiz.txt'
$ git commit -m "gereksiz.txt silindi"git rm:
Dosyayı diskten siler
Silme işlemini staging'e alır
İki adım yerine bir adım.
--cached: Dosyayı Git'ten Çıkar Ama Diskten Silme
Bazen bir dosyayı Git'in izlemesinden çıkarmak ama diskten silmemek istersin:
# Yanlışlıkla .env dosyasını commit'lemişsin
# Git'in izlemesinden çıkar ama dosya kalsın
$ git rm --cached .env
rm '.env'
# .gitignore'a ekle (tekrar eklenmesini önle)
$ echo ".env" >> .gitignore
$ git add .gitignore
$ git commit -m "chore: .env dosyası izlemeden çıkarıldı"Bu, en sık kullanılan git rm kullanımı. Yanlışlıkla izlemeye alınan dosyaları çıkarmak için.
Klasör Silme
# Bir klasörü ve içindekileri sil
$ git rm -r logs/
rm 'logs/error.log'
rm 'logs/access.log'
$ git commit -m "chore: Log klasörü kaldırıldı"-r = recursive (alt klasörlerle birlikte).
⚠️ Dikkat:
git rmile silinen dosyalar commit geçmişinde hâlâ var. Eğer hassas veri (API key, şifre) commit'lediysen,git rm --cachedyeterli değil — geçmişte hâlâ gözükür. Bunu temizlemek içingit filter-branchveyaBFG Repo Cleanergibi araçlar gerekir (ileri bölümlerde).
git mv — Dosya Taşıma ve Yeniden Adlandırma
Git'te dosya taşımak veya yeniden adlandırmak için git mv kullanırız:
# Dosyayı yeniden adlandır
$ git mv eski_isim.txt yeni_isim.txt
$ git status
On branch main
Changes to be committed:
renamed: eski_isim.txt -> yeni_isim.txtBu aslında üç komutun kısayolu:
# git mv'nin yaptığı şey:
$ mv eski_isim.txt yeni_isim.txt # 1. Dosyayı taşı
$ git rm eski_isim.txt # 2. Eski ismi sil (Git'ten)
$ git add yeni_isim.txt # 3. Yeni ismi ekleKlasöre Taşıma
# Dosyayı başka bir klasöre taşı
$ git mv app.js src/app.js
$ git status
Changes to be committed:
renamed: app.js -> src/app.jsKlasörü Yeniden Adlandırma
$ git mv css styles
$ git status
Changes to be committed:
renamed: css/style.css -> styles/style.css💡 İpucu: Git aslında dosya taşımalarını izlemez — silme + ekleme olarak görür. Ama Git yeterince akıllıdır: dosya içeriği aynı veya çok benzer ise, "renamed" olarak algılar.
git log --follow dosya.txtile taşınma öncesindeki geçmişi de görebilirsin.
.gitignore — Neyi İzlememeliyiz?
.gitignore, Git'e "bu dosyaları görmezden gel" diyen bir yapılandırma dosyasıdır.
Neden Önemli?
Her projede izlenmemesi gereken dosyalar vardır:
Bağımlılıklar (
node_modules/,vendor/) — çok büyük,npm installile yeniden oluşturulabilirOrtam değişkenleri (
.env) — API anahtarları, şifrelerBuild çıktıları (
dist/,build/) — kaynak koddan üretilirIDE dosyaları (
.idea/,.vscode/) — kişiye özelİşletim sistemi dosyaları (
.DS_Store,Thumbs.db) — gereksiz
Pattern Sözdizimi
# Yorum satırı
# Hash (#) ile başlayan satırlar yorum
# Belirli bir dosya
secret.key
config.local.php
# Belirli bir uzantı
*.log
*.tmp
*.swp
# Belirli bir klasör
node_modules/
vendor/
dist/
# Klasör içindeki belirli dosya türü
logs/*.log
# Tüm alt dizinlerdeki belirli dosya türü
**/*.pyc
# Olumsuzlama (hariç tutma)
*.log
!important.log
# Tüm .log dosyalarını yoksay AMA important.log'u izle
# Belirli bir yol
/TODO
# Sadece kök dizindeki TODO'yu yoksay
# alt_dizin/TODO etkilenmez
# Çift yıldız — herhangi bir derinlik
**/build/
# build/ klasörünü nerede olursa olsun yoksay
docs/**/*.pdf
# docs/ ve tüm alt dizinlerindeki PDF'leri yoksayPratik .gitignore Örnekleri
Node.js Projesi:
# Dependencies
node_modules/
package-lock.json
# Environment
.env
.env.local
.env.*.local
# Build
dist/
build/
.next/
# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# IDE
.vscode/
.idea/
*.swp
# OS
.DS_Store
Thumbs.db
# Coverage
coverage/Python Projesi:
# Byte-compiled
__pycache__/
*.py[cod]
*$py.class
# Virtual environment
venv/
.venv/
env/
# Distribution
dist/
build/
*.egg-info/
# IDE
.idea/
.vscode/
*.swp
# Environment
.env
# Jupyter
.ipynb_checkpoints/Java Projesi:
# Compiled
*.class
*.jar
*.war
# Build
target/
build/
out/
# IDE
.idea/
*.iml
.classpath
.project
.settings/
# Logs
*.logGlobal .gitignore
Tüm projelerinde geçerli olacak bir global .gitignore tanımlayabilirsin:
# Global gitignore dosyası oluştur
$ cat > ~/.gitignore_global << 'EOF'
# macOS
.DS_Store
.AppleDouble
.LSOverride
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# Linux
*~
# IDEs
.idea/
.vscode/
*.swp
*.swo
*~
# Editör yedekleri
*.bak
*.orig
EOF
# Git'e tanıt
$ git config --global core.excludesfile ~/.gitignore_globalBu sayede her projede .DS_Store veya .idea/ eklemenize gerek kalmaz.
Zaten İzlenen Dosyayı .gitignore'a Eklemek
.gitignore sadece henüz izlenmeyen dosyaları etkiler. Zaten izlenen bir dosyayı sonradan .gitignore'a eklemek yetmez:
# Dosya zaten izleniyor
$ git ls-files
.env
index.html
# .gitignore'a .env ekle
$ echo ".env" >> .gitignore
# AMA .env hâlâ izleniyor!
$ git status
# .env değişiklikleri gözükmeye devam eder
# Çözüm: Önce izlemeden çıkar
$ git rm --cached .env
$ git add .gitignore
$ git commit -m "chore: .env izlemeden çıkarıldı ve .gitignore güncellendi"
# Artık .env izlenmiyor⚠️ Dikkat:
.gitignore'u projenin en başında oluştur. Sonradan eklemek çalışır ama zaten commit'lenmiş dosyaların geçmişi kalır. En iyisi,git init'ten hemen sonra.gitignoreoluşturmaktır.
.gitignore Debugging
Bir dosyanın neden izlendiğini veya neden yoksayıldığını anlamak için:
# Bu dosya neden yoksayılıyor?
$ git check-ignore -v dosya.txt
.gitignore:3:*.txt dosya.txt
# .gitignore'un 3. satırındaki *.txt kuralı yüzünden
# Bu dosya yoksayılıyor mu?
$ git check-ignore dosya.txt
dosya.txt # Çıktı varsa yoksayılıyor
# Çıktı yoksa izleniyorgit clean — Untracked Dosyaları Temizleme
git clean, izlenmeyen (untracked) dosyaları çalışma dizininden siler. Build artifact'ları, geçici dosyalar veya deneme dosyalarını temizlemek için kullanılır:
# Neyin silineceğini göster (dry-run, güvenli)
$ git clean -n
Would remove temp.txt
Would remove debug.log
Would remove test-output/
# Untracked dosyaları sil
$ git clean -f
Removing temp.txt
Removing debug.log
# Untracked dizinleri de sil (-d)
$ git clean -fd
Removing temp.txt
Removing debug.log
Removing test-output/
# .gitignore'da olan dosyaları da sil (-x)
$ git clean -fdx
# node_modules/, .env, build/ dahil HER ŞEYİ siler
# ⚠️ Dikkatli kullan!
# Interaktif mod (en güvenli)
$ git clean -i
Would remove the following items:
temp.txt debug.log test-output/
*** Commands ***
1: clean 2: filter by pattern
3: select by numbers 4: ask each one 5: quit
What now>⚠️ Dikkat:
git clean -fgeri alınamaz! Git tarafından izlenmeyen dosyalar silindiğinde reflog veya başka bir kurtarma yolu yoktur. Her zaman öncegit clean -nile neyin silineceğini kontrol edin.
Assume Unchanged — Yerel Değişiklikleri Gizleme
Bazen bir dosyayı yerelde değiştirirsiniz ama Git'in bu değişikliği görmesini istemezsiniz (örneğin yerel konfigürasyon):
# Git'e "bu dosya değişmemiş gibi davran" de
$ git update-index --assume-unchanged config/local.yml
# Geri al
$ git update-index --no-assume-unchanged config/local.yml
# Hangi dosyalar assume-unchanged?
$ git ls-files -v | grep "^[a-z]"
h config/local.ymlAlternatif olarak --skip-worktree daha güvenlidir:
# skip-worktree (checkout/reset'e dayanıklı)
$ git update-index --skip-worktree config/local.yml
$ git update-index --no-skip-worktree config/local.ymlStaging Area'yı İnceleme
Staging area'da ne olduğunu görmek için:
# Staging'deki dosyaları listele
$ git ls-files --stage
100644 a1b2c3d4... 0 index.html
100644 e5f6a7b8... 0 style.css
100644 c9d0e1f2... 0 app.js
# Staging ile son commit arasındaki fark
$ git diff --staged
diff --git a/index.html b/index.html
--- a/index.html
+++ b/index.html
@@ -10,6 +10,7 @@
<body>
+ <footer>© 2026</footer>
</body>
# Staging ile working directory arasındaki fark
$ git diff
# (staging'e alınmamış değişiklikler)diff --staged vs diff Karşılaştırması
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Working │ │ Staging │ │ Last Commit │
│ Directory │ │ Area │ │ (HEAD) │
└───────┬────────┘ └───────┬────────┘ └───────┬────────┘
│ │ │
│◄── git diff ──────────►│ │
│ (staging'e alınmamış │ │
│ değişiklikler) │ │
│ │◄── git diff --staged ─►│
│ │ (commit'lenecek │
│ │ değişiklikler) │
│ │ │
│◄── git diff HEAD ─────────────────────────────► │
│ (tüm değişiklikler — staged + unstaged) │Pratik Senaryo: Profesyonel Dosya Yönetimi
# Senaryo: Bir web projesinde çalışıyorsun
$ mkdir pro-workflow && cd pro-workflow && git init
# Başlangıç dosyaları
$ echo "<html><body>Hello</body></html>" > index.html
$ echo "body { margin: 0; }" > style.css
$ echo "console.log('app');" > app.js
$ echo "DB_PASSWORD=secret123" > .env
$ mkdir logs && echo "error at 10:00" > logs/error.log
$ git add index.html style.css app.js
$ git commit -m "feat: Proje başlatıldı"
# 1. .env'yi yanlışlıkla eklediniz mi? Hayır, çünkü .gitignore var
$ cat > .gitignore << 'EOF'
.env
logs/
*.log
EOF
$ git add .gitignore
$ git commit -m "chore: .gitignore eklendi"
# 2. Dosya taşıma
$ mkdir src
$ git mv app.js src/app.js
$ git commit -m "refactor: app.js src/ klasörüne taşındı"
# 3. Dosya silme
$ echo "temp data" > gecici.txt
$ git add gecici.txt && git commit -m "temp: Geçici dosya"
$ git rm gecici.txt
$ git commit -m "chore: Geçici dosya silindi"
# 4. Parçalı staging
$ echo "// Bug fix" >> src/app.js
$ echo "h1 { color: blue; }" >> style.css
$ git add -p
# Her değişikliği ayrı değerlendir
# 5. Geçmişe bak
$ git log --oneline --statÖzet
git add -pile değişiklikleri hunk bazında seçerek staging'e alabilirsin — temiz commit'ler için kritikgit rmdosyayı hem diskten siler hem staging'e alır;--cachedile sadece Git'ten çıkarırgit mvdosya taşıma ve yeniden adlandırma için kullanılır — Git tarihinde "rename" olarak gözükür.gitignoreile izlenmemesi gereken dosyaları belirlersin — projenin başında oluşturZaten izlenen dosyayı yoksaymak için önce
git rm --cachedile izlemeden çıkarmalısıngit diff --stagedile commit'lenecek değişiklikleri,git diffile henüz staging'e alınmamış değişiklikleri görebilirsin
*Bir sonraki derste commit'in iç yapısını — tree, blob, SHA-1 — ve profesyonel commit mesajı yazmayı öğreneceğiz!*
AI Asistan
Sorularını yanıtlamaya hazır