Rehber

Git submodule: alt modül ekleme, güncelleme ve silme

Güncellendi: · Skillaria.Top

Git submodule, sizin repository'nize gömülmüş ve belirli bir commit'e sabitlenmiş başka bir repository'dir. Alt modül git submodule add <url> <yol> ile eklenir, klonlarken git clone --recurse-submodules ile alınır, git submodule update --remote ile güncellenir, git submodule deinit ve git rm ile silinir.

Git submodule (alt modül), projenizin bir klasörüne gömülmüş ayrı bir Git repository'sidir. Temel özelliği şudur: üst repository alt modülün dosyalarını değil, içindeki belirli bir commit'e referansı saklar. Bu yüzden projeyi klonlayan herkes alt modülü aynı sürümde bulur — siz bu sürümü açıkça değiştirene kadar.

Alt modüller; harici bir kütüphaneyi paket yöneticisi olmadan bağlamak, ortak kodu birkaç proje arasında paylaşmak, bir temayı veya firmware'i kendi geçmişi olan ayrı bir repository'ye taşımak gerektiğinde kullanılır.

Git submodule'ler nasıl çalışır?

Bir alt modül üç parçadan oluşur ve aralarındaki ilişkiyi anlamak sorunların çoğunu ortadan kaldırır:

  • .gitmodules dosyası proje kökündedir — commit edilir ve hangi yolun hangi URL'den alındığını tanımlar.
  • gitlink kaydı commit ağacındadır — 160000 modlu özel bir öğedir, içerik yerine alt modül commit'inin hash'ini tutar.
  • Alt modül repository'sinin kendisi — verileri üst projenin .git/modules/<ad> klasöründe saklanır, alt modül klasöründe ise oraya işaret eden bir .git dosyası bulunur.
cat .gitmodules
[submodule "libs/ui-kit"]
	path = libs/ui-kit
	url = https://github.com/example/ui-kit.git

git ls-tree HEAD libs/
160000 commit 8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c	libs/ui-kit

Dikkat: üst proje branch'i değil, tam olarak commit'i sabitler. Git submodule'ü «main'deki son sürüm» türü bir bağımlılıktan ayıran temel fark budur.

Alt modül nasıl eklenir?

git submodule add https://github.com/example/ui-kit.git libs/ui-kit
Cloning into '/home/dev/shop/libs/ui-kit'...
done.

git status
	new file:   .gitmodules
	new file:   libs/ui-kit

git commit -m "ui-kit'i alt modül olarak ekle"

Komut repository'yi klonlar, .gitmodules dosyasını oluşturur veya günceller ve gitlink'i index'e ekler. Geriye commit etmek kalır. Yol belirtilmezse klasör repository'nin adıyla oluşturulur.

Alt modülün güncellemelerde belirli bir branch'i takip etmesini istiyorsanız bunu baştan belirtin: git submodule add -b develop <url> <yol>. Branch .gitmodules dosyasına branch = develop olarak yazılır.

Göreli URL

Alt modül aynı sunucudaysa göreli bir yol verebilirsiniz: git submodule add ../ui-kit.git libs/ui-kit. Bu yol, üst projenin uzak repository URL'sine göre çözümlenir; bu yüzden proje nasıl klonlandıysa ona göre hem SSH hem HTTPS ile çalışır.

Alt modüllü bir proje nasıl klonlanır?

En sık şikâyet: «klonladım ama alt modül klasörü boş». Varsayılan olarak git clone alt modülleri indirmez. Doğrusu şöyle:

git clone --recurse-submodules https://github.com/example/shop.git

Proje alt modüller olmadan zaten klonlandıysa:

git submodule update --init --recursive

--init, .gitmodules içindeki alt modülleri yerel .git/config dosyasına kaydeder, update onları indirir ve sabitlenmiş commit'e geçirir, --recursive aynısını alt modüllerin içindeki alt modüller için yapar.

Alt modül nasıl güncellenir?

Burada iki görevi ayırt etmek önemlidir: «ekip arkadaşlarının commit ettiği sürümü almak» ve «kütüphanenin yeni bir sürümüne geçmek».

Projede sabitlenmiş sürümü almak

Üst projede git pull sonrasında gitlink değişmiş olabilir, ama alt modül dosyaları kendiliğinden güncellenmez — git status modified: libs/ui-kit (new commits) gösterir. Senkronize edin:

git pull
git submodule update --init --recursive

Bunu elle yapmamak için otomatiği açın: git config submodule.recurse true. Böylece pull, checkout ve switch alt modülleri kendisi günceller. Tek seferlik çağrı için alternatif: git pull --recurse-submodules.

