Mitarbeit an einem Github Projekt

Vor kurzem hatte ich beschlossen auch mal herauszufinden wie es denn ist an einem OpenSource Projekt mitzuarbeiten welches auf Github gehostet wird…

In meinem Fall sollte es das Tool youtube-dl sein. Das nutze ich um Videos von Youtube in mp3’s umzuwandeln. Es ist vollständig in Python geschrieben und der komplette Programmcode ist offen auf Github zu finden.

Um nun mitzuhelfen braucht man als erstes Mal einen Github Account. Um den führt kein Weg herum! Kosten tut er aber natürlich nichts.
Außerdem sollte auf dem eigenen (Linux) System Git installiert sein.
Das ist aber mit ‚apt-get install git‘ zumindest unter Debian und Ubuntu schnell erledigt.
Jetzt muss man sich auf dem entsprechenden Linux System (so noch nicht geschehen) einen SSH-Key erzeugen, und diesen anzeigen lassen:

ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub

Dieser Key muss dann in den Github Einstellungen eingetragen werden, damit Github uns kennt und weiß das wir von diesem Computer aus mit unserem Github-Account arbeiten dürfen.

Außerdem muss Git so konfiguriert werden dass es den richtigen Autor-Namen und Mailadresse kennt:

git config --global --edit

Nun sucht man sich auf der Github-Seite des Projektes z.B. einen Fehlerbericht raus (Issue). Ich habe diesen hier gewählt: #12235
(ich habe diesen Issue gewählt, weil es einer der wenigen ist wo ich auf Anhieb meinen Programmcode fehlerfrei hatte 🙂 )

Bevor es nun mit dem Issue weitergeht sollte man sich die komplette Readme des Projektes durchlesen. Zumindest aber den Abschnitt „Developer Instructions„. Dort steht drin wie man arbeiten sollte damit die eigene Arbeit auch in das Projekt aufgenommen wird.
Unter anderem steht da drin dass man Unit-Tests ausführen muss, eigene Tests erzeugen sollte und jeden Programmcode vorher mit Flake8 prüfen muss.
Gut ist es auch zu lesen wie eine gute Commit-Message aussieht.
Dann sollte man natürlich bevorzugt fertige Funktionen des Frameworks von Youtube-Dl verwenden und nicht selber eigene Sachen bauen.
Zusammengefasst: Vor dem Programmieren sollte man erstmal viel lesen!
Sowohl die Readme als auch viel vom Programmcode.

Nun aber weiter mit unserem Issue. Von der Projektseite von Youtube-DL klicken wir auf „Fork“. Damit kriegen wir eine aktuelle Kopie des Git-Repositorys von Youtube-Dl. Das heißt alle commits mit allen Änderungen die jemals stattgefunden haben. Und die „gehören“ nun uns!
WOW!
(Einzig und allein die Issues und die Pull Requests bekommen wir nicht.)

Nachdem wir also nun Youtube-Dl geforkt haben, holen wir uns die Kopie auf unseren aktuellen Computer:

mkdir youtubedlfork
cd youtubedlfork/
git clone git@github.com:ThomasChr/youtube-dl.git .

Den Link zu eurem Fork findet ihr auf der Projektseite eures Forks, die ihr von eurem Github Profil aus aufrufen könnt.

Nun habt ihr also nicht das Repository von Youtube-Dl auf eurem Computer, sondern euren Fork. Das ist auch gut so, denn in eurem Fork dürft ihr natürlich Änderungen machen. Das dürft ihr im Originalrepository natürlich nicht!

Um den Fix zu bauen erzeugt ihr euch nun einen eigenen Zweig (Branch) in den alle Änderungen des Fixes reinkommen, das geht so:

git checkout -b thescenefix

Hiermit habt ihr einen neuen Branch mit dem Namen „thescenefix“ erzeugt. So ein Branch ist praktisch weil ihr alle Änderungen die ihr dort macht unabhängig vom Hauptzweig (master) macht. Somit könnt ihr spielen und probieren ohne etwas kaputt zu machen!

