Development:Git Patch erstellen

Aus TuxBoxWIKI
Version vom 24. Mai 2012, 07:56 Uhr von Dbt (Diskussion | Beiträge) (Formulierung korrigiert)
Wechseln zu: Navigation, Suche


Review-KandidatDieser Artikel befindet sich derzeit im Reviewprozess. Hilf mit, ihn zu verbessern! Falls du bei weiteren Artikeln helfen willst, findest du hier eine Auswahl offener Artikel.

Wer einen Patch bereitstellen möchte, kann mit Git speziell importierbare Patchfiles erstellen. Die nötigen Funktionen werden durch Git ohne Zusatzsoftware zur Verfügung gestellt. Zusätzliche Tools wie diff und patch werden nicht benötigt.

Durch diese Git Eigenheit wird das Arbeiten mit Git auch für die Entwickler deutlich vereinfacht und zudem unterscheidet Git, anders als CVS oder auch SVN zwischen Committer und Autor des Patches. Dies hat unter Anderem zur Folge, das durch einen mit Git formatierter Patch, sofern er korrekt erzeugt und angewendet wurde, auch der Autor in die Historie des Repostories aufgeführt wird.

Dazu kann man wie folgt vorgehen.

Vorbereitung

Sicherstellen das ein gültiger Authorname und eine gültige Emailadresse hinterlegt ist. Wenn nicht, dies global für alle Git Repositories nachholen.

git config --global user.name "Firstname Lastname"
git config --global user.email "your_email@youremail.com"

Oder nur für das lokale Git Repository.

cd /Pfad/zum/Repository 
git config user.name "Firstname Lastname"
git config user.email "your_email@youremail.com"

Quellcode verändern

Diese Schritt ist genauso wie bei anderen SCM-Systemen. Man verändert den Quellcode mit den eigenen gewünschten Veränderungen.

git pull
# adding some modifications

Patch erstellen

Dieser Schritt ist recht einfach. Dazu gibt es einen Git-Befehl. Zuvor müssen die Quellcodeveränderungen committet werden. Also zunächst einen Commit durchführen. Wenn Ihr wirklich nur die Dateien verändert habt, die zum Commit gehören, kann einfach dieses Kommando verwendet werden.

git commit -a

Wenn nicht per

git add <Datei1> <Datei2> ...

die relevanten Dateien selktiv hinzufügen und abschließend

git commit

aufrufen. Hier im Beispiel eine einfache Veränderung der neutrino.cpp.

user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ vi src/neutrino.cpp
user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git commit -a
[tuxbox-port 5756abf] neutrino.cpp: changing debug output to use macro dprintf
1 files changed, 2 insertions(+), 2 deletions(-)

Nun liegen die Veränderungen im lokalen Git Repo und können mit

git format-patch [BRANCH]

als Patch ausgegeben werden. Im Beispiel wurde die neutrino.cpp vom Branch tuxbox-hd/tuxbox-port verändert. Daher dann auch der git-format-patch Befehl gegen diesen Branch. Würde man gegen origin/master in dem Falle den Befehl anwenden, dann würden auch alle Patches bzw. Änderungen aus weiteren Commits ausgegegeben werden, die sich zwischen tuxbox-hd/tuxbox-port und origin/master ergeben.

user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git format-patch tuxbox-hd/tuxbox-port
0001-neutrino.cpp-changing-debug-output-to-use-macro-dpri.patch

Das ist eigentlich schon alles. Diese Datei(en) können nun an einen Entwickler geschickt werden.

Patch von einem Einzel-Commit erstellen

zunächst das Log aufrufen, um den benötigten Commit zu finden. In diesem Beispiel liegt der betreffende Commit ein einem lokalem Branch und sollte unter den letzten paar commits zu finden sein. Pauschal suchen wir nun die letzten Commits ab:

git log -3

Dies gibt nun die letzten Commits aus:

commit ac7abd8db402724f9c195b2091c7a92997edce6e
Author: Thilo Graf <###@n###x.de>
Date:   Mon Apr 16 10:51:07 2012 +0200

    target ntp: add target for ntp
    
    neutrino sectionsd missed ntpdate with error log
    "getUTC: read: invalid argument
    ntpdate not found"
    
    ntpdate should also now can be intstalling with system-tools
    
    
    Signed-off-by: Thilo Graf <###@n###x.de>>

commit 3caecd682aea585f101286ec7cb550813c7ac1df
Author: Stefan Seyfried <seife@tuxbox-git.#######.de>
Date:   Sun Apr 15 19:52:05 2012 +0200

    start_neutrino: prepare for deep standby

commit 874ba0c75afe65ebd0a2482000634ac0c75303f2
Author: Stefan Seyfried <seife@tuxbox-git.#######.de>
Date:   Sun Apr 15 18:48:23 2012 +0200

    spark: use aotom FP to switch the box into deep standby
    
    For this to be really useful, we need support in neutrino.
lines 1-28/28 (END)

