204 lines
6.2 KiB
Markdown
204 lines
6.2 KiB
Markdown
# Git-Submodule: Der umfassende Praxisleitfaden
|
||
|
||
## Inhalt
|
||
|
||
- [Git-Submodule: Der umfassende Praxisleitfaden](#git-submodule-der-umfassende-praxisleitfaden)
|
||
- [Inhalt](#inhalt)
|
||
- [🔰 Was ist ein Git-Submodul?](#-was-ist-ein-git-submodul)
|
||
- [🧱 Grundlagen](#-grundlagen)
|
||
- [📌 `.gitmodules`](#-gitmodules)
|
||
- [🧠 Merksatz](#-merksatz)
|
||
- [🛠️ Submodul hinzufügen](#️-submodul-hinzufügen)
|
||
- [🔄 Submodule aktualisieren](#-submodule-aktualisieren)
|
||
- [📥 Klonen mit Submodulen](#-klonen-mit-submodulen)
|
||
- [Methode 1: Inklusive Submodule](#methode-1-inklusive-submodule)
|
||
- [Methode 2: Nachträglich initialisieren](#methode-2-nachträglich-initialisieren)
|
||
- [🔃 Submodul-Synchronisation](#-submodul-synchronisation)
|
||
- [📂 Weitere Remotes im Submodul](#-weitere-remotes-im-submodul)
|
||
- [❗ Stolperfallen und Besonderheiten](#-stolperfallen-und-besonderheiten)
|
||
- [🔄 Remote-URL wechseln](#-remote-url-wechseln)
|
||
- [🚀 Push \& Pull Verhalten](#-push--pull-verhalten)
|
||
- [🧼 Submodul löschen](#-submodul-löschen)
|
||
- [🧰 Best Practices](#-best-practices)
|
||
- [📎 Nützliche Kommandos](#-nützliche-kommandos)
|
||
- [📑 Beispiel `.gitmodules` mit kommentierter Remote-Auswahl](#-beispiel-gitmodules-mit-kommentierter-remote-auswahl)
|
||
- [🧭 Alternative: Subtree statt Submodul?](#-alternative-subtree-statt-submodul)
|
||
- [📚 Fazit](#-fazit)
|
||
- [🔗 Weiterführende Links](#-weiterführende-links)
|
||
|
||
---
|
||
|
||
## 🔰 Was ist ein Git-Submodul?
|
||
|
||
Ein **Submodul** ist ein Git-Repository innerhalb eines anderen Git-Repositories. Es erlaubt, einen festen Commit eines externen Repositories als Teilprojekt einzubinden, ohne dessen Dateien direkt zu übernehmen.
|
||
|
||
Beispielhafte Struktur:
|
||
|
||
```plaintext
|
||
hauptprojekt/
|
||
├── .gitmodules
|
||
├── modul1/ ← eingebundenes Submodul
|
||
└── modul2/
|
||
```
|
||
|
||
## 🧱 Grundlagen
|
||
|
||
### 📌 `.gitmodules`
|
||
|
||
Diese Datei beschreibt Pfad und Remote-URL aller eingebundenen Submodule:
|
||
|
||
```ini
|
||
[submodule "modul1"]
|
||
path = modul1
|
||
url = git@github.com:user/modul1.git
|
||
```
|
||
|
||
### 🧠 Merksatz
|
||
|
||
> Submodule sind **Pointer auf einen bestimmten Commit** eines anderen Repositories.
|
||
|
||
## 🛠️ Submodul hinzufügen
|
||
|
||
```bash
|
||
git submodule add <repo-url> <zielpfad>
|
||
git commit -m "📦 Submodul hinzugefügt"
|
||
```
|
||
|
||
Beispiel:
|
||
|
||
```bash
|
||
git submodule add git@github.com:user/libmath.git extern/libmath
|
||
```
|
||
|
||
Erzeugt:
|
||
|
||
- `.gitmodules`
|
||
- Verzeichniseintrag im Git-Index
|
||
- Initialer Checkout des Submoduls (HEAD auf Remote-Commit)
|
||
|
||
## 🔄 Submodule aktualisieren
|
||
|
||
```bash
|
||
cd extern/libmath
|
||
git pull origin main
|
||
cd ../..
|
||
git add extern/libmath
|
||
git commit -m "🔄 Submodul libmath aktualisiert"
|
||
```
|
||
|
||
> Nur das **Hauptrepo speichert den Commit-Zeiger**, nicht den Submodul-Inhalt selbst.
|
||
|
||
## 📥 Klonen mit Submodulen
|
||
|
||
### Methode 1: Inklusive Submodule
|
||
|
||
```bash
|
||
git clone --recurse-submodules <url>
|
||
```
|
||
|
||
### Methode 2: Nachträglich initialisieren
|
||
|
||
```bash
|
||
git clone <url>
|
||
git submodule update --init
|
||
```
|
||
|
||
## 🔃 Submodul-Synchronisation
|
||
|
||
Wenn sich `.gitmodules` ändert (z. B. Remote-URL):
|
||
|
||
```bash
|
||
git submodule sync
|
||
```
|
||
|
||
## 📂 Weitere Remotes im Submodul
|
||
|
||
```bash
|
||
cd modul1
|
||
git remote add backup git@backup.server:repo.git
|
||
```
|
||
|
||
> Diese Remotes sind **lokal**, nicht versioniert. `.gitmodules` kennt nur den Haupt-Remote.
|
||
|
||
## ❗ Stolperfallen und Besonderheiten
|
||
|
||
| Problem | Erklärung |
|
||
|--------|-----------|
|
||
| Submodul wird nicht mitgeclont | `--recurse-submodules` vergessen |
|
||
| Änderungen im Submodul nicht sichtbar | Submodul-Commit im Hauptrepo nicht geupdated |
|
||
| `.gitmodules` zeigt nicht funktionierende URL | z. B. lokale URL nach GitHub-Push – muss angepasst werden |
|
||
| Submodul zeigt „detached HEAD“ | normaler Zustand, wenn Submodul auf festen Commit gesetzt ist |
|
||
|
||
## 🔄 Remote-URL wechseln
|
||
|
||
```bash
|
||
# In .gitmodules ändern oder per Befehl:
|
||
git config -f .gitmodules submodule.modul1.url git@github.com:newuser/libmath.git
|
||
git submodule sync
|
||
```
|
||
|
||
## 🚀 Push & Pull Verhalten
|
||
|
||
| Aktion | Wirkung |
|
||
|---------------------|---------|
|
||
| `git push` im Hauptrepo | Pusht nur Zeiger auf Submodul-Commit |
|
||
| `git push` im Submodul | Muss separat erfolgen |
|
||
| `git pull` im Hauptrepo | Holt *nicht* automatisch neuen Submodul-Stand |
|
||
|
||
## 🧼 Submodul löschen
|
||
|
||
```bash
|
||
# Schritt 1: Entfernen
|
||
git submodule deinit -f pfad/zum/modul
|
||
git rm -f pfad/zum/modul
|
||
rm -rf .git/modules/pfad/zum/modul
|
||
git commit -m "❌ Submodul entfernt"
|
||
```
|
||
|
||
## 🧰 Best Practices
|
||
|
||
- **Nur stabile Submodul-Commits einchecken**, keine laufenden Branches.
|
||
- **Submodule niemals blind aktualisieren** – Änderungen genau prüfen.
|
||
- **Remote-Umschaltung dokumentieren oder automatisieren**, z. B. per Script.
|
||
- **Submodule klein halten** – große, tief verschachtelte Strukturen vermeiden.
|
||
- Für wiederverwendbare Bibliotheken oder Assets ideal (CAD, Snippets, Markdown, etc.).
|
||
|
||
## 📎 Nützliche Kommandos
|
||
|
||
```bash
|
||
git submodule status # Überblick über alle Submodule
|
||
git submodule update --init # Submodule initial holen
|
||
git submodule update --remote # Auf neuesten Remote-Stand updaten
|
||
git config -f .gitmodules ... # .gitmodules direkt bearbeiten
|
||
```
|
||
|
||
## 📑 Beispiel `.gitmodules` mit kommentierter Remote-Auswahl
|
||
|
||
```ini
|
||
[submodule "modul1"]
|
||
path = modul1
|
||
url = ssh://git@local.example.com:2222/myorg/modul1.git
|
||
# url = git@github.com:myorg/modul1.git
|
||
```
|
||
|
||
## 🧭 Alternative: Subtree statt Submodul?
|
||
|
||
Subtree ist einfacher zu verwalten, aber:
|
||
|
||
- kein fester Commit-Zeiger,
|
||
- kein Remote-Wechsel ohne Umweg,
|
||
- gemergte Historie im Hauptrepo.
|
||
|
||
**Submodul = getrennte Repos**
|
||
**Subtree = eingemergter Inhalt**
|
||
|
||
## 📚 Fazit
|
||
|
||
Git-Submodule sind mächtig, aber erfordern **Disziplin und Überblick**. Für wiederverwendbare Komponenten, zentral gepflegte Inhalte oder externe Bibliotheken sind sie oft die bessere Wahl als Duplikate oder Copy-Paste.
|
||
|
||
## 🔗 Weiterführende Links
|
||
|
||
- [Git Book: Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules)
|
||
- [git-scm Doku: submodule](https://git-scm.com/docs/git-submodule)
|
||
- [Vergleich Submodule vs. Subtree](https://www.atlassian.com/git/tutorials/git-submodule)
|