Nachverfolgung eines Upstream-Projekts mit git

Bei der Softwareentwicklung sollte man möglichst nie das Rad neu erfinden. Dies gibt beispielsweise schon das DRY-Prinzip vor. Als Erweiterung des Prinzips sollte man sich nicht nur seine eigene Arbeit nicht wiederholen, sondern auch nicht die Arbeit von anderen. Daher werden in allen Softwareprojekten andere Softwareprojekte als Abhängigkeiten verwendet. Es kommt bei externen Abhängigkeiten manchmal zu dem Effekt, dass diese minimale Anpassungen benötigen.

Anpassungen an externen Projekten

Wir nehmen ein beliebiges Open Source Projekt, dass man zuerst anpassen muss, bevor man es benutzen kann. (Hinweis: Bitte vor der Anpassung die Lizenz des Projekts prüfen!). Wir nehmen einen Softwarestand des entsprechenden Projektes, passen den Stand an und verwenden die angepasste Abhängigkeit. Das Problem dabei: Wie übernimmt man seine Änderungen in neue Versionen?

Die Lösung dazu bietet sich im Versionskontrollsystem git. Die Idee ist sehr einfach, erleichtert das Vorgehen aber massiv. Zuerst importiert man den initialen Stand der Software (im unteren Beispiel „Release 1.0“). Diesen Stand brancht man in 2 Richtungen ab:

  1. Der Zweig mit dem offiziellen Stand der Software (upstream genannt)
  2. Der Zweig mit lokalen Änderungen (master)

Jetzt können im „master“ Branch wie gewohnt die notwendigen Anpassungen vorgenommen werden. Sobald eine neue Version der Software erscheint wechselt man in den „upstream“ Branch und importiert die neue Version. Sobald man mit git den Branch „upstream“ wieder in den „master“ merged, erhält man eine automatisch gepatchte Version mit den vorigen Änderungen. Eine meist enorme Zeitersparnis.

git_track_upstream

 

Hinweis: Natürlich ist es möglich (sofern das externe Softwareprojekt git als Versionskontrollsystem verwendet), den händische Import zu vermeiden. Der Arbeitsablauf selbst ändert sich dadurch aber nicht.

Unsauberer Start

Aber was macht man, wenn man erst zu spät feststellt, dass man dieses Vorgehen mit git so einfach ist? Nehmen wir an, wir haben einen Stand des Upstream-Projekts importiert und im gleichen Branch unsere Änderungen gemacht:

git_unclean_track_upstream_pre

Ganz einfach: Man erstellt den Branch „upstream“ indem man ihn vom „master“ abspaltet. Jetzt wechselt man in diesen Branch, löscht den gesamten Inhalt und importiert den offiziellen Stand der Software (der zu dem Stand im „master“ Branch passt, d.h. wenn master eine angepasst Version von 1.0 ist, würde man die offizielle Version 1.0 importieren). Jetzt würde bei einem Merge natürlich das schlimmste Chaos entstehen. Daher muss man git ein wenig helfen. Wir behaupten einfach, dass alles, was derzeit im „upstream“ Branch steckt, bereits zurück in den „master“ gemerged wurde:

git checkout master
git merge -s ours upstream

git_unclean_track_upstream_merge

Damit kann man dann genauso wie oben beschrieben arbeiten, also in „upstream“ immer den aktuellen Stand importieren und in den master mergen.

git_unclean_track_upstream_post

Dieser kleine Trick reduziert die Dauer von mehreren Stunden des händischen Vergleich der Änderungen auf wenige Minuten durch diese Automatisierung. Hinweis: Ein anschließendes Testen des angepassten Softwarestand ist allerdings trotzdem notwendig!

Änderungen an das externe Projekt zurückgeben

Grundsätzlich ist dieses Vorgehen einfach, aber aufwendig (je nach dem wie häufig das Einspielen einer neues Upstream-Version vorkommt). Ich versuche immer, die Änderungen an das externe Projekt zurückzugeben, selbst wenn die Lizenz dies nicht erfordert. Dies reduziert den lokalen Aufwand, stellt die (vermutlich hilfreiche) Anpassung allen anderen Nutzern zur Verfügung und motiviert die Betreuer des externen Projekts.

Copyright © christophbrill.de, 2002-2017.