Von Perforce zu Git – Argumente für die Umstellung

Git ist die führende SCM-Lösung für Softwareentwickler. Das Interesse an Git nimmt seit seinem ersten Release 2005 stetig zu. Heute ist Git bei professionellen Teams jeder Größenordnung beliebt, vom Indie-Entwickler bis hin zu großen Enterprise-Unternehmen sowie auch bei wichtigen Open-Source-Projekten wie Android und Linux.

Doch Perforce, ein kommerzielles zentralisiertes SCM-System, findet immer noch großen Anklang bei Spielentwicklern und einigen anderen Gruppen von Softwareentwicklern. Woran liegt das? Um zu verstehen, warum Perforce von diesen Entwicklern weiterhin bevorzugt wird, müssen wir uns die Gründe vor Augen führen, aus denen sich Git in der allgemeinen Softwareentwicklung gegen Perforce und andere zentralisierte SCM-Systeme durchgesetzt hat, und verstehen, warum die Branche für Spielentwicklung langsamer umsteigt.

Wie Git die ganze Welt für sich vereinnahmte

Gehen wir einen Schritt zurück. Wir schreiben das Jahr 1995. Du hast zwei SCM-Optionen: CVS und ClearCase. CVS ist kostenlos und die Features sind jeden Cent wert. ClearCase ist extrem teuer, hat dafür aber einiges zu bieten: Es kommt mit echten Merges klar (und sogar bis zu 64-Way-Merges!), unterstützt die Zusammenarbeit in globalen Entwicklerteams sowie Softwareprojekte mit mehreren Modulen.

Nun tritt Perforce auf die Bildfläche. Es ist zwar nicht kostenlos, aber deutlich günstiger als ClearCase. Das Tool ist weniger leistungsstark als ClearCase, doch relativ schnell und erfüllt seinen Zweck. Genau dies ist das Erfolgsrezept für kommerzielle SCM-Produkte. Und tatsächlich sah es vor ein paar Jahren so aus, als wäre die Stunde einer breitflächigen Einführung von Perforce gekommen, nachdem ClearCase langsam in Vergessenheit geriet und Subversion stagnierte.

Wir springen in die Gegenwart. Git ist jetzt das führende SCM-Tool für Softwareentwickler. Was ist geschehen?

Schnelles verteiltes System

Git ist verteilt: Jeder Entwickler verfügt lokal über den kompletten Verlauf seines Code-Repositorys. Dies verlangsamt den ursprünglichen Klon des Repositorys (es sei denn, du nutzt Smart Mirroring), beschleunigt jedoch nachfolgende Git-Befehle wie commit, blame, diff, merge und log erheblich.

Für Perforce ist meistens sogar eine Verbindung zum Server erforderlich, um den Änderungsverlauf anzuzeigen. Und wenn die Teams und Projekte wachsen, wird dieser einzige zentrale Server zum Nadelöhr. Befehle wie etwa zum Anzeigen des Verlaufs (p4 changes), Erstellen eines Tags (p4 label oder p4 tag), Aufbauen eines Branches (p4 integ) oder Schreibbarmachen einer Datei in deinem Arbeitsbereich (p4 edit) erfordern einen Schreibzugriff auf den Server – der zu einem Engpass wird, wenn Tausende von Benutzern auf diesen Server zugreifen.

Kosten

Perforce veröffentlicht zwar keine Preise mehr, aber es ist bekannt, dass diese sich beim Neuerwerb im Bereich von mehreren Hundert US-Dollar pro Benutzer bewegen und ein gewisser Prozentsatz dieses Preises für die jährlichen Verlängerungen fällig wird. In größeren Teams kann also recht teure Hardware für diesen großen zentralen Server erforderlich sein.

Git selbst ist ein Open-Source-Tool und vollkommen kostenlos. Bitbucket Server kostet mitsamt technischem Support und Installation vor Ort einen Bruchteil von Perforce.

Bei einem Team von 50 Entwicklern würde Bitbucket 600 USD pro Jahr kosten, während Perforce mit Zehntausenden Dollarn zu Buche schlägt. Dafür kannst du deinen fleißigen Hackern sehr häufig ein Mittagessen spendieren.

