Ana içeriğe atla

Git Subtree Açıklaması: Örneklerle Pratik Rehber

Ekipler arası paylaşılan kütüphaneleri senkron tutmak için dört temel komutu kullanın (add, pull, push, split).
Güncel 3 Eki 2026  · 12 dk. oku

Yapay Zeka ile Keşfedin

ChatGPTClaudePerplexity

Bir veri analizi projesi üzerinde çalışıyorsunuz ve ekibinizin başka bir depoda bakımını yaptığı ortak bir yardımcı araçlar kütüphanesini projeye dahil etmeniz gerekiyor. Kodu kopyalayıp yapıştırabilirsiniz, ancak bu durumda güncelleme yolunu kaybedersiniz. Git submodule kullanabilirsiniz, ama zor olduklarını duydunuz. Üçüncü bir seçenek var: git subtree.

git subtree, bir Git deposunu bir diğerinin içine bir alt dizin olarak gömmenizi sağlar; tam geçmişi korur ve güncellemeler için kolay bir yol sunar.

Bu rehber, git subtree’yi ne zaman kullanmanız gerektiğini, nasıl çalıştığını ve yaygın iş akışları için pratik örnekleri kapsar. Veri bilimi projelerinde gerçekten karşılaşabileceğiniz senaryoları kullanacağız.

git subtree Nedir?

Git subtree, projenizde belirli bir klasör altında başka bir Git deposunu, tüm commit geçmişini koruyarak, içerir. Kodu kopyalamaktan veya sembolik bağlantılar kullanmaktan farklı olarak, subtree özgün depoyla bir bağlantıyı sürdürür; böylece güncellemeleri çekebilir ve gerekirse değişiklikleri geri gönderebilirsiniz.

İşte onu kodu sadece kopyalamaktan ayıran noktalar:

Kopyala-yapıştır kod:

  • Özgün depoyla bağlantı yok
  • Kütüphane değiştiğinde güncelleme yolu yok
  • Kodun nereden geldiğine dair geçmiş yok

Git subtree:

  • Özgün depodan tam commit geçmişi
  • Tek komutla güncellemeleri çekme
  • Gerekirse değişiklikleri özgün depoya geri gönderme
  • Her şey tek bir depo checkout’unda bulunur

Git submodule’dan temel fark: subtree içeriği doğrudan ana deponuza commit edilir. Birisi projenizi klonladığında, ek adım olmadan tek seferde her şeyi alır.

Bütün bunlar daha kolay işe alıştırma ve daha az “benim makinemde çalışıyor” sorununa dönüşür.

git subtree Nasıl Çalışır

Bir subtree eklediğinizde Git akıllı bir şey yapar: başka bir deponun geçmişini projenizin bir alt dizinine birleştirir. Olan şu:

  1. Git uzak deponun geçmişini çeker
  2. Bu commit’leri seçtiğiniz alt dizin altında görünecek şekilde yeniden yazar
  3. Yeniden yazılmış bu geçmişi mevcut dalınıza birleştirir
  4. Gelecekteki güncellemeler aynı modeli izler: fetch, rewrite, merge

Depo, sadece bir işaretçi veya referans değil, subtree’den gerçek dosyalar ve tam commit geçmişi içerir. Birisi projenizi klonladığında veya bir dalı checkout ettiğinde, tüm koda hemen sahip olur. Ayrı bir “submodule başlat” adımı yoktur.

Takas noktası: deponuz büyür; çünkü hem kendi kodunuzu hem de subtree’nin kodu ile tam geçmişini içerir. Buna değer mi? Duruma bağlı, ancak çoğu veri bilimi ekibi için, bence değer.

git subtree Nasıl Kullanılır (Yaygın Komutlar)

Artık subtree’nin ne yaptığını anladığınıza göre, en yaygın işlemleri adım adım inceleyelim. Gerçekçi bir senaryo kullanacağız: bir veri analizi projesi geliştiriyorsunuz ve ortak bir yardımcı kütüphaneyi dahil etmeniz gerekiyor.

