Mehrere KI-Agenten im selben Git-Projekt: So helfen Worktrees
Gib jedem KI-Agenten einen eigenen Git-Worktree und einen eigenen Branch, wenn mehrere Aufgaben dieselbe Codebasis ändern. So bearbeitet jeder seine eigenen Dateien, während zwei Agenten im selben Ordner fremde Änderungen überschreiben oder sich durch einen Branch-Wechsel stören können. Mit getrennten Worktrees entfallen diese gegenseitigen Eingriffe im gemeinsamen Arbeitsordner; Konflikte beim Zusammenführen und gemeinsam genutzte Dienste musst Du weiterhin selbst koordinieren.
Ein Branch ist ein Entwicklungszweig, ein Worktree der dazu ausgecheckte Dateibaum in einem eigenen Ordner. Mehrere Worktrees gehören zum selben Repository, also demselben Git-Projekt, und teilen dessen Historie. Du brauchst deshalb keine vollständige Kopie der Git-Datenbank pro Agent.
Aufgaben schneiden, bevor der erste Agent startet
Die Grenze zwischen zwei Aufgaben zählt mehr als die Zahl der Agenten, weshalb „Verbessere die Anwendung“ für parallele Arbeit zu offen ist. Besser: Einer ändert die Berechnung, ein anderer die Beschriftung, und beide bekommen klare Dateigrenzen. Gemeinsame Schnittstellen legst Du vorher fest, damit die Aufgaben beim Zusammenführen zueinander passen.
Am 08.07.2026 haben wir in einem Python-Projekt vier unabhängige Aufgaben auf vier Agenten verteilt, jeweils mit einem eigenen Worktree. Das half bei der Trennung, ersparte uns aber weder die Integration noch das Prüfen der Diffs, die geänderte Zeilen gegenüber einem anderen Stand zeigen.
| Aufgabe | Passende Trennung | Deine Entscheidung |
|---|---|---|
| Mehrere voneinander unabhängige Texte erstellen | Eigener Ausgabeordner je Aufgabe | Kein Git-Merge nötig, wenn kein gemeinsamer Code entsteht |
| Zwei Funktionen in derselben Codebasis ändern | Eigener Worktree und Branch je Aufgabe | Dateien zuweisen, anschließend einzeln integrieren |
| Dieselbe Schnittstelle umbauen und gleichzeitig nutzen | Erst Schnittstelle festlegen oder Aufgaben nacheinander ausführen | Die Abhängigkeit verschwindet durch Worktrees nicht |
| Mehrere Entwicklungsserver oder Datenbanktests starten | Worktrees plus getrennte Laufzeitumgebungen | Ports, Testdaten und Dienste ausdrücklich zuordnen |
Für getrennte Textaufgaben reichen eigene Ausgabeordner, weil die Texte nicht zu einem gemeinsamen Programmstand verschmolzen werden müssen. Diesen Unterschied solltest Du prüfen, bevor Du zusätzliche Branches anlegst.
Der Auftrag an jeden Agenten braucht sechs Angaben: Ziel, Ausgangsbranch, Arbeitsordner, erlaubte Dateien, Testbefehl und Abschlusskriterium. Lass ihn außerdem ein kurzes Journal führen, in dem Änderungen, Testergebnisse und offene Fragen stehen. Lege dafür getrennte Dateien oder die jeweilige Sitzung fest, denn eine gemeinsame Journaldatei wäre schon die nächste Konfliktstelle.