Workflow

Nüchtern betrachtet geht es bei SCM-Tool im Grunde um das Zusammenarbeiten, also darum, dass ein Entwickler-Team an einer Reihe gemeinsam genutzter Softwaredateien arbeiten kann. Git bietet einige einfache und nicht rechenintensive Branching-Optionen, die viele coole Workflow-Möglichkeiten eröffnen. Von Open-Source-Teams bis hin zu professionellen Entwicklern gibt es für alle den passenden Workflow – ob Aufgaben-Branching, Git-flow oder geforkte Repositorys –, der schnell und einfach funktioniert und mit leistungsstarken Tools für Code-Review und Zusammenarbeit abgerundet wird.

Git erleichtert darüber hinaus die Zusammenarbeit über Unternehmensgrenzen hinweg – dies ist in der funktionsübergreifenden Entwicklung häufig erforderlich. Selbst wenn ein physischer Netzwerkzugriff auf ein geteiltes Git-Repository nicht möglich ist, machen die Git-Patch- und Bundle-Tools das Teilen von Daten leicht.

Perforce pflegt dagegen Branching-Einträge pro Datei, während Git Einträge auf Commit-Basis erstellt. Was bedeutet das? Nun, zunächst einmal entsteht in der Perforce-Datenbank jedes Mal, wenn du einen Branch erstellst, eine enorme Menge an Metadaten. Dies trägt bei größeren Deployments zu Performance-Problemen bei, und zwar in einem solchen Ausmaß, dass Perforce-Administratoren die Branch-Erstellung beschränken.

Stell dir das einmal kurz vor: Jedes Mal, wenn du einen Aufgaben-Branch erstellen möchtest, um ein neues Feature auszuprobieren, musst du um Erlaubnis fragen. Wenn du keine Aufgaben-Branches erstellen kannst, besteht die Gefahr, dass du instabilen Code in den Master Branch eincheckst oder dass du einfach wartest, bis du ganz "fertig" bist, bevor du alles committest. Du opferst bei deinen Aufgaben-Branches somit die Vorteile von CI/CD und die Möglichkeit zum Verfolgen granularer WIP-Aufgaben. Das Ende vom Lied ist eine geringere Produktivität, da die Entwickler entweder unproduktivere Workflows anwenden oder einfach nebenher Git nutzen und einen Weg suchen, ihre Arbeit manuell zurück in Perforce zu mergen.

Perforce-Branches sind nicht nur teuer, sondern auch nicht förderlich für den Workflow, den die meisten Entwickler bevorzugen. Perforce-Branches werden von Benutzern gemeinsam genutzt. Private Aufgaben-Branches mit regelmäßigem Rebasing gibt es daher nicht. Außerdem sind Merge-Algorithmen in Perforce überaus kompliziert. Man findet ganze Artikel mit Anleitungen zum Mergen von unbenannten Dateien oder Dateien mit geänderten Attributen.

Und wie sieht es mit dem Teilen von Code zwischen Perforce-Servern aus? Hier wirst du zurück ins Zeitalter des Austauschs von TAR-Dateien ohne gemeinsamen Verlauf versetzt. Das Datenmodell von Perforce betrachtet einen Softwareverlauf als einzigartig für den jeweiligen Server, wohingegen bei Git das Klonen und Teilen des Verlaufs überall problemlos möglich ist.

Gedankenaustausch und die Community

Mal von den kommerziellen Mitbewerbern abgesehen, wie hat sich Git gegen Mercurial und andere würdige Konkurrenten durchgesetzt? Eigendynamik ist natürlich einiges wert und daran mangelt es Git nicht. Git wurde von Linus Torvalds entwickelt, um die Herausforderungen der verteilten Entwicklung des Linux Kernel-Projekts zu bewältigen, und ist nun zum Standard-SCM-Tool für Linux, Android, OpenStack und auch die meisten anderen bedeutenden Open-Source-Projekte geworden. Wer etwas auf sich hält, verwendet Git. Wenn du also Personalchef bist, kannst du in aller Regel davon ausgehen, dass ein neuer Entwickler mit Git arbeiten kann (und will), ohne ein Training zu erfordern.