Örnek kurulum:

  • Ana proje: data-pipeline

  • Paylaşılan kütüphane: shared-utils (https://github.com/yourteam/shared-utils.git adresinde mevcut)

  • Bunu projenizde libs/shared-utils/ altında dahil etmek istiyorsunuz

git subtree add

add komutu, başka bir depoyu projenize ilk kez dahil eder.

Referans için temel sözdizimi şöyledir:

git subtree add --prefix=<directory> <remote-url> <branch> --squash

Gerçek örnek:

# shared-utils deposunu libs/shared-utils altına ekleyin
git subtree add --prefix=libs/shared-utils \
  https://github.com/yourteam/shared-utils.git \
  main \
  --squash

Bunun yaptığı şey:

  • libs/shared-utils dizinini oluşturur
  • shared-utils’tan tüm dosyaları buraya kopyalar
  • Her şeyi deponuza commit eder
  • Gelecekteki güncellemeler için bağlantıyı kaydeder

Bayrakları anlama:

  • --prefix=libs/shared-utils: Subtree’nin projenizde yaşayacağı yer. Tüm gelecekteki işlemler için aynı öneki (prefix) tam olarak kullanmalısınız. Bunu bir kez değiştirirseniz, nedenlerin bozulduğunu 02:00’de Stack Overflow’da arıyor olabilirsiniz.

  • --squash: Subtree’nin tüm commit geçmişini projenizde tek bir commit’e indirger. Bu, projenizin geçmişini daha temiz tutar. --squash olmadan, projenizin geçmişinde özgün depodaki her commit’i görürsünüz ki bu bunaltıcı olabilir.

Ne zaman squash yapılır: Özgün depodaki ayrıntılı commit atıflarını korumanız gerekmiyorsa --squash kullanın. Paylaşılan yardımcılar içeren çoğu veri projesinde, sıkıştırılmış (squashed) geçmiş daha temiz ve çalışması daha kolaydır. Ben her zaman kullanırım.

Bunu çalıştırdıktan sonra projenizde şu tarz bir iletisi olan yeni bir commit göreceksiniz: "Add 'libs/shared-utils/' from commit 'abc123'". libs/shared-utils dizini artık tüm dosyaları içerir ve hemen kullanabilirsiniz.

git subtree pull

pull komutu, subtree’nizi özgün depodaki değişikliklerle günceller. Paylaşılan kütüphane ekibi bir hatayı düzeltirse veya bir özellik eklerse, bu güncellemeleri böyle alırsınız.

Temel sözdizimi:

git subtree pull --prefix=<directory> <remote-url> <branch> --squash

Gerçek örnek:

# shared-utils’tan en son değişiklikleri çekin
git subtree pull --prefix=libs/shared-utils \
  https://github.com/yourteam/shared-utils.git \
  main \
  --squash

Bunun yaptığı şey:

  • Uzak depodan yeni commit’leri çeker
  • Bunları libs/shared-utils dizininize birleştirir
  • Projenizde bir merge commit’i oluşturur

Önek tam olarak eşleşmelidir. add sırasında libs/shared-utils kullandıysanız, pull için de libs/shared-utils kullanmalısınız. Farklı bir önek kullanmak işe yaramaz. Buna güvenin.

Squash tutarlılığı: add sırasında --squash kullandıysanız, her pull’da --squash kullanmalısınız. Sıkıştırılmış ve sıkıştırılmamış güncellemeleri karıştırmak kafa karıştırıcı bir geçmiş yaratır. Bunu zor yoldan öğrendim.

Çakışmaların ele alınması: libs/shared-utils içindeki dosyaları siz değiştirdiyseniz ve aynı dosyalar upstream’de de değiştiyse, merge çatışmaları oluşur. Bunları, herhangi bir Git birleştirme çatışmasını çözdüğünüz gibi çözün—dosyaları düzenleyin, aşamaya (stage) alın ve birleştirmeyi tamamlayın.

Ekibinizin README’sinde --squash kullanıp kullanmadığınızı belgeleyin ki herkes tutarlı kalsın.

git subtree push

push komutu, subtree klasöründe yaptığınız değişiklikleri özgün depoya geri gönderir.

Temel sözdizimi:

git subtree push --prefix=<directory> <remote-url> <branch>

Gerçek örnek:

# libs/shared-utils içindeki değişiklikleri özgün depoya geri gönderin
git subtree push --prefix=libs/shared-utils \
  https://github.com/yourteam/shared-utils.git \
  main

Bunun yaptığı şey:

  • Sadece libs/shared-utils’i etkileyen commit’leri çıkarır
  • Onları, sanki shared-utils’ın kökünde yapılmış gibi yeniden yazar
  • Bu commit’leri özgün depoya iter

Ne zaman kullanılır: Ortak bir kütüphaneyi uygulama deponuzun içinde bakımını yapıyor ve iyileştirmeleri geri katkılamak istiyorsunuz. Diyelim ki data-pipeline projeniz üzerinde çalışırken shared-utils’a yararlı bir veri doğrulama işlevi eklediniz ve bundan diğer projeler de yararlanmalı.

Push’u, pull’un tersi gibi düşünün. Pull değişiklikleri içeri alır; push değişiklikleri dışarı gönderir. Git yalnızca ilgili geçmişi çıkarır ve onu özgün deponun yapısına çevirir. Oldukça akıllıca.

Özgün depoya yazma erişimine ihtiyacınız var. İzniniz yoksa, depoyu forklamanız, forka push etmeniz ve bir çekme isteği (pull request) oluşturmanız gerekir.

git subtree split

split komutu, bir alt dizinin geçmişini kendi dalına çıkarır.

Temel sözdizimi:

git subtree split --prefix=<directory> -b <new-branch-name>

Gerçek bir örnek:

# libs/shared-utils’ı kendi dalına çıkarın
git subtree split --prefix=libs/shared-utils -b shared-utils-extracted

Bunun yaptığı şey:

  • Sadece libs/shared-utils’i etkileyen commit’leri içeren yeni bir dal oluşturur
  • Bu dal, yalnızca o dizinden oluşan bağımsız bir depo gibi görünür
  • Özgün dal değişmeden kalır

Yaygın kullanım durumları:

Bir monorepo’dan kütüphane çıkarmak: Veri işleme hattınız büyüdü ve yeniden kullanılabilir bir bileşeni bağımsız bir kütüphane olarak çıkarmak istiyorsunuz. Split, yalnızca o bileşenin geçmişini içeren bir dal oluşturur; bunu yeni bir depoya itebilirsiniz.

Bir alt dizini bağımsız bir proje olarak yayımlamak: Analiz projenizin içinde yararlı bir veri görselleştirme modülü oluşturdunuz ve bunu bağımsız bir paket olarak paylaşmak istiyorsunuz. Split, tam geçmişi korunmuş şekilde bunu çıkarır.

Yeni bir bağımsız depo oluşturma iş akışı örneği:

# Alt dizini çıkarın
git subtree split --prefix=libs/shared-utils -b shared-utils-standalone

# Yeni bir depo oluşturun ve ona push edin
git remote add shared-utils-origin https://github.com/yourteam/shared-utils-new.git
git push shared-utils-origin shared-utils-standalone:main

Artık shared-utils-new, yalnızca o alt dizinin tam geçmişine sahip eksiksiz bir depodur.

git subtree vs. submodule

İnsanların her zaman sorduğu soru şu: subtree mi submodule mü?

Her ikisi de dış kodu deponuza dahil etmenizi sağlar, ancak farkları vardır. Eğer kesin sürüm sabitlemeye ihtiyacınız varsa ya da depo boyutu kısıtlıysa, submodule kullanın. Ekibinizin Git becerileri karışıksa ve sadelik istiyorsanız, subtree kullanın. Aksi halde ikisi de işe yarar.

Boyut

git subtree

git submodule

Kurulum karmaşıklığı

Orta (doğrudan komutlar)

Yüksek (ayrı init adımı gerekir)

Klonlama deneyimi

Basit (tek klon, her şey çalışır)

Karmaşık (clone + git submodule update --init)

Depo boyutu

Daha büyük (tam subtree içeriği + geçmişi dahil)

Daha küçük (yalnızca başka bir depoya işaretçi)

Geliştirici işe alıştırma

Kolay (klondan sonra her şey çalışır)

Daha zor (submodule iş akışını anlamak gerekir)

CI/CD karmaşıklığı

Basit (klonla ve devam et)

Daha karmaşık (submodule’lar başlatılmalı)

Sürüm sabitleme

Daha az kesin (en son veya belirli commit’i birleştirir)

Kesin (tam commit hash’i)

Güncelleme iş akışı

git subtree pull (değişiklikleri birleştirir)

cd submodule && git pull (manuel)

"Benim makinemde çalışıyor" riski

Daha düşük (her şey commitlidir)

Daha yüksek (submodule durumu sapabilir)

Değişiklikleri geri gönderme

git subtree push

Submodule içinde normal git push

Sorumlulukların ayrımı

Karışık (kod ana depoda yaşar)

Net (submodule ayrı depodur)

Şunlara ihtiyacınız olduğunda git submodule kullanın :

  • Sıkı sürüm sabitleme (kütüphane Y’nin tam olarak X commit’i kullanılmalı)
  • Projeler arasında net ayrım (gerçekten bağımsızlar)
  • Aynı bağımlılığı farklı sürümlerde paylaşan birden çok proje
  • İş akışınız için küçük ana depo boyutu önemliyse

Şunları istediğinizde git subtree kullanın:

  • Ek başlangıç adımı olmasın
  • Yeni ekip üyeleri bir kez klonlayıp sonra testleri çalıştırsın
  • Ekibinizin öğrenmesi gereken daha az Git kavramı olsun
  • Zaman zaman güncelleme çektiğiniz vendoring senaryoları

Hiçbiri her zaman daha iyi değildir. Seçim, sadeliğe mi yoksa sıkı sürüm kontrolüne mi değer verdiğinize bağlıdır. Benim görüşüm: Git’in iç detaylarından çok analize odaklanan veri bilimi ekipleri için subtree genellikle sürtünmeyi azaltır. Bağımlılık gereksinimlerini yöneten platform ekipleri için submodule mantıklıdır.

git subtree’yi Ne Zaman Kullanmamalı

git subtree’yi, depo boyutu sıkı bir kısıt olduğunda kullanmayın. Subtree, tam içerik ve geçmişi dahil ettiği için depo boyutunuzu şişirir. Git platformu limitlerine yakındaysanız veya ağ hızı çok önemliyse, submodule’lar daha hafiftir.

Ayrıca, sıkı sürüm sabitlemeye ihtiyacınız varsa git subtree kullanmayın. Kütüphanenin yalnızca 2.3.1 sürümünü ve başka hiçbir şeyi kullanmanız gerekiyorsa. Submodule’lar tam commit’lere sabitler; subtree commit aralıklarını birleştirir.

git subtree’yi harici depo sık değişiyorsa kullanmayın. Subtree her gün önemli değişiklerle güncelleniyorsa, sürekli güncelleme çekmek dağınık bir birleştirme geçmişi oluşturur. Gerçekten gömülü olmasına ihtiyacınız olup olmadığını veya bir paket yöneticisinin daha temiz olup olmayacağını değerlendirin.

Son olarak, kurumsal ayrım gerekiyorsa git subtree kullanmayın. Subtree içeriğinin farklı erişim kontrolleri, lisanslaması veya sahipliği varsa, onları ayrı depolarda tutmak sınırları daha net kılar.

git subtree’nin Avantajları

Tek depo klonlama deneyimi: git clone çalıştırın ve bitti. İhtiyacınız olan her şey orada. Bu, herkesin Git uzmanı olmadığı ekiplerde işe alıştırma sürtünmesini azaltır.

Submodule’lardan daha az hareketli parça: Ayrı başlatma adımı yok. Açıklanması gereken detached HEAD durumları yok. “Submodule’un uyumsuz” karmaşası yok. İş akışı standart Git işlemlerine (add, pull, push) daha yakındır.

CI/CD sadeliği: Sürekli entegrasyon betikleriniz daha basittir. Subtree ile klonlayıp testleri çalıştırırsınız. Submodule’larda klonlar, özyinelemeli başlatır, sonra testleri çalıştırırsınız. Bu ekstra adım unutulduğunda derlemeleri bozar.

Git konusunda farklı rahatlık seviyelerine sahip ekipler için iyi çalışır: Kıdemsiz veri uygulayıcılarının submodule mekaniğini anlaması gerekmez. Alışıldık Git komutlarını kullanırlar ve her şey çalışır.

Ara sıra güncellemeli vendoring için iyi: Bir kütüphanenin 1.2 sürümünü dahil edersiniz. Altı ay sonra, 1.3 sürümünde istediğiniz bir hata düzeltmesi vardır. Tek komutla içeri alın. Bakımı yapılmayan kopyalanmış kodla sıkışıp kalmazsınız; ama aynı zamanda sürekli upstream’i takip etmek zorunda da kalmazsınız.

git subtree’nin Sınırlamaları ve Tavizleri

Depo önemli ölçüde büyür: Deponuz, kendi kodunuzun yanı sıra subtree’nin kodunu ve tam commit geçmişini içerir (yardımcı olmakla birlikte --squash kullanmadıkça). 50 MB’lık bir subtree, deponuza yaklaşık 50 MB ekler.

Büyük veya birden çok subtree için bu birikir. Kolaylığın disk alanı ve klonlama süresine değip değmeyeceğini düşünün.

  • Geçmiş grafiği karmaşıklığı: --squash ile bile, subtree güncellemeleri için yapılan merge commit’leri Git geçmişinize karmaşıklık katar. Subtree güncellemelerini sık çekerseniz, commit grafiğiniz dağınık hale gelir.

  • Upstream ayrışma kafa karışıklığı: Subtree dosyalarını siz değiştirir ve upstream de aynı dosyaları değiştirirse, birleştirme çatışmaları olur. Bir subtree’de çatışma çözmek kafa karıştırıcı olabilir; çünkü başkasının deposunu sizin alt dizininize birleştiriyorsunuz.

  • Push iş akışında dikkat edilmesi gerekenler: git subtree push geçmişi yeniden yazmayı gerektirir; bu, büyük subtree’lerde yavaş olabilir. Subtree klasöründe birçok commit yaptıysanız, push biraz sürebilir. Sabırlı olun.

  • Birleştirme çatışmaları yine olur: Siz ve upstream aynı dosyayı değiştirirseniz, çatışmaları çözmeniz gerekir. Bu subtree’ye özgü değildir; ancak subtree, Git çatışmalarını sihirli şekilde önlemez.

  • Disiplin gerektirir: Farklı --prefix değerleri kullanmak veya tutarsız --squash bayrakları sorun yaratır. Ekibin aynı iş akışını belgelemesi ve takip etmesi gerekir.

Bu sınırlamalar ölümcül değildir, ancak en baştan bilmeye değerdir. Taviz şu: daha basit iş akışı karşılığında daha büyük depo boyutu ve potansiyel geçmiş karmaşıklığı.

git subtree Kullanırken Yaygın Hatalar

git subtree kullanmaya başladığınızda şu yaygın sorunlara dikkat edin. Haberdar olduktan sonra kaçınması kolaydır.

--squash’ın tutarsız kullanımı

Subtree’yi eklerken --squash kullandınız ama git subtree pull sırasında unuttunuz. Artık geçmişiniz, subtree’den hem sıkıştırılmış hem sıkıştırılmamış commit’ler içeriyor ve bu kafa karıştırıyor.

Çözüm, proje README’nizde bunu belgelemektir. Şu gibi notlar yazın: "shared-utils subtree ile her zaman --squash kullanın."

Yanlış veya değişen önek

Subtree’yi --prefix=libs/shared-utils ile eklediniz ama daha sonra --prefix=libs/utils ile çekmeye çalıştınız. Bu çalışmaz çünkü Git subtree’yi bulamaz.

Çözüm, her seferinde tam olarak aynı öneki kullanmaktır. Bunu bir betikte belgelemeyi düşünün, şöyle:

# scripts/update-subtree.sh
#!/bin/bash
git subtree pull --prefix=libs/shared-utils \
  https://github.com/yourteam/shared-utils.git \
  main \
  --squash

Subtree’nin submodule gibi davranmasını beklemek

libs/shared-utils içine cd yapıp git checkout ile sürüm değiştirebileceğinizi sandınız. Bu çalışmaz; çünkü subtree içeriği, deponuzda sadece dosyalardır; ayrı bir Git deposu değildir.

Çözüm, subtree’nin belirli commit’leri birleştirdiğini anlamaktır. Bir subtree’yi “düşürmek” için eski bir commit’i bulup birleştirmeniz veya subtree güncelleme commit’lerini geri almanız gerekir.

İş akışını belgelememek

Ekip üyeleri --squash kullanılıp kullanılmayacağını, hangi uzak URL’nin kullanılacağını veya değişikliklerin ne zaman geri gönderileceğini bilmiyor. Herkes farklı yaparsa, tutarsız bir geçmiş oluşur.

Çözüm, README’nize bir bölüm eklemektir:

## shared-utils’ı güncelleme

## En son değişiklikleri çekmek için:
git subtree pull --prefix=libs/shared-utils https://github.com/yourteam/shared-utils.git main --squash

## Değişiklikleri geri göndermek için:
git subtree push --prefix=libs/shared-utils https://github.com/yourteam/shared-utils.git main

Son olarak, planlamadan subtree dosyalarını değiştirmek

Kendi projenize özel olarak libs/shared-utils içindeki dosyaları düzenliyorsunuz, ancak hiç geri göndermiyorsunuz. Altı ay sonra güncellemeleri çekiyorsunuz ve değişiklikleriniz üst akıştaki (upstream) değişikliklerle çakıştığı için çatışmalarla karşılaşıyorsunuz.

Çözüm şudur: Subtree dosyalarını değiştirirseniz, değişiklikleri herkes için yararlıysa shared-utils’a geri gönderin ya da güncellemeler sırasında çatışmaları yönetmeniz gerektiğini kabul edin.

Sonuç

Git subtree, depo boyutu ve geçmiş karmaşıklığını iş akışı sadeliğiyle takas eder. Git’in iç detaylarından çok analize odaklanan veri bilimi ekipleri için subtree sürtünmeyi azaltır. Yeni ekip üyeleri depoyu klonlar ve hemen çalışmaya başlar.

Git iş akışları hakkında daha fazla bilgi edinmek için Git’e Giriş kursumuzu inceleyin.


Oluseye Jeremiah's photo
Author
Oluseye Jeremiah
LinkedIn

Yapay zekâ, makine öğrenimi ve veri bilimi alanlarında uzmanlaşmış teknik yazar; karmaşık fikirleri anlaşılır ve erişilebilir kılar.

Konular
Git

DataCamp ile Git Öğrenin

Kurs

Git'e Giriş

2 sa
101.4K
Yazılım ve veri projelerinizde sürüm kontrolü için Git'in temellerini keşfedin.
Ayrıntıları GörüntüleRight Arrow
Kursa Başla
Devamını GörRight Arrow
İlgili

blog

Hızlı Sevkiyat İçin Pratik Vibe Kodlama Teknoloji Yığını

Ön uç, arka uç, veritabanları, kimlik doğrulama, depolama, e-posta, test, dağıtım ve izleme için en iyi araçları keşfedin.
Abid Ali Awan's photo

Abid Ali Awan

14 dk.

blog

2026’da En Popüler 40 Yazılım Mühendisi Mülakat Sorusu

Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Dario Radečić's photo

Dario Radečić

15 dk.

Eğitim

.gitignore Nasıl Kullanılır: Örneklerle Pratik Bir Giriş

Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Kurtis Pykes 's photo

Kurtis Pykes

8 dk.

Eğitim

Python'da Listeyi String'e Nasıl Dönüştürürsünüz

Bu hızlı eğitimde, Python'da bir listeyi string'e nasıl dönüştüreceğinizi öğrenin.
Adel Nehme's photo

Adel Nehme

Devamını GörDevamını Gör