Core Forking - best practice
Aus Contao Community Documentation
Inhaltsverzeichnis
Core Forking - best practice
Dieses Tutorial beschreibt, wie man einen eigenen Fork von Contao mit git anlegt und beschreibt in einem good practice Szenario wie man eigene Features entwickelt, diese als Pull Requests dem Entwicklerteam übergibt und sein eigenes Repsitory auf dem aktuellen Stand hält.
Dieses Szenario ist nicht nur für den Contao Core geeignet, sondern kann auch auf andere Projekte, die auf github gehostet werden übernommen werden.
Voraussetzungen
git Kentnisse
git ist ein verteiltes Source Code Management System. Wer mit git noch nicht vertraut ist, dem sei das Buch Pro Git, welches Online, gedruckt und auch als eBook erhältlich ist ans Herz gelegt. Es gibt noch andere gute Bücher, z.B. Git. Verteilte Versionsverwaltung für Code und Dokumente die git ausführlich und praktisch erklären.
github Account
github ist einer der größten freien Anbieter für git Repositories auf dem Markt. Ähnlich wie Sourceforge. github wird bereits von vielen großen Unternehmen und Projekten genutzt, z.B. facebook, Twitter, redhat, Apache, eclipse, jquery, mootools und vielen mehr. So ist auch Contao seit dem Contao Camp 2011 auf github zu finden. Für dieses Tutorial wird ein Account auf github benötigt.
Contao Core forken
Der persönliche Fork
Zuerst muss ein persönlicher Fork erstellt werden. Ein Fork ist eine Kopie des Repositories, im eigenen Account. Auf dem Fork kann man beliebig arbeiten, man hat alle Commits die bis zu dem Zeitpunkt gemacht wurden zur Verfügung und kann mit diesen Arbeiten wie es einem beliebt. Um einen persönlichen Fork zu erstellen, muss zuerst das Contao Repository auf github aufgerufen werden. Anschließen reicht ein klick auf den Button Fork um einen persönlichen Fork zu erstellen. Nachdem der Vorgang abgeschlossen ist, wird man direkt auf seinen persönlichen Fork weitergeleitet.
Den persönlichen Fork richtig benennen
Standardmäßig wird der Fork unter dem Namen core erstellt. core kann vieles bedeuten, daher empfiehlt es sich, das Repository sinnvoll umzubenennen. Z.B. in contao-core. Dazu muss zuerst auf den Button Admin geklickt werden, im darauffolgenden Formular lässt sich der Name des Repositories ändern.
Den persönlichen Fork klonen
Als nächstes muss der eigene Fork geklont werden, dazu wird die URL von dem persönlichen Fork benötigt.
$ git clone git@github.com:tristanlins/contao-core.git Cloning into contao-core... remote: Counting objects: 27464, done. remote: Compressing objects: 100% (6952/6952), done. remote: Total 27464 (delta 20159), reused 27310 (delta 20025) Receiving objects: 100% (27464/27464), 17.49 MiB | 152 KiB/s, done. Resolving deltas: 100% (20159/20159), done.
Den Fork aktuell halten
Der Fork ist eine Kopie von dem Zeitpunkt, als dieser erstellt wurde. Neue Änderungen die im Originalrepository durchgeführt werden, kommen nicht automatisch in das eigene Repository. Will man immer auf dem aktuellen Stand bleiben, muss man ein bisschen selbst Hand anlegen.
Zuerst muss ein Remote zum Originalrepository hinzugefügt werden, dies geschieht mit git remote add <name> <url>
, es empfiehlt sich als Remote Name contao zu nehmen. Als URL nehmen wir die öffentliche git URL zum Contao Core Repository https://github.com/contao/core.git
.
$ cd contao-core contao-core/ $ git remote add contao https://github.com/contao/core.git
Anschließend rufen wir die Informationen aus dem Repository ab, so dass diese lokal zur Verfügung stehen.
contao-core/ $ git fetch contao remote: Counting objects: 2624, done. remote: Compressing objects: 100% (936/936), done. remote: Total 1917 (delta 1552), reused 1303 (delta 973) Receiving objects: 100% (1917/1917), 555.81 KiB | 234 KiB/s, done. Resolving deltas: 100% (1552/1552), completed with 329 local objects. From https://github.com/contao/core * [new branch] 2.11.x -> contao/2.11.x * [new branch] 3.0.x -> contao/3.0.x * [new branch] master -> contao/master * [new tag] 2.11.RC1 -> 2.11.RC1 * [new tag] 2.11.RC2 -> 2.11.RC2
Ein Blick auf alle verfügbaren Branches zeigt, dass jetzt nicht nur die lokalen und die aus dem persönlichen Fork (origin), sondern auch die Branches aus dem Contao Core Repository (contao) zur Verfügung stehen.
contao-core/ $ git branch -a * master remotes/contao/2.11.x remotes/contao/3.0.x remotes/contao/master remotes/origin/2.11.x remotes/origin/HEAD -> origin/master remotes/origin/browserversions remotes/origin/database_result_issues remotes/origin/dcasaveperformance remotes/origin/gitignore remotes/origin/master
Während die remotes/origin/* Branches die Branches in dem persönlichen Fork darstellen (man sieht das bereits ein paar zusätzliche angelegt wurden), stellen die remotes/contao/* Branche die aus dem Contao Core Repository dar.
Lokale Branches aktualisieren
Wir gehen von folgender Situation aus, wir haben vor längerer Zeit einen persönlichen Fork erstellt und einen Commit gemacht. Am Contao Core wurde mittlerweile weiter entwickelt und wir wollen die persönlichen Änderungen auf den neuen Stand aufsetzen. Eine Möglichkeit wäre es, den neuen Stand aus dem Core Repository neu zu branchen und die Änderungen manuell einzuspielen. Mit git geht es auch automatisch und zwar mit git rebase
.
Zuerst einmal die Ausgangssituation.
* 76b0bab (tag: 2.10.4, contao/master) Version 2.10.4 * 18bc510 Set all files to CHMOD 644 * dcab24e Correctly handle HTML comments in inline JavaScripts (#3696) * a9199e5 Get the next auto increment ID when importing a theme so deleted themes can be restored (#3604) | * a18c378 (HEAD, master) Make some changes on an old state. |/ * baaa762 (origin/master, origin/HEAD) Correctly handle HTML comments in inline JavaScripts (#3696) * 328ed4a Correctly update the cache after a new template has been created (#3676) * 3a2aefe Do not block resources required by the Google website preview in the robots.txt file (#3688) ...
Der Commit a18c378
stammt von einem alten Commit baaa762
ab. Im contao Repository gibt es aber bereits 4 neue Commits a9199e5
, dcab24e
, 18bc510
und 76b0bab
.
Merge bietet sich in diesem Fall nicht an, da ein Merge die Versionsgeschichte verfälschen würde.
* 6c2bda5 (HEAD, master) Merge remote-tracking branch 'contao/master' |\ | * 76b0bab (tag: 2.10.4, contao/master) Version 2.10.4 | * 18bc510 Set all files to CHMOD 644 | * dcab24e Correctly handle HTML comments in inline JavaScripts (#3696) | * a9199e5 Get the next auto increment ID when importing a theme so deleted themes can be restored (#3604) * | a18c378 (HEAD, master) Make some changes on an old state. |/ * baaa762 (origin/master, origin/HEAD) Correctly handle HTML comments in inline JavaScripts (#3696) * 328ed4a Correctly update the cache after a new template has been created (#3676) * 3a2aefe Do not block resources required by the Google website preview in the robots.txt file (#3688) ...
Was ist falsch? Die Weiterentwicklung von Contao würde durch einen Merge als Abspaltung der Geschichte erkannt. Was aus Sicht des Fork auch korrekt ist, da die Weitereintwicklung ja in einem anderen Repository statt findet. Wir wollen jedoch nicht die Weiterentwicklung in unseren Fork integrieren, sondern wir wollen unseren Fork auf den neuen Stand aufbauen.
Unser Ziel ist ganz einfach, unsere Änderungen, Commit a18c378
soll als direkten Vorgänger den letzten Commit 76b0bab
erhalten, so das die Linearität erhalten bleibt.
Das Ziel sollte also so aussehen.
* ....... (HEAD, master) Make some changes on an old state. * 76b0bab (tag: 2.10.4, contao/master) Version 2.10.4 * 18bc510 Set all files to CHMOD 644 * dcab24e Correctly handle HTML comments in inline JavaScripts (#3696) * a9199e5 Get the next auto increment ID when importing a theme so deleted themes can be restored (#3604) * baaa762 (origin/master, origin/HEAD) Correctly handle HTML comments in inline JavaScripts (#3696) * 328ed4a Correctly update the cache after a new template has been created (#3676) * 3a2aefe Do not block resources required by the Google website preview in the robots.txt file (#3688) ...
Dies können wir mit git rebase
erreichen. Rebase ist ein komplexes Thema, es liefert ähnliche Ergebnisse wie ein Merge, jedoch greift Rebase stark auf die Versionsgeschichte ein. Rebase mit all seinen Möglichkeiten kann hier nicht erklärt werden, daher soll hier lediglich das einfache Rebase gezeigt werden, da es das ist, was wir brauchen.
Um unser Ziel zu erreichen, reicht ein git rebase contao/master
. Das bedeutet so viel wie: Baue mir alle Änderungen meines lokalen Branch (master) auf den Branch contao/master auf. Rebase sucht dafür den nächsten Gemeinsamen Vorgänger, in unserem Fall der Commit baaa762
. Nimmt alle Änderungen die seither in unserem lokalen Branch passiert sind, in unserem Fall nur der Commit a18c378
und baut diese auf den Stand von contao/master, also den Commit 76b0bab
neu auf. Git baut dabei jeden Commit einzeln auf die neue Basis auf. Sollten dabei Konflikte auftreten, meldet git detailliert was zu tun ist.
$ git rebase contao/master First, rewinding head to replay your work on top of it... Applying: Make some changes on an old state.
Danach sieht unsere Versionsgeschichte so aus, wie wir sie haben wollten.
* a93f652 (HEAD, master) Make some changes on an old state. * 76b0bab (tag: 2.10.4, contao/master) Version 2.10.4 * 18bc510 Set all files to CHMOD 644 * dcab24e Correctly handle HTML comments in inline JavaScripts (#3696) * a9199e5 Get the next auto increment ID when importing a theme so deleted themes can be restored (#3604) * baaa762 (origin/master, origin/HEAD) Correctly handle HTML comments in inline JavaScripts (#3696) * 328ed4a Correctly update the cache after a new template has been created (#3676) * 3a2aefe Do not block resources required by the Google website preview in the robots.txt file (#3688) ...
Die lokalen Commits bekommen dabei neue Ids, da sich ihr direkter Vorgänger geändert hat und damit auch das Commit Objekt. Aus unserem Commit a18c378
ist also der Commit a93f652
geworden, der jetzt auf den aktuellen Stand von Contao aufbaut.
Neue Features entwickeln
Der neue Fork besteht standardmäßig aus den gleichen Branches wie das Contao Repository. Um im persönlichen Fork den Überblick nicht zu verlieren, vor allem wenn man mehrere Features parallel entwickeln will, sollte jedes Feature in einem eigenen Branch entwickelt werden. Ein neuer Feature-Branch sollte immer auf einen Branch aus contao/* aufgebaut werden. Dadurch wird das Feature immer auf dem aktuellen Stand entwickelt und kann so von den Contao Entwicklern automatisiert in den Core überführt werden.
Zuerst muss man wissen, für welche Version will man das Feature entwickeln? Für Contao 2.10.5, Contao 2.11 oder sogar schon Contao 3? Diese Frage sollte wenn möglich vorher beantwortet werden, da es einem einige Arbeit ersparen kann. Wir gehen davon aus, dass das neue Feature für Contao 2.11 entwickelt werden soll, das entspricht dem Branch 2.11.x
.
# zuerst aktualisieren wir den lokalen Bestand contao-core/ $ git fetch --all Fetching origin Fetching contao # jetzt lassen wir uns alle verfügbaren Branches anzeigen contao-core/ $ git branch -a * master remotes/contao/2.11.x remotes/contao/3.0.x remotes/contao/master remotes/origin/2.11.x remotes/origin/HEAD -> origin/master remotes/origin/browserversions remotes/origin/database_result_issues remotes/origin/dcasaveperformance remotes/origin/gitignore remotes/origin/master # danach erstellen wir einen neuen Branch, auf Basis von origin/master contao-core/ $ git branch myfeature origin/master Branch myfeature set up to track remote branch master from origin. # und wechseln auf den neuen Branch contao-core/ $ git checkout myfeature Switched to branch 'myfeature'
In dem neuen Branch kann nun das neue Feature entwickelt werden. Wenn alles fertig ist, pushen wir den neuen Branch in unseren Fork.
contao-core/ $ git push -u origin myfeature Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 325 bytes, done. Total 3 (delta 2), reused 0 (delta 0) To git@github.com:tristanlins/contao-core.git * [new branch] myfeature -> myfeature Branch myfeature set up to track remote branch myfeature from origin.
Nach dem alles zu github übertragen wurde, ist der neue Branch im Interface verfügbar.
Einen Pull Request erstellen
Ein Pull Request ist einfach gesagt ein Ticket im Tracker, bei dem auch die Änderungen übermittelt werden. Die Entwickler können über die Änderungen diskutieren, den Pull Request nochmal nachbessern und letztendlich mit ein paar Klicks in das Contao Repository automatisch überführen.
Um einen Pull Request zu erzeugen reicht es, im Interface von github beim persönlichen Fork auf den Button Pull Request zu klicken.
Wichtig ist, dass man genau ausgewählt hat, für welchen Branch im Core Repository der Pull Request bestimmt ist und welchen eigenen Branch man pullen möchte. Die Auswahl der Commit Range erhält man, wenn man auf den Button Change Commits klickt.
Zum Schluss beschreibt man noch, möglichst ausführlich und nachvollziehbar was die Änderungen bewirken und warum sie gemacht wurden. Mit einem Klick auf Send pull request schickt man den Pull Request an die Contao Core Entwickler.
Tips und Troubleshooting
UNIX/DOS Dateiformat automatisch korrigieren
Contao benutzt für alle Dateien das UNIX Format (\n
), wenn man Contao unter Windows klont, kann es vorkommen, dass nach dem Klonen ganz viele Änderungen im Repository gemeldet werden, weil die Dateien alle in das DOS Format (\r\n
) konvertiert wurden. GIT versucht einfach, das Dateiformat der aktuellen Platform zu bestimmen und konvertiert Dateien dann automatisch um. Wer am Contao Core mitentwicklen will, sollte jedoch alle Dateien im UNIX Format comitten. Um GIT zu sagen, dass es nicht die Platformeinstellung nehmen soll, reicht eine Änderung der GIT Konfiguration core.autocrlf.
$ git config --global core.autocrlf input
Der Wert input besagt, dass alle Dateien in das UNIX Format konvertiert werden sollen. Dies gillt für alle neu zum Repository hinzugefügte Dateien, bzw. beim klonen von Repositories. Auf github ist beschrieben wie sich core.autocrlf genau auswirkt und welche Werte die Option annehmen kann.