Natürlich steht hinter Git auch noch eine dynamische Open-Source-Community, von deren Wissen du profitieren kannst. Git entwickelt sich rasant weiter und löst Alltagsprobleme mit wichtigen neuen Features wie Git LFS. Du kannst im Git-Projekt deinen eigenen Code beisteuern, wenn du einen Fehler findest, den du beheben möchtest. Somit bist du nicht an ein kommerzielles Produkt mit einer Roadmap und das von einem einzigen Unternehmen vorgegebene Entwicklungstempo gebunden. Sieh dir nur einmal die große Auswahl an Git-Client-Programmen an: mehrere leistungsstarke Desktop-GUIs, eine Windows Explorer-Integration, Plug-ins für jede IDE und jedes Entwickler-Tool.

GUIs und Entwickler-Tools

In den Anfangszeiten von Git waren die GUI und der Toolsupport noch nicht sehr ausgearbeitet. Dies war für Benutzer, die eine visuelle Oberfläche für die Interaktion mit ihren Git-Repositorys bevorzugen, ein Stolperstein. Vor allem nicht-technische Mitarbeiter wie z. B. Game Artists blieben außen vor. Bei dieser Zielgruppe war das Windows Explorer-Plug-in von Perforce ein echter Hit.

Doch diese Zeiten sind zum Glück vorbei. GUIs wie SourceTree bieten eine Point-and-Click-Lösung und es gibt eine Vielzahl an Shell-Integrationen für Git. Bitbucket ermöglicht Code-Reviews, Merging und Pull-Requests, Forking und Online-Browsen durch Code sowie eine Unmenge an weiteren Tools zur Zusammenarbeit. Von Data Scientists bis hin zu Kreativagenturen, wirklich alle stellen Communities auf, die sich die offene Zusammenarbeit zunutze machen, die Git und Bitbucket ermöglichen.

Game-Entwickler sind eine Sondergruppe

Was hat also Communitys wie Game-Entwickler oder Forscher, die mit riesigen Datenmengen arbeiten, davon abgehalten, auf den Zug mitaufzuspringen? Letztendlich läuft alles auf die Datenarten und die Komplexität der Projektorganisation hinaus.

Binärdateien

Spielentwickler, insbesondere Game Artists, müssen mit großen Binärobjekten arbeiten, u. a. zur Oberflächenstrukturierung und Audioressourcen. Data Scientists arbeiten mit riesigen Datensätzen, die Milliarden von Beispielszenarien umfassen.

Dies stellt Git vor zwei Probleme.

  • Diese Dateien können nicht gemergt werden. Ein zentralisierter Sperrmechanismus ist praktisch und in Perforce vorhanden. (Beachte jedoch, dass selbst ein zentralisierter Server nur einen Sperrmechanismus in einem einzigen Branch bietet. Wenn du dich auf dieses Feature stützt, heißt das im Prinzip auch, dass du einen sehr eingeschränkten Workflow hast.)

  • Diese Dateien können dazu führen, dass Git mit wachsendem Repository langsamer wird.

Das Problem mit der Repository-Größe wird weitgehend durch Git LFS behoben, einer Erweiterung, mit der Git große Dateien verarbeitet und den tatsächlichen Speicherort von Dateien verlagern kann.

Das Problem der Dateisperrung muss von zwei Seiten betrachtet werden. Aus Sicht des Softwarekonfigurationsmanagements verfügt Git über eine überlegene Art der Dateisperrung in der Roadmap. Git LFS hilft mit einem Algorithmus, der sicherstellt, dass du in jedem Branch immer an der neuesten Version arbeitest, bei der Koordinierung der Sperrung von Binärdateien über mehrere Branches hinweg. Auf diese Weise eröffnen sich Branching-Workflows Benutzern, die mit großen Binärdateien arbeiten, sodass diese nicht mehr auf das Sperrungsmodell von Perforce mit nur einem Branch angewiesen sind.