Worktrees anlegen und die Trennung prüfen
In unserem Versuch vom 09.09.2026 haben wir zwei Agentenrollen durch gezielte Dateiänderungen nachgestellt, ohne zwei KI-Modelle laufen zu lassen. Geprüft wurden Git, der Commit von außen und das Zusammenführen. Alle folgenden Git- und Python-Befehle stammen aus diesem Versuch, den Du mit Bash, Git ab Version 2.31 und Python 3 in einem leeren Arbeitsordner wiederholen kannst.
Das kleine Projekt enthält einen Grenzwert, eine Beschriftung, ein Changelog und einen Test. Die Git-Konfiguration setzt nur im Labor-Repository die Beispielidentität und schaltet Commit-Signaturen sowie Hooks ab, damit keine persönliche Signatur oder Hooks eingreifen. Bei einem vorhandenen Projekt behältst Du Deine eigene Git-Identität und die dort vorgesehenen Einstellungen.
git init -q -b main repo
git -C repo config user.name Labor
git -C repo config user.email [email protected]
git -C repo config commit.gpgsign false
git -C repo config core.hooksPath /dev/null
cat > repo/werte.py <<'EOF'
LIMIT = 10
EOF
cat > repo/texte.py <<'EOF'
LABEL = 'alt'
EOF
cat > repo/CHANGELOG.md <<'EOF'
Stand: Basis
EOF
cat > repo/test.py <<'EOF'
from pathlib import Path
import sys
from werte import LIMIT
from texte import LABEL
expected_limit = int(sys.argv[1])
expected_label = sys.argv[2]
assert LIMIT == expected_limit, (LIMIT, expected_limit)
assert LABEL == expected_label, (LABEL, expected_label)
changelog = Path(__file__).with_name('CHANGELOG.md').read_text()
assert not any(marker in changelog for marker in ('<<<<<<<', '=======', '>>>>>>>'))
print(f'OK: LIMIT={LIMIT}, LABEL={LABEL}, keine Konfliktmarker')
EOF
python3 -B repo/test.py 10 alt
git -C repo add werte.py texte.py CHANGELOG.md test.py
git -C repo commit -m "Basis mit Mini-Test"
git -C repo worktree add -b agent/a ../agent-a main
git -C repo worktree add -b agent/b ../agent-b mainDie zwei letzten Befehle legen neue Branches ab demselben Commit an, deren Worktrees nun als agent-a und agent-b neben repo stehen. Git führt jeden Befehl mit -C im angegebenen Ordner aus, sodass Du für diese Schritte nicht ständig das Verzeichnis wechseln musst.
Die Git-Dokumentation zu Worktrees beschreibt auch eine wichtige Schutzregel: Derselbe Branch lässt sich standardmäßig nicht in zwei Worktrees gleichzeitig auschecken. Deshalb gehört zu jeder Aufgabe ein eigener Branch; jeder Worktree hat außerdem seinen eigenen Index, die Vormerkliste für den nächsten Commit.
Für Aufgabe A ändern wir den Grenzwert, während Aufgabe B die Beschriftung bekommt und beide absichtlich dieselbe Changelog-Zeile bearbeiten. Im echten Auftrag würdest Du diese gemeinsame Datei möglichst erst bei der Integration pflegen.
cat > agent-a/werte.py <<'EOF'
LIMIT = 12
EOF
cat > agent-a/CHANGELOG.md <<'EOF'
Stand: Limit auf 12
EOF
cat > agent-b/texte.py <<'EOF'
LABEL = 'neu'
EOF
cat > agent-b/CHANGELOG.md <<'EOF'
Stand: Label neu
EOF
python3 -B agent-a/test.py 12 alt
python3 -B agent-b/test.py 10 neu
python3 -B repo/test.py 10 altAlle drei Tests bestanden: A sah den neuen Grenzwert und das alte Label, B dagegen das neue Label und den alten Grenzwert. Der Hauptordner enthielt weiterhin den Ausgangsstand, womit die gewünschte Trennung der Dateistände belegt war. Der Test liest außerdem das Changelog und lehnt ungelöste Konfliktmarker ab; -B verhindert hier Python-Bytecode-Dateien.
Jeder Agent bekommt seinen Worktree
Starte die Agentensitzung im zugewiesenen Ordner und sage ihr ausdrücklich, welche Dateien sie ändern darf und wer committet. Für unser Beispiel wäre der Kernauftrag an A: „Arbeite im Branch agent/a und ändere nur werte.py und die vereinbarte Changelog-Zeile. Prüfe Grenzwert 12 und Label alt und melde am Ende Testausgabe, Git-Status und Commit.“
Laut aktueller Claude-Code-Dokumentation kannst Du in einem schon angelegten Worktree die normale Sitzung mit claude starten. Alternativ erzeugt der folgende Aufruf selbst einen Worktree:
claude --worktree feature-authDie Kurzform des Schalters lautet -w; standardmäßig entsteht der Ordner .claude/worktrees/feature-auth mit dem Branch worktree-feature-auth. Er zweigt dabei vom Standardbranch des Remote-Repositorys ab, meist main; soll er vom gerade ausgecheckten Commit starten, setzt Du in den Einstellungen worktree.baseRef auf head. Dieser Aufbau ist eine Alternative zu unseren manuell angelegten Ordnern; für eigene Subagenten gibt es außerdem isolation: worktree.
Bei Codex CLI wählst Du einen vorhandenen Worktree über den Arbeitsordner, aus dem die Sitzung startet. Das Beispiel kombiniert die Optionen der offiziellen Codex-CLI-Referenz und geht von unserem übergeordneten Arbeitsordner aus:
codex --cd agent-b --sandbox workspace-write--cd, kurz -C, setzt den Arbeitsordner; codex exec ist der Einstieg für nicht interaktive Aufgaben, während --add-dir zusätzliche Schreibpfade erlaubt. Neuere Versionen der Codex CLI kennen zusätzlich den Schalter --worktree, der die Sitzung laut codex --help in einem neuen, von Codex verwalteten Git-Worktree startet; die Worktree-Funktion der Desktop-Oberfläche ist ein eigener Bedienweg.
Ein Worktree ist keine Sicherheits-Sandbox: Er trennt die Arbeitsdateien und den ausgecheckten Branch, während Dateirechte und Sandbox bestimmen, was ein Agent außerhalb dieses Ordners darf. Eine gemeinsame Datenbank, belegte Ports oder globale Paket-Caches trennt Git nicht, und ein verlinktes node_modules-Verzeichnis bleibt ebenfalls gemeinsam genutzt. Eigene Abhängigkeiten pro Worktree kosten wiederum Platz und Zeit.
Arbeitest Du auf einem entfernten Rechner, kommt noch die Terminalsitzung hinzu, die unser älterer Beitrag zu Mosh bei wechselnden Netzverbindungen behandelt. Die Worktrees und Dienste liegen weiterhin auf dem Rechner, auf dem Du sie startest.
Fertig gemeldet, aber noch nicht committet
Bei unserem Lauf am 08.07.2026 konnten zwei von vier Agenten ihre Arbeit nicht committen, weil der Worktree-Index außerhalb ihrer erlaubten Schreibpfade lag. Die Dateien waren fertig, der Commit fehlte: „Fertig“ in einer Agentenantwort sagt eben wenig über den Git-Stand.
Prüfe daher Dateistand und letzten Commit; unser Versuch zeigte den Indexpfad mit diesem Befehl:
git -C agent-a rev-parse --path-format=relative --git-path indexDas Ergebnis war ../repo/.git/worktrees/agent-a/index, also ein Pfad außerhalb von agent-a, den Du bei einem Rechtefehler mit den erlaubten Schreibpfaden abgleichen musst. Im Worktree selbst ist .git nur eine kleine Datei, die auf diesen Verwaltungsordner in repo/.git verweist. Je nach Sandbox braucht dieser Git-Pfad eine zusätzliche Freigabe, die dem Agenten aber nicht pauschal den ganzen Rechner öffnen sollte. Codex hält im Sandbox-Modus workspace-write laut Codex-Sicherheitsdoku das .git im Arbeitsordner und bei einem Worktree auch den verlinkten Git-Ordner schreibgeschützt, während Claude Code in seiner Sandbox Schreibzugriffe auf das gemeinsame .git-Verzeichnis zulässt. Im Labor ließen wir B bewusst uncommittet, ohne den früheren Rechtefehler neu auszulösen.
A prüfte und sicherte seine Arbeit zunächst mit diesen Befehlen, ausgeführt im Ordner agent-a:
git status --short
git diff --check
git diff
git add werte.py CHANGELOG.md
git commit -m "Limit auf 12 setzen"B haben wir anschließend mit den folgenden Befehlen von außen gesichert, wieder im übergeordneten Arbeitsordner. Vorher muss die Agentensitzung ihre Schreibarbeit beendet haben, damit sich der geprüfte Dateistand während des Commits nicht mehr ändert. Der letzte Commit zeigte zunächst noch die Basis, während der Diff bereits das neue Label und den Changelog-Eintrag enthielt:
git -C agent-b status --short
git -C agent-b log -1 --oneline
git -C agent-b diff --check
git -C agent-b diff
git -C agent-b diff --cached
git -C agent-b add texte.py CHANGELOG.md
git -C agent-b diff --cached
git -C agent-b commit -m "Label von aussen sichern"
git -C agent-b status --short
git -C agent-b log -1 --onelineDie Prüfung mit --cached zeigt auch bereits vorgemerkte Änderungen, sodass auffällt, wenn mehr im nächsten Commit landen würde als geplant. Nach unserem Commit war der Status leer, und das Log zeigte den neuen Commit auf B.
Zusammenführen und nach jedem Merge testen
Für den Merge, der die Branches zusammenführt, bestimmst Du eine Reihenfolge und eine zuständige Person oder Sitzung. Prüfe die Diffs vor der Übernahme: Der Vergleich mit drei Punkten zeigt hier die Änderungen des Aufgabenbranches seit dem gemeinsamen Ausgangsstand.
git -C repo status --short
git -C repo diff --check main...agent/a
git -C repo diff main...agent/a
git -C repo merge --no-ff agent/a -m "Agent A integrieren"
python3 -B repo/test.py 12 alt
git -C repo diff --check main...agent/b
git -C repo diff main...agent/b
git -C repo merge --no-ff agent/b -m "Agent B integrieren"Der erste Merge gelang, und der anschließende Test bestätigte Grenzwert 12 und Label alt. Beim zweiten Merge stoppte Git mit Exit 1, wie es die Git-Dokumentation zum Merge für Konflikte beschreibt. Unsere Ausgabe lautete:
Auto-merging CHANGELOG.md
CONFLICT (content): Merge conflict in CHANGELOG.md
Automatic merge failed; fix conflicts and then commit the result.Die getrennten Python-Dateien ließen sich zusammenführen; nur das Changelog war offen, und der Status zeigte dort UU. Beim Lesen der Datei sahen wir beide Fassungen:
<<<<<<< HEAD
Stand: Limit auf 12
=======
Stand: Label neu
>>>>>>> agent/bBeide Aussagen gehören zum Ergebnis, weshalb wir die Konfliktstelle durch eine gemeinsame Zeile ersetzten. Hätten wir beim Auflösen einfach eine Seite behalten, wäre ein gültiger Eintrag verloren gegangen.
cat > repo/CHANGELOG.md <<'EOF'
Stand: Limit auf 12, Label neu
EOF
git -C repo add CHANGELOG.md
git -C repo diff --cached
git -C repo diff --cached --check
git -C repo commit -m "Agent B integrieren, beide Eintraege erhalten"
python3 -B repo/test.py 12 neuDer Test meldete nun OK: LIMIT=12, LABEL=neu, keine Konfliktmarker und prüfte damit den zusammengeführten Stand im Hauptordner. Ein erfolgreicher Test allein in A oder B hätte dieses Ergebnis nicht belegt.
Bei unserem Python-Projekt im Juli lief deshalb nach jedem Merge die reguläre Testsuite; eine abgespeckte Umgebung übersprang mehr Tests und war als Prüfgrundlage schwächer. Übernimm für Dein Projekt den üblichen Testlauf samt nötigen Diensten, denn unser Mini-Test zeigt den Ablauf, ersetzt aber keine echte Projektsuite.

