Wie man Konflikte in Git versteht und löst

Da ist es, das Wort, das jeder Entwickler nicht gerne sieht: Konflikt. 😱 Bei der Arbeit mit Git (oder anderen Versionskontrollsystemen) führt kein Weg an gelegentlichen Zusammenführungskonflikten vorbei.

Aber wenn ich mit Entwicklern spreche, höre ich oft, dass das Thema Zusammenführungskonflikte ein Gefühl der Angst oder des Unbehagens hervorruft .

Der Umgang mit Konflikten bleibt oft ein dunkler, mysteriöser Ort: eine Situation, in der die Dinge schwer kaputt sind und es unklar ist, wie man daraus herauskommt (ohne die Dinge noch schlimmer zu machen).

Zwar sind Zusammenführungskonflikte ein unvermeidbarer Bestandteil des Lebens eines Entwicklers, doch ist das Unbehagen in diesen Situationen völlig optional.

Mit diesem Artikel möchte ich Klarheit in dieses Thema bringen: Wie und wann Konflikte normalerweise auftreten, was sie tatsächlich sind und wie sie gelöst oder rückgängig gemacht werden können.

Wenn Sie diese Dinge richtig verstehen, können Sie mit Zusammenführungskonflikten viel entspannter und sicherer umgehen. 😍

Wie und wann Konflikte auftreten

Der Name sagt es bereits: "Zusammenführungskonflikte" können beim Integrieren von Commits aus einer anderen Quelle auftreten.

Beachten Sie jedoch, dass "Integration" nicht nur auf "Zusammenführen von Zweigen" beschränkt ist. Dies kann auch beim erneuten Basieren oder beim interaktiven erneuten Basieren, beim Ausführen eines Kirschpflückens oder Ziehens oder sogar beim erneuten Anwenden eines Stash auftreten.

Alle diese Aktionen führen eine Art Integration durch - und dann können Zusammenführungskonflikte auftreten.

Aber natürlich führen diese Aktionen nicht jedes Mal zu einem Zusammenführungskonflikt (Gott sei Dank!). Idealerweise sollten Sie sich in diesen Situationen nur selten befinden. Aber wann genau treten Konflikte auf?

Tatsächlich sind die Zusammenführungsfunktionen von Git einer der größten Vorteile: Das Zusammenführen von Zweigen funktioniert die meiste Zeit mühelos, da Git normalerweise in der Lage ist, die Dinge selbst herauszufinden.

Es gibt jedoch Situationen, in denen widersprüchliche Änderungen vorgenommen wurden - und in denen die Technologie einfach nicht entscheiden kann , was richtig oder falsch ist. Diese Situationen erfordern einfach eine Entscheidung eines Menschen.

Der wahre Klassiker ist, wenn genau dieselbe Codezeile in zwei Commits in zwei verschiedenen Zweigen geändert wurde. Git kann nicht wissen, welche Änderung Sie bevorzugen! 🤔

Es gibt einige andere, ähnliche Situationen - zum Beispiel, wenn eine Datei in einem Zweig geändert und in einem anderen gelöscht wurde -, aber sie sind etwas seltener.

Die Git-Desktop-GUI "Tower" bietet beispielsweise eine gute Möglichkeit, solche Situationen zu visualisieren:

Wie man weiß, wann ein Konflikt aufgetreten ist

Keine Sorge: Git wird Ihnen sehr deutlich sagen, wann ein Konflikt aufgetreten ist. 😉  

Zunächst werden Sie sofort über die Situation informiert , z. B. wenn eine Zusammenführung oder Wiederherstellung aufgrund eines Konflikts fehlschlägt:

$ git merge develop Auto-merging index.html CONFLICT (content): Merge conflict in index.html CONFLICT (modify/delete): error.html deleted in HEAD and modified in develop. Version develop of error.html left in tree. Automatic merge failed; fix conflicts and then commit the result.

Wie Sie dem obigen Beispiel entnehmen können, habe ich beim Versuch, eine Zusammenführung durchzuführen, einen Zusammenführungskonflikt erstellt - und Git kommuniziert das Problem sehr klar und schnell:

  • Ein Konflikt in der Datei "index.html" ist aufgetreten.
  • Ein weiterer Konflikt in der Datei "error.html" ist aufgetreten.
  • Und schließlich schlug der Zusammenführungsvorgang aufgrund der Konflikte fehl.

Dies sind die Situationen, in denen wir uns in den Code vertiefen und sehen müssen, was zu tun ist.

In dem unwahrscheinlichen Fall, dass Sie diese Warnmeldungen beim Auftreten des Konflikts übersehen haben, informiert Git Sie zusätzlich, wann immer Sie ausführen git status:

