# 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)