Index-Sperren und Scheindiffs richtig einordnen
Eine Meldung zu index.lock verlangt zuerst eine genaue Diagnose: Fehlt das Schreibrecht, passt der erlaubte Pfad nicht. Existiert die Sperrdatei bereits, kann noch ein Git-Prozess arbeiten; beende laufende Arbeit geordnet, bevor Du über eine verwaiste Sperre entscheidest. Das Git-Kommando worktree lock hat eine andere Aufgabe: Laut Dokumentation schützt es die Registrierung eines Worktrees vor dem Aufräumen.
Eine weitere Falle zeigte sich in unserem Projekt am 08.07.2026: Neu erzeugte JSON-Vergleichsdateien hatten eine andere Formatierung. Der Diff wurde riesig, obwohl sich der Inhalt dieser gespeicherten Vergleichsstände, oft Snapshots oder Golden-Dateien genannt, nicht geändert hatte. Erzeuge sie mit derselben Sortierung und Einrückung wie die bisherige Fassung und trenne echte Änderungen vom bloßen Neuformatieren. Zum Review gehört auch das Lesen jedes Befehls vor dem Ausführen, wie unser Archivbeitrag über versteckte Befehle beim Kopieren ins Terminal an einem historischen Fall zeigt.
Fertige Worktrees aufräumen
Nach der Integration haben wir beide Arbeitskopien auf offene Änderungen geprüft und anhand der Branch-Liste bestätigt, dass A und B in main enthalten waren. Erst dann folgte das Aufräumen:
git -C agent-a status --short
git -C agent-b status --short
git -C repo branch --merged main
git -C repo worktree remove ../agent-a
git -C repo worktree remove ../agent-b
git -C repo worktree prune
git -C repo branch -d agent/a agent/b
git -C repo status --short
python3 -B repo/test.py 12 neuDas gelang ohne Force-Schalter: remove entfernt die Arbeitskopie, während der Branch separat gelöscht wird. Enthält ein Worktree initialisierte Submodule, entfernt remove ihn nur mit --force, deshalb prüfst Du deren Status vorher selbst. Die Git-Dokumentation nennt die Submodul-Unterstützung von Worktrees ohnehin unvollständig und rät davon ab, ein Projekt mit Submodulen mehrfach auszuchecken. Mit prune räumst Du verwaiste Verwaltungsdaten auf, wobei nach regulärem Entfernen dort normalerweise nichts mehr zu tun ist. Unser Abschlusstest bestand, main war sauber, und nur der Haupt-Worktree blieb registriert.
Die erhaltene Git-Historie ist trotzdem keine unabhängige Sicherung, weil alle Worktrees zentrale Repository-Daten teilen. Weshalb auch Spiegel nicht jede Panne abfangen, zeigt der historische KDE-Vorfall mit Git-Repositories von 2013.
Starte für Dein erstes echtes Projekt mit zwei kleinen, klar getrennten Aufgaben. Prüfe vor der Übernahme diese vier Punkte:
- Jede Sitzung hat ihren eigenen Ordner und Aufgabenbranch.
- Die erlaubten Dateien, Laufzeitdienste und der Testlauf sind festgelegt.
- Status, vorgemerkte Änderungen und Commits passen zur gemeldeten Arbeit.
- Nach jedem Merge besteht der Test im gemeinsamen Stand, bevor Du die fertigen Worktrees aufräumst.

Alle Kommentare als Feed abonnieren




