$ git status On branch main You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add/rm ..." as appropriate to mark resolution) deleted by us: error.html both modified: index.html

Mit anderen Worten: Machen Sie sich keine Sorgen , dass Sie Zusammenführungskonflikte nicht bemerken . Git stellt sicher, dass Sie sie nicht übersehen können.

So lösen Sie einen Konflikt in Git und beginnen von vorne

Zusammenführungskonflikte sind mit einer gewissen Dringlichkeit verbunden. Und das zu Recht: Sie müssen sich mit ihnen befassen, bevor Sie mit Ihrer Arbeit fortfahren können.

Obwohl das Ignorieren keine Option ist, bedeutet "Umgang mit Zusammenführungskonflikten" nicht unbedingt, dass Sie sie lösen müssen. Ein Rückgängigmachen ist ebenfalls möglich!

Dies kann eine Wiederholung wert sein: Sie haben immer die Möglichkeit, einen Zusammenführungskonflikt rückgängig zu machen und zuvor zum Status zurückzukehren. Dies gilt auch dann, wenn Sie bereits mit der Lösung der in Konflikt stehenden Dateien begonnen haben und sich in einer Sackgasse befinden.

In diesen Situationen ist es gut zu bedenken, dass Sie immer von vorne beginnen und in einen sauberen Zustand zurückkehren können, bevor der Konflikt überhaupt aufgetreten ist.

Zu diesem Zweck kommen die meisten Befehle mit einer --abortOption, zum Beispiel , git merge --abortund git rebase --abort:

$ git merge --abort $ git status On branch main nothing to commit, working tree clean

Dies sollte Ihnen das Vertrauen geben, dass Sie es wirklich nicht vermasseln können. Sie können jederzeit abbrechen, in einen sauberen Zustand zurückkehren und von vorne beginnen.

Wie Konflikte in Git wirklich aussehen

Nun, da wir sicher sind, dass nichts brechen kann, wollen wir sehen, wie ein Konflikt unter der Haube wirklich aussieht . Dies entmystifiziert diese kleinen Kerle und hilft Ihnen gleichzeitig, den Respekt vor ihnen zu verlieren und Vertrauen in sich selbst zu gewinnen.

Schauen wir uns als Beispiel den Inhalt der (derzeit in Konflikt stehenden) Datei "index.html" in einem Editor an:

Git was kind enough to mark the problem area in the file, enclosing it in <<<<<<< HEAD and >>>>>>> [other/branch/name]. The content that comes after the first marker originates from our current working branch. Finally, a line with ======= characters separates the two conflicting changes.

How to Solve a Conflict in Git

Our job as developers now is to clean up these lines: after we're finished, the file has to look exactly as we want it to look.

It might be necessary to talk to the teammate who wrote the "other" changes and decide which code is actually correct. Maybe it's ours, maybe it's theirs - or maybe a mixture between the two.

This process - cleaning up the file and making sure it contains what we actually want - doesn't have to involve any magic. You can do this simply by opening your text editor or IDE and starting to making your changes.

Often, however, you'll find that this is not the most efficient way. That's when dedicated tools can save time and effort:

  • Git GUI Tools: Some of the graphical user interfaces for Git can be helpful when solving conflicts. The Tower Git GUI, for example, offers a dedicated "Conflict Wizard" that helps visualize and solve the situation:
  • Dedicated Merge Tools: For more complicated conflicts, it can be great to have a dedicated "Diff & Merge Tool" at hand. You can configure your tool of choice using the "git config" command. (Consult your tool's documentation for detailed instructions.) Then, in case of a conflict, you can invoke it by simply typing git mergetool. As an example, here's a screenshot of "Kaleidoscope" on macOS:

After cleaning up the file - either manually or in a Git GUI or Merge Tool - we have to commit this like any other change:

  • By using git add on the (previously) conflicted file, we inform Git that the conflict has been solved.
  • When all conflicts have been solved and added to the Staging Area, you need to complete the resolution by creating a regular commit.

How to Become More Confident and Productive

Many years ago, when I started using version control, merge conflicts regularly freaked me out: I was afraid that, finally, I had managed to break things for good. 😩

Only when I took the time to truly understand what was going on under the hood was I able to deal with conflicts confidently and efficiently.

The same was true, for example, when dealing with mistakes: only once I learned how to undo mistakes with Git was I able to become more confident and productive in my work.

I highly recommend taking a look at the free "First Aid Kit for Git", a collection of short videos about how to undo and recover from mistakes with Git.

Have fun becoming a better programmer!

About the Author

Tobias Günther is the CEO of Tower, the popular Git desktop client that helps more than 100,000 developers around the world to be more productive with Git.