Aufrufen könnt ihr Youtube-Dl direkt aus eurem Repository aus, und zwar so:

python -m youtube_dl http://www.meinvideo.de/video123 -v

Jetzt behebt ihr den Fehler, bei mir in der Datei ‚thescene.py‘:

vi ./youtube_dl/extractor/thescene.py

Mit ‚git diff‘ seht ihr was ihr schon geändert habt.

Bevor ihr nun denkt alles ist richtig, solltet ihr flake8 nutzen.
Dieses installiert ihr mit „apt-get install pip3“, „pip3 install flake8“.
Checken tut ihr eure Datei nun mit:

flake8 ./youtube_dl/extractor/thescene.py

Kommt hier keine Ausgabe ist alles ok. Flake8 prüft unter anderem alle Zeilenumbrüche, Leerzeichen am Zeilende, Leerzeichen in leeren Zeilen und vieles mehr!

Jetzt solltet ihr aber noch checken ob alle Testcases des Extractors noch gehen:

python test/test_download.py TestDownload.test_TheScene

Das testet den ersten Testcase! Wenn es mehr Tests geben sollte (so wie z.B. beim Extractor ProSiebenSat1), so könnt ihr diese so aufrufen, wobei ‚_1‘ der zweite Testcase ist:

python test/test_download.py TestDownload.test_ProSiebenSat1_1
python test/test_download.py TestDownload.test_ProSiebenSat1_2
python test/test_download.py TestDownload.test_ProSiebenSat1_3
python test/test_download.py TestDownload.test_ProSiebenSat1_4

Das Testen von z.B. den Utils-Funktionen geht so:

python test/test_utils.py

Wenn ihr nun zufrieden mit eurer Änderung seid könnt ihr die Datei für einen commit vorbereiten:

git add youtube_dl/extractor/thescene.py

Und nun einen tatsächlichen commit (mit einer aussagekräftigen commit-message) machen:

git commit -m "Fixed Extraction"

Hiermit werden eure vorbereiteten (staged) Änderungen in einem commit übernommen..

Jetzt ladet ihr die Änderung in euren Branch in eurem Fork hoch:

git push origin thescenefix

Hier wird der aktuelle Branch ins Repository „origin“ hochgeladen. Und zwar in den Branch „thescenefix“.
(„origin“ ist ein automatisch von „git clone“ angelegtes Repository. Es ist das Repository wo euer Klon herkommt!)

Und nun müsst ihr nur noch auf der Projektseite von Youtube-Dl einen sog. „Pull Request“ erzeugen. Dabei gebt ihr an dass ihr die Branch „ThomasChr:thescenefix“ in die Branch „rg3:master“ mergen wollt.
Das geht einfach auf der Projektseite von Youtue-Dl unter „Create New Pull Request“

Bei mir sieht das so aus.

Wenn ihr nun großes Glück habt so ist alles richtig und früher oder später wird euer Pull Request einfach in die master-Branch von Youtube-Dl gemerged.
Dann könnt ihr bei Github eurer Branch löschen, und auch auf eurem Computer mittels ‚git branch -d thescenefix“.

Wahrscheinlicher aber ist es, dass ihr etwas falsch gemacht habt. Dann müsst ihr nochmal Änderungen machen, diese nochmal commiten und euren Branch wieder hochpushen in eureren Fork. Durch euren neuen hochgepushten commit aktualisiert sich der Pull Request automatisch!

Wenn ihr übrigens euer lokales Repository aktualiseren wollt, so müsst ihr diesem sagen dass es ein sog. upstream Repository gibt und ihr dessen Änderungen nun holen wollt. Das geht so:

git checkout master
git remote add upstream git://github.com/rg3/youtube-dl.git
git pull upstream master

Erst wird in den Branch „master“ gewechselt, dann wird eine Kopie eures Repositorys hinzugefügt die ihr „upstream“ nennt. Von dieser werden alle Änderungen geholt und eingefügt („git pull“ entspricht einem „git fetch“ und einem nachträglichen „git merge“)

