Seit zwei Wochen arbeiten wir im Projekt wirklich mit GIT. Bisher kannte ich es nur als Tool, um Open-Source-Projekte zu bekommen, oder für Spielzeug-Repositories auf der eigenen Platte. Die wirklichen Fragen kommen erst jetzt - im realen Leben. 'Bekomme ich wirklich jedesmal alle Updates aller Branches aus dem Repository oder nur den HEAD?' 'Wie läuft denn das mergen, wenn ich gleichzeitig mehrer Branches bekomme?' Ich merke bei meinen Fragen, dass ich noch in SVN denke.

GIT könne endlich Mergen, Branchen mache Spass, weil das Mergen kein Problem sei, habe ich im Vorfeld von den GIT-Befürwortern gehört und nie so richtig geglaubt. SVN kann doch auch mergen. Nachdem ich den ersten Konflikt hatte und die GIT-merge-Datei genauso aussah wie ich das von SVN gewohnt war (letztlich unix-merge), fühlte ich mich bestätigt.

Was ist eigentlich das Problem beim Mergen? In unseren Projekten passiert es öfter, dass es einen Branch gibt, der mehrere Wochen existiert. Sei es, dass hier der Umstieg auf eine neue Version der Software vorbereitet wird, sei es, dass hier Feature programmiert sind, die erst am Tag X in Erscheinung treten sollen, oder dass der Kunden im Live-Betrieb seine Infrastruktur noch erweitern muss. Diese Branches entwickeln sich parallel zum Trunk. Damit das Mergen nicht so kompliziert wird, werden alle paar Tage die Änderungen aus dem Trunk in den Branch gemergt. Und das kann SVN - irgendwie, oder eigentlich doch nicht. Es gibt zwar ein Kommando 'svn merge', doch das merged nur ein Changeset (die Differenz von zwei Versionen - bspw. Trunk zum Zeitpunkt 1 und zum Zeitpunkt 2) in den Branch. Ich sitze dann da mit all den Konflikten, die mir der Merge beschert hat und muss sie auflösen. Danach committe ich wieder und habe eine neue Version im Branch. Das SVN weiss nichts davon, das es sich bei diesem Comit um einen Merge von Version X und Version Y gehandelt hat. Svn hat die Version  geliefert und die Tools angestoßen, die dann den Merge durchführen, den ich selbst als unabhängigen Commit speichere. Wenn ich also den nächsten Merge aus dem Trunk in den Branch mache, muss ich wissen, was ich denn beim letzten Mal gemergt habe. Nur dann kann ich ein neues Changeset so definieren, dass ich alle neuen Änderungen bekomme. Ich kann mir helfen, indem ich in der Commit-Message speichere, was ich beim letzten Mal getan habe, aber das ist nur eine Krücke.

Ganz anders GIT. In GIT nur ein paar Entitäten. Es gibt Blobs, das sind die Inhalte der Dateien. Es gibt Baumobjekte, die die Dateien benennen und die aufeinander verweisen. Und es gibt Commits, die auf ein Baumobjekt und andere Commits verweisen. Branches sind nur PostIts an Commits. Jeder Branch ist also ein Commit mit einem anderen Commit als Vater. Mache ich einen Merge, ist das ein Commit mit zwei Müttern. Die Geschichte meiner Merges und Branches ist explizit im Versionskontrollsystem abgelegt. Ich habe nicht das oben beschriebene Problem. GIT weiss genau, was ich gemergt habe und was noch aussteht. Ich muss nicht durch Kommentare dafür sorgen, das meine Merges funktionieren. (Und natürlich: Beim Mergen auf Dateieben kann GIT auch nicht hexen.)

Was ist jetzt der Unterschied beim Mergen? Für GIT ist ein Merge ein essentielles Konzept, welches explizit modelliert ist. In svn gibt es den Merge nur auf der Ebene der Benutzungsschnittstelle. Die Kernkonzepte kennen ihn nicht. (svn 1.5 soll - Achtung: Hörensagen - den Merge explizit modellieren, allerdings nicht als Kernkonzept.)