CommunityCodierung & Entwicklunggithub.com

roselletabuena/git-conflict-resolution

Löst Git-Konflikte bei Merge, Rebase, Cherry-Pick, Revert oder Stash-Pop korrekt – versteht die Absichten beider Seiten, kombiniert sie, prüft das Build-Ergebnis und setzt die Operation fort.

Was ist git-conflict-resolution?

Diese Fähigkeit ist ein unverzichtbares Werkzeug für Entwickler, die bei Git-Operationen wie Merge, Rebase, Cherry-Pick, Revert oder Stash-Pop auf Konflikte stoßen. Statt einfach eine Seite zu wählen (was stillschweigend die Arbeit eines Kollegen verwirft), analysiert sie die Absichten beider Seiten. Sie unterstützt alle gängigen Git-Szenarien und bietet Schritt-für-Schritt-Anleitungen: Identifikation der aktuellen Operation (wichtig, da „ours“ und „theirs“ je nach Kontext unterschiedliche Bedeutungen haben), Betrachtung des vollständigen Konflikts mit dem gemeinsamen Vorfahren, Kombination der Änderungen statt Auswahl einer Seite, Verifikation durch Build und Tests sowie das Fortsetzen der Operation. Die Fähigkeit warnt vor den Fallstricken von Befehlen wie `git checkout --ours .` oder `-X theirs`, die gerade während eines Rebases die gegenteilige Wirkung haben können. Sie enthält außerdem Guardrails, die verhindern, dass Konflikte einfach ignoriert oder Rebase-Abbrüche zu früh durchgeführt werden. Zusätzlich behandelt sie wiederkehrende Konflikte durch die `rerere`-Funktion und gibt klare Kriterien vor, wann der Benutzer gefragt werden sollte.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/roselletabuena/skills/tree/HEAD/plugins/git-workflows/skills/git-conflict-resolution

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Konflikte lösen

Ein Konflikt bedeutet, dass Git zwei Änderungen an derselben Stelle gefunden hat und sich weigert zu raten. Eine Lösung ist eine Entscheidung über die Absicht, und der sichere Standard ist, die Absicht beider Seiten zu bewahren. Das Lösen durch Löschen einer Seite lässt die Markierungen zwar verschwinden, macht das Problem aber schlimmer: Der Build besteht trotzdem, und die Änderung eines Kollegen ist verschwunden.

1. Wissen, in welcher Operation Sie sich befinden – ours und theirs hängen davon ab

git status                  # „rebase in progress“ / „You have unmerged paths“ / „cherry-pick in progress“
Operation--ours / HEAD-Seite--theirs-Seite
mergeder Branch, auf dem Sie sindder Branch, der gemerged wird
rebaseder Branch, auf den Sie rebasen (Upstream)Ihr eigener Commit, der wiederholt wird
cherry-pick, revert, stash popder Branch, auf dem Sie sindder Commit, der angewendet wird

Die Zeile für Rebase ist die Falle. Während git rebase main ist „ours“ main und „theirs“ ist die eigene Arbeit des Benutzers, also das Gegenteil eines Merges. git checkout --theirs datei in einem Rebase behält Ihre Änderung und verwirft die des Upstreams. Lesen Sie diese Tabelle erneut, bevor Sie eines der Flags verwenden.

2. Den gesamten Konflikt sehen, nicht nur die Markierungen

git diff --name-only --diff-filter=U        # nicht gemergte Dateien
git status                                   # der Typ: both modified / deleted by us / both added
git config merge.conflictStyle zdiff3        # zeigt auch den gemeinsamen Vorfahren an (git 2.35+; bei älteren diff3 verwenden)
git checkout --conflict=zdiff3 -- <datei>    # EINE Datei mit angezeigtem Basisinhalt neu rendern (verwirft bereits vorgenommene Bearbeitungen)

Mit sichtbarer Basis haben die Markierungen drei Teile: Ihre Seite, das Original, die andere Seite. Die meisten scheinbaren Konflikte werden offensichtlich, wenn Sie sehen können, von was jede Seite geändert hat.

Um zu verstehen, warum jede Seite geändert hat:

git log --merge -p -- <datei>                 # Commits von beiden Seiten, die die Datei betreffen (Merge oder Rebase läuft)
git show REBASE_HEAD                          # während eines Rebase: der Commit, der wiederholt wird
git show :1:<datei>  :2:<datei>  :3:<datei>   # Basis, „ours“, „theirs“ als vollständige Dateien

Lesen Sie die Commit-Nachrichten. Eine Lösung, die Sie nicht in einem Satz pro Seite erklären können, ist eine Vermutung.