Diese Änderungen wollt ihr nun auch in eurem Github-Fork haben, das ist einfach:

git push origin master

Ihr pusht euren aktuellen Branch nach „Origin“ (das ist das Repo wo ihr herkommt, in diesem Fall das auf github) und dort in den Branch „Master“.

Wichtig sind eventuell noch die Kommandos „git log“ um alle Änderungen im aktuellen Branch zu sehen, und „git show SHA1“ um zu einem commit die detailierten Änderungen zu sehen, sowie „git status“ um zu sehen wo man gerade ist.
„git reflog“ zeigt einem alle commits (auch vermeintlich gelöschte) und kann einem den Hintern retten…
Wenn man übrigens den aktuellen commit auf einen bestimmten setzen muss so geht das mit „git reset –hard SHA1“. Natürlich sollte man da auch wissen was man tut!

Ach und wenn ihr schon mehrere commits in eurem Branch habt, es aber nur einer sein soll, so könnt ihr mittels „git rebase -i master“ wenn ihr in eurer Fix-Branch seid alle Änderungen vom Master nochmal auf eure Branch spielen. Der Trick hierbei ist aber dass ihr eure eigenen commits auch nochmal verändern könnt. So könnt ihr unteranderem mehrere commits zusammenfassen (squash).
Beim push kann es sein dass ihr dann ein ‚-f‘ (für Force) mit anhängen müsst, denn schließlich pusht ihr nicht einfach neue commits nach oben, sondern ihr wollt ja die commits die schon oben sind verändern!

Und was ist nun der Unterschied zwischen Merge und Rebase?
Ein Merge kann entweder ein Fastforward Merge sein, dann werden die Änderungen einer Branch einfach auf den aktuellen Branch aufgesetzt. Das geht aber nur wenn der aktuelle Branch nicht verändert wurde nachdem der andere Branch abgezweigt hat. Ein normaler Merge fügt den aktuellen und den anderen Branch zusammen, er erzeugt dafür einen commit der zwei Parents hat.
Ein Rebase hingegen nimmt alle eigenen commits weg, nimmt dann alle Änderungen des anderen Branch, spielt die beim eigenen Branch ein und fügt danach alle eigenen commits wieder oben drauf.

Wer jetzt denkt dass ich keine Ahnung von Git habe und hier nur irgendwelche Befehle poste ohne sie so Recht zu verstehen, mag eventuell nicht ganz Unrecht haben. Ich denke zwar ich verstehe das meiste, aber es gibt hier wohl noch viel für mich zu lernen.
Korrekturen sind also in den Kommentaren gerne willkommen!

Ach und Bücher kann ich auch noch empfehlen:
Einerseits „Daily Git: Wie ein kompetenter Kollege Ihnen Git erklären würde“ von „Martin Dilger“ und andererseits „Ry’s Git Tutorial“ von „Ryan Hodson“. Wobei ich das zweitere fast noch etwas einfacher finde. Das erste ist manchmal recht ausschweifend ohne dabei viel verständlich zu erklären.

2 Antworten auf „Mitarbeit an einem Github Projekt“

  1. Schade, dass so viel Krempel auf GitHub gehostet wird. Allerdings ist wegen der ekelhaften neuen ToS eine Abwanderung zu beobachten, was ich ausdrücklich gutheißen möchte. Monokulturen sind scheiße.

  2. Gerade das testen kann man übrigens auch super in git-hooks einbauen, denn all zu oft vergisst man das einfach und dann gibts zu recht eine Ermahnung beim mergen durch das core-Team 🙂

    Am besten ist es auch, wenn man oft commitet, damit man keine zu großen Änderungen anhäuft und im Falle (etwas im Code / Verhalten ist doch kaputt gegangen) genau weiß wo der Hase im Pfeffer liegt bzw. man nicht viel verliert.
    Bevor man das pusht, kann man ja die Commits beliebig zusammenfassen und umbenennen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.