Kütüphanenin yeni sürümüne geçmek

# Seçenek 1: takip edilen branch'in son commit'ini çek
git submodule update --remote libs/ui-kit

# Seçenek 2: sürümü elle seç
cd libs/ui-kit
git fetch
git checkout v3.2.0
cd ../..

# Her iki durumda da yeni sürümü üst projede sabitle
git add libs/ui-kit
git commit -m "ui-kit'i v3.2.0'a güncelle"

--remote, branch'i .gitmodules içindeki branch parametresinden alır; yoksa alt modülün uzak repository'sindeki HEAD'in gösterdiği branch'i (genellikle main) kullanır. Üst projedeki son commit olmadan ekip arkadaşlarınız yeni sürümü almaz: alt modül güncellemesi her zaman commit edilmesi gereken bir gitlink değişikliğidir.

Alt modüllerde neyin değiştiğine şöyle bakmak pratiktir:

git diff --submodule=log
git config diff.submodule log    # bu çıktıyı varsayılan biçim yap
git submodule status
 8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c libs/ui-kit (v3.1.0)
+1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b libs/charts (v1.4.0-3-g1a2b3c4)

git submodule status çıktısındaki önek: - — alt modül başlatılmamış, + — mevcut commit'i üst projede sabitlenenden farklı, U — merge çakışması.

Alt modülde değişiklik nasıl yapılır?

git submodule update sonrasında alt modül detached HEAD durumundadır — bir branch'te değil, belirli bir commit'tedir. Bu haldeyken commit atmaya başlarsanız commit'ler bir sonraki update'te kolayca kaybolabilir. Çalışma sırası:

cd libs/ui-kit
git switch main                  # bir branch'e geç
# ... değişiklikler ...
git commit -am "Buton boşluklarını düzelt"
git push                         # önce alt modülü push et!
cd ../..
git add libs/ui-kit
git commit -m "ui-kit: buton boşlukları düzeltildi"
git push

Push sırası kritiktir. Üst projeyi alt modülden önce gönderirseniz sunucudaki proje sizden başka kimsenin indiremeyeceği bir commit'e işaret eder ve ekip arkadaşlarınızda git submodule update fatal: remote error: upload-pack: not our ref veya did not contain hatasıyla düşer. Korunmak için git push --recurse-submodules=check (alt modül gönderilmemişse push'u reddeder) veya =on-demand (alt modülleri önce kendisi gönderir) kullanın.

Alt modül nasıl silinir?

Eskiden silmek için birkaç dosyayı elle düzenlemek gerekiyordu. Git'in güncel sürümlerinde üç adım yeterli:

git submodule deinit -f libs/ui-kit   # .git/config'ten kaldır ve klasörü temizle
git rm -f libs/ui-kit                 # gitlink'i ve .gitmodules kaydını kaldır
rm -rf .git/modules/libs/ui-kit       # alt modülün saklanan verilerini sil
git commit -m "ui-kit alt modülünü kaldır"

Son adım doğruluk için zorunlu değildir, ancak o olmadan aynı yola alt modülü yeniden eklerken Git yerel klasörün zaten var olduğundan şikâyet edebilir (A git directory for 'libs/ui-kit' is found locally).

Alt modülün URL'si değiştiyse

Repository taşındıysa .gitmodules dosyasını düzeltin ve yerel yapılandırmayı senkronize edin:

git submodule set-url libs/ui-kit https://gitlab.com/example/ui-kit.git
git submodule sync --recursive
git commit -am "ui-kit'in yeni adresi"

Ekip arkadaşlarınızın da pull sonrasında git submodule sync çalıştırması gerekir: .gitmodules içindeki URL, onların .git/config dosyasına yalnızca init veya sync sırasında kopyalanır.

Birden fazla alt modül için faydalı komutlar

GörevKomut
Liste ve durumgit submodule status --recursive
Her birinde komut çalıştırmagit submodule foreach 'git switch main && git pull'
İndirmeyi hızlandırmagit submodule update --init --jobs 4
Geçmiş olmadan indirmegit submodule update --init --depth 1
status'ta kısa özetgit config status.submoduleSummary true