3. Durch Kombinieren lösen

  • Beide Seiten haben dieselben Zeilen aus unterschiedlichen Gründen bearbeitet – schreiben Sie die Version, die beides tut. Zum Beispiel: Eine Seite hat einen Parameter tax_rate hinzugefügt, die andere einen Parameter discount: Die gelöste Funktion nimmt beide entgegen und wendet beide an.
  • Eine Seite hat verschoben oder umbenannt, die andere hat bearbeitet – wenden Sie die Bearbeitung an der neuen Stelle an. Behalten Sie nicht die alte Datei und die neue.
  • Von einer Seite gelöscht, von der anderen geändert – das ist eine echte Entscheidung, keine mechanische. Finden Sie heraus, warum es gelöscht wurde; wenn die Änderung noch relevant ist, muss sie übernommen werden, sonst gewinnt die Löschung. Fragen Sie den Benutzer, wenn es unklar ist.
  • Generierte Dateien und Sperrdateien (package-lock.json, poetry.lock, go.sum, Snapshots, kompilierte Ausgaben) – nicht von Hand mergen. Eine Seite nehmen, dann mit dem Tool neu generieren (npm install, poetry lock, go mod tidy, der Snapshot-Befehl).
  • Binärdateien – es gibt keinen Merge; wählen Sie bewusst eine Seite (beachten Sie die obige Tabelle) und sagen Sie dies.

Text kann sauber gemerged werden und trotzdem falsch sein: Wenn eine Seite eine Funktion umbenannt hat und die andere einen Aufruf des alten Namens hinzugefügt hat, sieht Git keinen Konflikt. Deshalb gehört der Build zu Schritt 4.

Pauschale Flags verstecken Entscheidungen. git checkout --ours ., -X ours / -X theirs (die jeden konfliktären Abschnitt zu einer Seite auflösen) und -s ours (die den anderen Branch komplett verwirft) werfen jedes Mal Arbeit weg, ohne sie anzusehen. Verwenden Sie sie nur, wenn der Benutzer genau das verlangt hat und weiß, was fallengelassen wird.

4. Verifizieren, dann fortfahren

git diff --check                              # schlägt fehl bei übriggebliebenen Konfliktmarkierungen und Whitespace-Fehlern
grep -rnE '^(<<<<<<<|=======|>>>>>>>)' .      # zusätzliche Sicherheit in Dateien, die git diff-check nicht prüft
# Build und die schnellsten relevanten Tests ausführen
git add <gelöste-dateien>

Fahren Sie mit dem passenden Befehl fort. Fügen Sie GIT_EDITOR=true hinzu, wo ein Editor geöffnet würde, da ein Editor in einer nicht-interaktiven Shell hängt:

git merge --continue            # oder: git commit --no-edit
GIT_EDITOR=true git rebase --continue
GIT_EDITOR=true git cherry-pick --continue

Ein Rebase spielt Commits einzeln wiederholt ab, daher kann er beim nächsten Commit erneut anhalten. Wiederholen Sie die Schleife. Lösen Sie den Konflikt beim frühesten Commit, in dem er auftritt; spätere können denselben Konflikt erneut darstellen.

Wenn Tests nach der Lösung fehlschlagen, ist der Fehler eine Information über die Lösung. Fahren Sie nicht darüber hinaus fort und „korrigieren“ Sie ihn nicht, indem Sie Tests bearbeiten, bis Sie wissen, welches Verhalten von welcher Seite der Test schützt.

5. Wann anhalten und fragen

Halten Sie an, anstatt zu raten, wenn:

  • beide Seiten Geschäftslogik auf inkompatible Weise geändert haben (zwei unterschiedliche Steuerregeln, zwei unterschiedliche Wiederholungsstrategien);
  • Sie nicht in einem Satz sagen können, warum jede Seite ihre Änderung vorgenommen hat;
  • die Lösung einen Test fehlschlagen lässt und die Ursache nicht klar ist.

Geben Sie die beiden Absichten an, sagen Sie, was Sie wählen würden und warum, und lassen Sie den Benutzer entscheiden. Alles vor --continue ist umkehrbar: git merge --abort, git rebase --abort, git cherry-pick --abort stellen den Baum wieder auf den Ausgangszustand zurück.

Wiederholte Konflikte

Bei einem langen Rebase, bei dem derselbe Konflikt immer wieder auftritt, oder einem Branch, der wiederholt gemerged und aufgegeben wird:

git config rerere.enabled true      # zeichnet jede Lösung auf und spielt sie beim nächsten Mal erneut ab
git rerere diff                      # was aufgezeichnet wurde
git rerere forget-path <datei>       # eine aufgezeichnete Lösung verwerfen, die falsch war

rerere wendet eine Lösung ohne Nachfrage erneut an, daher breitet sich eine schlechte aus. Nach einem durch rerere gelösten Konflikt das Ergebnis dennoch überprüfen.

Wenn ein Branch langlebig und weit zurück ist, bedeutet das einmalige Mergen des Trunks in der Regel eine Runde Konflikte; Rebase wiederholt sie pro Commit. Diese Wahl bleibt dem Benutzer.

Leitplanken

  • Nie lösen, indem Sie pauschal eine Seite übernehmen, um Konflikte verschwinden zu lassen. Die andere Seite ist die Arbeit von jemandem.
  • Brechen Sie einen Rebase nicht ab, den der Benutzer zu Ende führen wollte, nur weil er mühsam ist; brechen Sie nur ab, wenn etwas schiefgeht, und sagen Sie es.
  • Pushen Sie nicht nach dem Lösen, es sei denn, Sie werden darum gebeten. Ein Rebase erfordert einen Force-Push; folgen Sie git-safe-history-rewrite.
  • Melden Sie jede konfliktäre Datei: was beide Seiten getan haben, was Sie behalten haben und alles, was Sie nicht verifizieren konnten.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Verwandte Skills