Wenn der gewünschte Commit dieser ist: ac7abd8db402724f9c195b2091c7a92997edce6e erzeugt folgendes Kommando einen entsprechenden Patch

 git format-patch -M -C ac7abd8db402724f9c195b2091c7a92997edce6e~1...ac7abd8db402724f9c195b2091c7a92997edce6e

Heraus kommt ein nummerierter Patch:

0001-target-ntp-add-target-for-ntp.patch


Stop hand.png HINWEIS:
  • Die Tilde (~) bei der ersten SHA1 Summe hat die Bedeutung das Git den Bezug auf die Anzahl nach der Tilde angegebenen Comit vor der SHA1 Summe nimmt (auf Commit 3caecd6), im Beispiel eben genau einen Commit davor. Man könnte so z.B. auch Bezug auf den drittletzten oder zehnten Comit vor der angebeben SHA1 Summe nehmen. Damit kann man auch mehrere Commits zu einem in Form eines Patches ohne Rebasing zusammen fassen.
  • Man muss sich nicht die langen SHA1 IDs merken. Git begnügt sich auch mit den ersten sieben Zahlen der SHA1 Summe, wenn es nicht andere Commits gibt die mit den selben Zahlen beginnen.
    • Der obere Befehl kann also auch verkürzt werden:
git format-patch -M -C ac7abd8~1...ac7abd8
0001-target-ntp-add-target-for-ntp.patch

Patch aus mehreren Commits erstellen

Angenommen man arbeitet lokal an einer Sache, die man in üblicherweise in mehreren Commits und in einem separaten Branch abgearbeitet hat und möchte genau diese Commits als Patch weitergeben, kann man diese ebenfalls als Folge von Einzelpatches erzeugen. Befindet sich also z.B. im lokalen Branch "commit" und dieser beinhaltet 4 Commits, würde man das etwa so machen:

$ git format-patch commit~1

Ergebnis:

0001-dvbsi-try-to-fix-broken-neutrino-build-with-cst-dvbs.patch
0002-libdvbsi-add-patch-for-src-time_date_section.cpp.patch

Den oder die erzeugten Patche kann man nun per eMail an eine Mailingliste oder direkt an einen Entwickler schicken.

einen Patch von einer dritten Person erhalten

Es ist möglich, das Ihr von einer anderen Person einen Patch erhalten habt und diesen weitergeben wollt. Wenn diese Person nun wiederum den Patch nicht selbst weitergeben wollte, aber trotzdem einverstanden ist, das der Patch weitergegeben werden kann, dann könnt Ihr diesen Patch noch mit einem SignOff versehen. Dazu einfach die Option --signoff beim git-format-patch mit angeben.

 
user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git format-patch tuxbox-hd/tuxbox-port --signoff
0001-neutrino.cpp-changing-debug-output-to-use-macro-dpri.patch

Danach wie oben schon beschrieben den Patch an einen Developer weiter geben.


einen Patch einspielen

Es gibt einige Möglichkeiten einen Patch direkt anzuwenden. Git stellt hierfür einige Kommandos bereit

git apply

git apply ist quasi das Git-Gegenstück zum allgemein bekannten Unix-Werkzeug patch. Die Anwendung eines solchen Patches ist daher recht einfach, ist aber nur für lokales Arbeiten sinnvoll, um Schnelltests durchzuführen, ansonsten sollte man vorzugsweise auf git am zurückgreifen, insbesondere dann, wenn der Patch vom Autor als "commitreif" zugestellt wurde und für einen Commit in das Remote-Repo vorgesehen ist.
Dazu wird dieser Befehl benutzt:

git apply [/Pfad/zur/Patchdatei]

Einzige Bedingung ist, das Ihr im entsprechenden Git Repository seid.

user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git apply 0001-neutrino.cpp-changing-debug-output-to-use-macro-dpri.patch

git am

Im Unterschied zu git apply werden angewendete Patche wie Commits behandelt, also stellt quasi jeder Patch einen Commit dar. Hat man also einen mit git format-patch formatierten Patch erhalten, kann man diesen Patch mit git am anwenden und überträgt gleichzeitig relevante Daten wie z.B. Autor-Informationen und übernimmt diese in die Historie des Repos. Diese Möglichkeit ist daher gegenüber der git apply Methode vorzuziehen, da hier auch die Leistungen von Contributoren eines Projektes gewürdigt werden. Unter anderen Versionskontrollsystemen wie Subversion oder CVS würde dies nie ins Gewicht fallen.

Ursprünglich ist git am dazu gedacht, Patche direkt aus EMails zu übernehmen, jedoch werden auch Dateien direkt übernommen. Befinden sich der oder die Patche im Stammverzeichnis des Gitrepos, reicht dieser Befehl:

 
git am 0001-neutrino.cpp-changing-debug-output-to-use-macro-dpri.patch

Bei mehreren Patchdateien kann man auch Platzhalter verwenden:

 
git am *.patch