Alt modüllerle sık yaşanan sorunlar

  • Klonlamadan sonra boş klasör — init yapılmamış. Çözüm: git submodule update --init --recursive.
  • pull'dan hemen sonra «modified: (new commits)» — üst proje başka bir commit'e işaret ediyor ama dosyalar eski. Çözüm: git submodule update.
  • Alt modülü yanlışlıkla geri almak — alt modül eski bir commit'teyken git add . çalıştırıp sürüm geri alımını commit etmek. Commit öncesinde her zaman git diff --submodule ile kontrol edin.
  • Merge sırasında gitlink çakışması — iki branch'te alt modül farklı commit'lere güncellenmiş. Alt modüle girin, doğru commit'i seçin (çoğu zaman iki değişikliği de içeren daha yenisi), ardından git add yol yapın ve merge'ü tamamlayın.
  • CI'da özel (private) alt modül — derleme, erişimi olmayan alt modülü indiremez. CI'a alt modül repository'si için bir anahtar veya token verilmelidir; göreli URL'ler yapılandırmayı kolaylaştırır.

Ekipte alt modüller: anlaşmalar

Alt modüllerle ilgili sorunların çoğu Git'ten değil, ekip üyelerinin farklı davranmasından kaynaklanır. Projenin README dosyasına yazmaya değer birkaç kural:

  1. Yalnızca --recurse-submodules ile klonlayın ve herkeste submodule.recurse true açık olsun.
  2. Alt modülü anlaşılır bir mesajla ayrı bir commit'te güncelleyin: hangi sürüm ve neden.
  3. Alt modülün kodunu, alt modülün kendisine ayrı commit ve push yapmadan üst projede düzenlemeyin.
  4. CI'da açıkça git submodule update --init --recursive çalıştırın ve derlemenin yerel değişikliklere bağlı olmadığını kontrol edin.

CI'da alt modüllerin sabitlenmiş tüm commit'lerinin gerçekten erişilebilir olduğunu kontrol etmek için temiz bir klon yeterlidir: biri alt modülü göndermeyi unuttuysa derleme bir hafta sonra bir ekip arkadaşında değil, update adımında düşer.

git clone --recurse-submodules --jobs 4 "$REPO_URL" build
cd build
git submodule status --recursive

Submodule mü, alternatifler mi?

Alt modüller sürüm üzerinde kesin kontrol ve ayrı geçmiş sağlar, ama her ekip üyesine elle yapılacak adımlar ekler. Kod sıradan bir kütüphaneyse paket yöneticisi (npm, pip, Composer, Go modules) daha basittir. Harici kodun proje içinde durması ve ek komut olmadan klonlanması önemliyse git subtree'yi değerlendirin: geçmişi ana repository'ye kopyalar ve ekip arkadaşlarınızın hiçbir şey bilmesi gerekmez. Çok sayıda ilişkili servis için ekipler sıklıkla monorepo'yu seçer. Alt modül, gömülü kodun kendi yaşamı, kendi sürümleri ve kendi ekibi olduğunda haklıdır.

Özet

Git submodule, başka bir repository'nin belirli bir commit'ine yapılan referanstır. Ekleme — git submodule add, alma — --recurse-submodules veya update --init, yeni sürüme güncelleme — update --remote artı üst projede commit, silme — deinit, git rm ve .git/modules temizliği. Alt modül içindeki detached HEAD'i ve push sırasını unutmayın. Git'in ileri düzey araçları Git kursunda pratikte ele alınır.

Sık sorulan sorular

Alt modül neden hep detached HEAD durumunda?

Üst proje branch'i değil commit hash'ini saklar ve git submodule update alt modülü tam olarak bu commit'e geçirir. Değişiklik yapmak için elle bir branch'e geçin veya git submodule update --remote --merge kullanın.

Alt modül bir tag'e sabitlenebilir mi?

Doğrudan hayır, ama alt modülde git checkout ile tag'e geçip ortaya çıkan commit'i üst projede commit edebilirsiniz; git submodule status çıktısında tag parantez içinde görünür.

GitHub ZIP arşivinde alt modülleri indirir mi?

Hayır, GitHub kaynak kod arşivleri alt modüllerin içeriğini içermez, klasörler boş olur. git clone --recurse-submodules kullanın.

git submodule ile git subtree arasındaki fark nedir?

Submodule harici repository'nin bir commit'ine referans saklar ve kodu almak için ayrı komutlar gerektirir; subtree ise dosyaları ve geçmişi doğrudan ana repository'ye kopyalar.

Alt modül başka bir klasöre taşınabilir mi?

Evet, git mv old/path new/path komutuyla: Git .gitmodules dosyasını ve iç referansları kendisi günceller, geriye commit etmek kalır.

Bu konuyu videoyla öğrenin

Bu konu “Sıfırdan Güvenilir Geliştiriciye Git” kursunda uygulamalı olarak ayrıntılı işleniyor.

Kursa git