Es ist außerdem hilfreich, Dateisperrungen als ein Koordinationsproblem zu betrachten. Wenn du an einem gemeinsamen Asset arbeiten möchtest, das nicht gemergt werden kann – wie teilst du dies allen mit, die darüber informiert sein sollten? Hier können moderne Workflows mit Pull-Requests und Zusammenarbeit in Echtzeit abermals so richtig glänzen. Du kannst dein Vorhaben über Hipchat kundtun und nachsehen, ob noch ausstehende WIP-Aufgaben für eine bestimmte Datei vorhanden sind.

Darüber hinaus ist der zukünftige Umgang mit großen Dateien im Zeitalter von Big Data einen Gedanken wert. Um ein Big Data-Analyseprogramm zu testen, benötigst du möglicherweise einen Datensatz in einer Größe von mehreren Terabytes. Vergiss SCM-Systeme – ein solches Projekt wird in einem Big Data-kompatiblen Dateisystem getestet und ausgeführt. Hier wird ein CI/CD-System benötigt, das eine komplexere Pipeline mit Artefakten in HDFS oder S3 befinden, orchestrieren kann. Dies führt uns zum nächsten Thema.

Große Projekte

Game-Entwicklung ist ein klassisches Beispiel für ein Softwareprojekt mit mehreren Modulen oder Komponenten – dem Game-Engine, der Benutzeroberfläche, statischem Artwork, Video-Renderings usw. Perforce als monolithisches zentralisiertes Repository kann all diese Module in einem einzigen Server hosten und lässt die Benutzer wählen, welche Teile sie für ihren eigenen Arbeitsplatz benötigen.

Das ist heute jedoch meist hinfällig. Moderne Git-Systeme wie Bitbucket vereinfachen das Management von Tools mit mehreren Modulen in Git, wie etwa Untermodulen und Unterbäumen. Vor allem haben Großprojekte wie Android gezeigt, wie komplexe Projekte mithilfe übergeordneter Composition-Tools verwaltbar sind. Viele dieser Erkenntnisse sind in moderne CI/CD-Tools wie Bamboo und Bitbucket Pipelines eingeflossen, mit denen komplexe Continuous Integration (CI)-Workflows orchestriert, die Abhängigkeiten zwischen Projekten modelliert und projektübergreifend Artefakte verwaltet werden können.

Dieser Trend folgt im Wesentlichen dem Grundgedanken von Git (und *nix) zum Erstellen von Tools, die sich sehr gut zur Bewältigung von Einzelaufgaben eignen. Continuous Integration (CI) und Continuous Delivery (CD) sind eigenständige Methoden, für die es Tools gibt, die speziell auf leicht verständliche Build- und Release-Workflows ausgerichtet sind. Bei diesen Verfahren werden statt einzelnen Großprojekten kleine selbständige Microservices bevorzugt, was auch den Best Practices der modernen Softwareentwicklung entspricht.

Nächste Schritte

Das "Von Perforce zu Git"-Lager ist ganz klar in Bewegung und Git sowie moderne CI/CD-Tools sind für die größten und komplexesten Entwicklungsaufgaben gerüstet. In der Tat hat Perforce sogar ein Tool namens "Git Fusion" erstellt, mit dem du ein zentrales Perforce-Repository teilweise als ein Git-Repository extrahieren kannst.

So nobel dieser Versuch auch war, ist die Übertragung von Git-Schichten in ein zentralisiertes SCM-System leider nicht gerade einfach. Beim Mischen von Nutzungsmodellen kann leicht die Systemansicht der Daten korrumpiert werden. Und wenn du deine Nutzungsmodelle nicht vermischt, gibt es keinen wirklichen Grund dafür, ein kommerzielles zentralisiertes Backend hinter Git zu stellen. Wir haben eigentlich einen gegensätzlichen Trend beobachtet: Wie kommen die letzten übriggebliebenen Teile des zentralisierten SCM, die noch zu gebrauchen sind, hinüber zu Git?

Wenn du Perforce für deine Software- oder Game-Entwicklung verwendest, fragst du dich wahrscheinlich (nervös), wie eine Migration zu Git abläuft. Ist dies überhaupt möglich? Und lohnen sich die Kosten der Umstellung? Genau darauf werden wir im nächsten Artikel eingehen.

Du möchtest mit Git arbeiten?

Sieh dir dieses interaktive Tutorial an.

Jetzt loslegen