Development
Development
- Allgemein
- Neutrino-HD-Entwicklung
- dbox2 Entwicklung
Dieser Artikel versucht interessierten Entwicklern oder die jenigen die zur Verbesserung der Tuxbox- bzw. auf NeutrinoHD basierender Software beitragen wollen, Informationen über den Entwicklungsprozess zu geben und Fragen von neuen Entwicklern zu beantworten. Wenn Du beim Programmieren helfen willst, aber noch nicht die notwendigen Kenntnisse hast, dürfte dies eine gute Anlaufstelle sein. Bei Fragen hierzu bitte auch die Supportforen oder Mailinglisten nutzen.
Inhaltsverzeichnis
- 1 Source-Code
- 2 Build Dokumentation
- 3 Programmiersprachen
- 4 Codingstyle
- 5 Fehler melden/Bug Report
- 6 Commit Messages
- 6.1 Was sind gute Commit Messages und warum man diese erstellen sollte.
- 6.1.1 Aufbau einer Commit Message
- 6.1.2 Tipps für Gute Commits
- 6.1.2.1 Buildfähigkeit behalten!
- 6.1.2.2 Du bist nichts besonderes!
- 6.1.2.3 Mache einfache Commits!
- 6.1.2.4 Sei spezifisch und genau! Hilf es einfach zu finden!
- 6.1.2.5 Erkläre, was Du gemacht hast, erkläre, warum Du es genau so implementiert hast!
- 6.1.2.6 Teile Auffälligkeiten und Besonderheiten mit!
- 6.1.2.7 Unterlasse unnötige Interjektion
- 6.1.2.8 Stelle keine anderen Mitglieder bloß!
- 6.1.2.9 Arbeiten mit Cherry-Picks
- 6.2 Kommunikation
- 6.3 Wann comitten?
- 6.4 Script zum Erstellen einer ChangeLog
- 6.1 Was sind gute Commit Messages und warum man diese erstellen sollte.
- 7 Code Changes/Source code Repositories
- 8 Dokumentation
- 9 GIT Zugang
- 10 Patch einreichen
- 11 Mailinglisten
- 12 Boards
- 13 Weblinks
Source-Code
- Tuxbox-GIT
- Coolstream GIT
- Gitorious (Buildsystem für Neutrino-MP)
- Neutrino-MP
- GIT Coolstream-SVN-Mirror, Novatux (Neutrino-HD Tuxbox-Port, Tuxbox-CVS Mirror und GNU-Novatux)
Build Dokumentation
HD-Generation
Community Buildsysteme
Yocto/OpenEmbedded basierend
- Yocto:seife-stlinux Recipies für Yocto Buildsystem zum bauen von Neutrino-MP, SH4 basiernde Geräte (Spark)
- Yocto:SDK Arbeiten mit dem Yocto-SDK, Erstellen von Images, Bearbeitung von Quellcode, Komplieren, direktes Testen auf Zielhardware (HD51)
- "Easy Setup" für Yocto/meta-neutrino-mp
- OESTLinux (basierend auf Yocto) für Spark-Boxen mit Sti7111/Sti7162 CPU
SD-Generation
Programmiersprachen
Vorwiegend wird C/C++ verwendet. Für diverse Software oder Tools, die nicht direkt mit der Software oder Treibern für die unterstützen Receivertypen zu tun haben, kann natürlich jede nach Bedarf benötige Sprache verwendet werden. Dies würde beispielsweise einige Tools betreffen, die unter Hostapps im CVS abgelegt worden sind.
Codingstyle
Der Sourcecode von Neutrino ist inzwischen in die Jahre gekommen. Viele Programmierer haben Hand am Source angelegt. Da es nie Maintainer oder besondere Sourcecode Formatierungsregeln gab, ist der Quellcode von Neutrino, und auch der daraus entstandene Quellcode von Neutrino-HD, in unterschiedlichster Weise formatiert. Dies ist für die Lesbarkeit und für das Verständnis des Quellcodes nicht von Vorteil.
Zustand
Der Source der Neutrino Quellen ist zum größten Teil in C++ geschrieben. Es wird aber auch C-Code verwendet. Da teilweise viele Personen an ein und derselben Datei gearbeitet haben kann es innerhalb ein und der selben Datei die unterschiedlichsten Formatierungen geben.
In den sonstigen Dateien wiederum (Shellscripte z.B.) gibt es keine besonderen Unterschiede in den Styles und Formatierungen.
Strukturierung
Für das Formatieren von C/C++ gibt es leicht unterschiedliche Einrückungsstile. Um die Lesbarkeit des Quellcodes zu verbessern sollten Programmierer die in den diversen Dateien arbeiten sich an bestimmte Standards halten. Dies ist kein absolutes Muss, ist aber sehr zuträglich für das Projekt. In anderen GNU Projekten ist die Einhaltung projektspezifischer Standards wegen der Größe dieser Projekte wiederum Pflicht. So zum Beispiel bei der Linuxkernelentwicklung oder beim KDE Projekt.
Modelines
Mit sogenannten Modelines kann man dem Editor seiner Wahl Bearbeitungsoptionen und Anzeigeoptionen mitgeben, sofern dieser dieses Feature unterstützt. Diese Modelines müssen entweder direkt in den bis zu ersten drei Zeilen oder in der letzten Zeile vorhanden sein, allgemein üblich ist am Beginn der Datei. Da historisch bedingt die ersten Editoren reine Text basierende Programme waren bezieht sich der Syntax in der Regel auf Vi/Vim. Eine Modeline (im Beispiel nur in der ersten Zeile) sieht dann z.B. so aus.
// vim:filetype=c:ai:expandtab:tabstop=4:textwidth=72:
//
// file foo.cpp
// The file foo.cpp implements various helper functions.
//
// include <iostream>
// ...
Modelineargument | Erklärung |
vim: |
Start der Modelineanweisungen |
filetype=c |
Angabe des Dateityp, hier C Quelletxt |
ai |
autointend, bei Zeilenumbruch automatisierte Einrückung (funktioniert je nach Editor nicht automatisch) |
expandtab |
automatische Erweiterung von Tabulatoranschlägen mit Leerzeichen |
tabstop=4 |
Anzahl von Zeichen die beim benutzen der Tabulatortaste benutzt werden |
textwidth=72 |
automatisierter Umbruch nach dem 72. Zeichen (Tabs werden aufgelöst) |
Die Anweisungen der Modeline beginnen im Beispiel mit vim:
und werden immer mit einem Doppelpunkt oder auch Leerzeichen getrennt. Zwischen den Kommentarzeichen und dem Beginn der Modeline muss mindestens ein Leerzeichen sich befinden. Genaueres zum Aufbau der Modelines findet man im Wiki vom Vim.
Quelltextformatierungen
Da an Neutrino wohl fast nur Freiwillige arbeiten, ist so eine Forderung nur schwer umzusetzen. Man kann so etwas aber sehr wohl als erstrebenswertes Optimum ansehen und jeder der mitarbeitet, sollte sich so weit es geht an solche Wunschvorgaben halten.
Als ein guter Kompromiss zwischen Lesbarkeit und Platzbedarf hat sich der Stil 1TBS/K&C („One True Brace Style“ von Kernighan und Ritchie) erwiesen. Kurz und kompakt bedeutet das folgendes:
Beispiel Funktionsdeklaration
- Die öffnende Klammer einer Funktion steht immer an einem Zeilenanfang.
void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
{
...
}
- Bei vielen Funktionsübergabeparametern sollten an diesen jeweils möglichst die Zeile umgebrochen werden. Eine Zeile sollte nicht mehr wie 72 Zeichen enthalten.
unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
unsigned int *offset, enum xfer_buf_dir dir)
{
...
}
Beispiel Schleifen
- Schleifen können genauso eingefasst werden. Dies kostet aber relativ viel Platz bei zahlreichen einfachen Aktionen, darum folgende Empfehlung die öffnenden Klammer direkt nach der Bedingung von Schleifen, if...then...else...-Steuerpaaren usw. zu setzen mit der schließenden Klammer vor der nächsten Bedingung. Dieser Stil wird auch in der Kernelentwicklung angewandt und ist sehr gebräuchlich.
if(( hp = gethostbyname( host )) != NULL ) {
memmove( &taddr->sin_addr, hp->h_addr_list[0], sizeof( taddr->sin_addr ));
taddr->sin_port = 0;
taddr->sin_family = AF_INET;
} else if ( inet_aton( host, &taddr->sin_addr ) == 0 ) {
return -1;
}
- Das Gegenstück dazu ist, jede Klammer separat in eine Zeile zu setzen was zwar nicht platz sparend ist, aber die Lesbarkeit des Quellcodes welcher logisch zusammen gehört, wird dabei erhöht. Der selbe Quellcode würde dann so aussehen.
if(( hp = gethostbyname( host )) != NULL )
{
memmove( &taddr->sin_addr, hp->h_addr_list[0], sizeof( taddr->sin_addr ));
taddr->sin_port = 0;
taddr->sin_family = AF_INET;
}
else if( inet_aton( host, &taddr->sin_addr ) == 0 )
{
return -1;
}
- Letztendlich gilt aber auch hier: Benutzt den Stil den Ihr in der Datei vorfindet!
- Die Einrückungstiefe (Tabulator) sollte aus vier Zeichen bestehen. Acht Zeichen sind allerdings auch o.k. Innerhalb einer Datei sollte aber immer die selbe Einrückungstiefe benutzt werden.
- Hier ist zu beachten das je nach verwendeten Editor und dessen Einstellungen unterschiedliche Effekte auftreten können. Die meisten Editoren bieten an eine Tabeinrückung mit der entsprechenden Leerzeichenanzahl aufzufüllen . Kontrolliert Eure Einstellung im Editor.
- Massives oder sogar vollständiges Verändern von Dateien, nur um die obigen Punkte zu erreichen (z.B. durch Tools wie astyle), sind daher grundsätzlich zu vermeiden! Dadurch geht die komplette Historie zu dieser Datei zwar nicht verloren, wird aber stark beeinträchtigt, so dass z.B. Blame-Tools unter Umständen wenig oder keine brauchbaren Daten liefern könnten. Die Historie ist aber bei der Einkreisung von Programmierfehlern teilweise sehr hilfreich! Es sollten daher nur die Stellen vereinzelt nebenher verändert werden, an denen man gerade Veränderungen durchführen will.
Kommentare
Kommentare sind wichtige Bestandteile des Quellcodes! Nutzt diese Möglichkeit der Informationsweitergabe.
Gemessen an vielen C++ Projekten wie sie zB. auf Openhub (früher Ohloh) analysiert werden, sind durchschnittlich 22% aller Quellcode-Zeilen Kommentare. Für Neutrino-HD liegt dieser Wert nur bei 12% und hat damit eine der niedrigsten Quoten, die offiziell bestätigt sind.
Eine hohe Anzahl von Kommentaren könnte darauf hindeuten, dass der Code gut dokumentiert und organisiert ist, und könnte ein Zeichen für teamfähige Mitglieder, ein hilfreiches und diszipliniertes Entwicklungsteam sein.
Leider sind Kommentare in Neutrino und Neutrino-HD aktuell in der Tat sehr spärlich im Code. Es muss nicht jede Subroutine erklärt werden, aber ein Kommentar zu einer Funktion, der Funktionsweise und deren Rückgabewerte sollte aber selbstverständlich sein.
- In internationalen Projekten sind Kommentare in Landessprache des Entwickler verpönt! Üblich und eine von jeden Programmierer verstandene Sprache ist Englisch, also bitte alle Kommentare in Englisch verfassen.
- Kommentare über mehr wie eine Zeile sollten mit
/* ... */
eingefasst und einzeilige Kommentare können mit//
begonnen werden, üblich ist aber auch wieder die Einfassung mit/* ... */
. Kommentare sollten entweder der einzige Inhalt einer Zeile sein oder am Ende einer Codezeile stehen aber niemals mitten im Code (was theoretisch auch geht).
/*
* draw_line
*
* args:
* x1 StartCol
* y1 StartRow
* x2 EndCol
* y1 EndRow
* state LCD_PIXEL_OFF/LCD_PIXEL_ON/LCD_PIXEL_INV
*
*/
oder
if ((fd = open(LCD_DEVICE, O_RDWR)) < 0) {
perror("LCD (" LCD_DEVICE ")"); //giving out an error message
...
folgendes ist auch gebräuchlich
if ((fd = open(LCD_DEVICE, O_RDWR)) < 0) {
perror("LCD (" LCD_DEVICE ")"); /* giving out an error message */
...
Debugausgaben
Ausgabe von Debugmeldungen sind ein wichtiges Hilfsmittel bei der Entwicklung. Für den normalen Betrieb sind diese Debugausgaben jedoch auf die wichtigsten Meldungen zu minimieren. Gerade hier kann Neutrino-HD noch deutlich verbessert werden. Einfache printf
Ausgaben sind für die eigene Entwicklung o.k. sollten aber nicht in ein Versionsverwaltungssystem eingecheckt werden.
Fehler melden/Bug Report
Commit Messages
Was sind gute Commit Messages und warum man diese erstellen sollte.
Commit Messages sind ein wichtiger Bestandteil der Kommunikation und Information in einem Projekt und sollten nicht als lästiges Beiwerk betrachtet werden. Sie dienen dazu, den anderen Beteiligten und Interessenten mitzuteilen, was am Qeuellcode geändert wurde und warum es geändert wurde. Um sicherzustellen, dass diese Informationen nachhaltig, effizient und elektronisch verwertbar sind (z.B. zur Erstellung einer ChangeLog-Datei, Suchfunktionen, Dokumentation), sollten bestimmte Regeln beachtet werden.
Eine aussagekräftige Commit Message erspart anderen Beteiligten eine aufwendige Suche für jetzt und späater und erhöht die Effektivität bei der Zusammenarbeit. Sie bildet auch die Grundlage für eine gezielte Suche, insbesondere bei der Fehlersuche, die in der Regel auf Basis der Commit Messages erfolgt.
Das Schreiben einer aussagekräftigen Commit Message erfordert normalerweise nur wenige Minuten Zeit. Diese Investition kann sich jedoch später durch eine erhebliche Zeitersparnis beim Durchsuchen der History oder des Quellcodes bemerkbar machen, sodass Entwickler sich auf ihre eigentliche Tätigkeit, das Programmieren, konzentrieren können. Wenn Du bisher noch nicht in dieser Weise gearbeitet hast, lies bitte die folgenden Hinweise und überlege, ob es nicht besser wäre, es zumindest auszuprobieren.
Aufbau einer Commit Message
- Die erste Zeile deines Commits sollte immer eine kurze Zusammenfassung aus alphanumerischen Zeichen sein, ohne einleitende Sonderzeichen. Diese Praxis gewährleistet eine saubere Historienansicht und verhindert mögliche Beeinträchtigungen von Suchfunktionen.
- Diese erste Zeile sollte nicht mehr als 50 Zeichen umfassen. Das dient dazu, die Lesbarkeit und Konsistenz von Commit-Nachrichten zu verbessern.
- Ein Grund dafür wäre z.B. Übersichtlichkeit. Viele Git-Tools, wie zum Beispiel Befehlszeilenschnittstellen, grafische Benutzeroberflächen oder Webbasierte Oberflächen wie GitHub usw. , zeigen Commit-Nachrichten nur in begrenzter Breite an. Mit einer maximalen Länge von 50 Zeichen bleibt genug Platz, um den Commit-Titel in einer einzigen Zeile darzustellen, ohne dass er abgeschnitten wird oder den verfügbaren Platz unnötig einnimmt. Ausserdem fördert es die Einhaltung einer einheitlichen Formatierung von Commit-Nachrichten in einem Projekt oder in der gesamten Git-Community. Daher ist dies eine anerkannte Konvention. Editoren können dabei helfen, dies einzuhalten.
- Danksagungen für Zuarbeit oder ähnliches sollten nicht in der ersten Zeile enthalten sein!
- Commit-IDs (egal ob Kurzform oder Langform) haben in der ersten Zeile ebenfalls nichts zu suchen. Wenn es notwendig ist, verweise bitte im erläuternden Teil der Commit-Message auf einen anderen Commit.
- Hintergrund: Commit-IDs zeigen nur auf Commits der Historie, in welcher sie erzeugt wurden. Sobald man Commits in andere Branches übernimmt bzw. pickt oder von anderen Branches rebased, ändern sich die IDs und werden mit ziemlicher Sicherheit nutzlos. Wenn man auf einen Commit verweisen möchte, sollte man daher möglichst immer den Reintext der ersten Zeile des Commits bevorzugt als Verweis nehmen.
- Es ist gute Praxis, die Funktion, logische Einheit oder auch eine Bugnummer gefolgt von einem Doppelpunkt der kurzen Zusammenfassung voranzustellen.
- Diese erste Zeile sollte nicht mehr als 50 Zeichen umfassen. Das dient dazu, die Lesbarkeit und Konsistenz von Commit-Nachrichten zu verbessern.
- Die zweite Zeile bleibt immer leer!
- Ab der dritten Zeile beginnt Deine ausführlichere Darstellung des Commits. Auch hier sollte jede Zeile nicht länger als 72 Zeichen sein (bei Texteditoren evtl. einstellbar), und für die Strukturierung kannst Du diverse Anführungszeichen wie
*, -, #
verwenden.- Schreibe Deine Nachricht in der gegenwartsbezogenen Verlaufsform!
- Bei Revert-Commits ist es wichtig, eine klare Erklärung zu liefern, warum ein vorheriger Commit zurückgenommen wurde. Dadurch wird anderen Entwicklern und Interessierten ermöglicht, die Gründe für die Rücknahme zu verstehen.
Ein Beispiel aus der Linuxkernelentwicklung. [1]
loop: export module parameters Export 'max_loop' and 'max_part' parameters to sysfs so user can know that how many devices are allowed and how many partitions are supported. If 'max_loop' is 0, there is no restriction on the number of loop devices. User can create/use the devices as many as minor numbers available. If 'max_part' is 0, it means simply the device doesn't support partitioning. Also note that 'max_part' can be adjusted to power of 2 minus 1 form if needed. User should check this value after the module loading if he/she want to use that number correctly (i.e. fdisk, mknod, etc.).
Im Vi bzw. VIM lässt sich die maximale Textbreite mit
set textwidth=72
schnell und einfach auf 72 Zeichen setzen! Ein Eintrag dieser Anweisung in die ~/.vimrc
veranlasst Vi bzw. VIM bei jedem Start diese Textbreite zu benutzen. Siehe auch Beispiel einer .vimrc
Tipps für Gute Commits
Die Qualität der Commit-Nachrichten spielt eine wichtige Rolle. Eine unzureichende Beschreibung kann den Eindruck erwecken, dass das Repository schlampig gepflegt wird. Selbst wenn es sich Deiner Ansicht nach um ein privates Projekt handelt, sollte man bedenken, dass die Historie öffentlich zugänglich ist und Interesse wecken kann. Insbesondere wenn man ein Repository bei renommierten Hostern betreibt, auf denen sich auch allgemein bekannte und große Softwareanbieter aus aller Welt tummeln. Wenn man nicht gewissenhaft damit umgeht, sollte man in Erwägung ziehen, das Repository lieber nicht öffentlich zu betreiben.
Buildfähigkeit behalten!
Ein Commit sollte niemals die Funktionalität des Projekts beeinträchtigen, daher gilt dies als goldene Regel. Jeder, der an dem Projekt arbeitet, sollte in der Lage sein, es auch mit deinem Commit weiterzubauen. Vergewissere dich also immer, dass deine Arbeit möglichst fehlerfrei ist, bevor du sie committest. Reverts sind dann zwar ein legitimes Mittel, aber auffällig viele zurückgenommene Commits machen auch keinen guten Eindruck und lässt eher auf mangelnde Sorgfalt schließen.
Du bist nichts besonderes!
Jeder glaubt, dass er gute Commit-Nachrichten schreiben kann, und in den meisten Fällen ist dies auch der Fall. Aber nach einer gewissen Zeit kann jeder, auch Du, nachlässig werden! Wenn Du denkst, dass Deine Commits außergewöhnlich sind, solltest Du kritisch über die letzten 100 Commits nachdenken und überlegen, wie viele davon wirklich außergewöhnlich sind. Mach es einfach mal aus Spaß und überprüfe es selbst.
Mache einfache Commits!
Dies kann wortwörtlich genommen werden: Selbst komplexe Aufgaben sollten in der Regel in einzelnen Commits erledigt werden. Jeder Commit sollte vorzugsweise ein spezifisches Problem lösen, eine neue Funktion hinzufügen oder Änderungen an einer bestimmten Datei vornehmen. Ein Commit sollte eine logische Einheit bilden, die später bei Bedarf einzeln zurückgenommen werden kann, ohne dass andere Commits betroffen sind. Dies ist besonders wichtig, wenn man automatisierte Fehlersuche mit git bisect
betreibt. Finde das richtige Gleichgewicht!
Sei spezifisch und genau! Hilf es einfach zu finden!
Folgende Message hat sicherlich jeder schon gesehen oder gar selber verfasst, einige der schlechtesten aller möglichen Messages!
fixed some bugs
Wow, wer hätte das gedacht!
fix foo id
Na toll, und was war jetzt damit? Muss ich jetzt den Code aufrollen, um zu sehen warum das gemacht wurde?
Und hier der Klassiker:
fix
Super! Hier hat jemand "gewaltig Schreibenergie reingesteckt"!
Beim Verfassen der Commit-Message sollte der Autor berücksichtigen, dass die Umstände, Gründe und Lösungen für das behandelte Problem für andere möglicherweise nicht sofort ersichtlich sind. Daher ist es ratsam, eine kurze Beschreibung des Problems und der Lösung bereitzustellen, um die Nachvollziehbarkeit und Verständlichkeit der Commits zu erhöhen. Auch wenn es zunächst ein gewisser Aufwand ist, kann dies später viel Zeit und Mühe sparen. Insbesondere wenn man bedenkt, dass manche Commits erst viel später überprüft oder noch nachgebessert werden müssen.
Grundsätzlich ist es niemandes Absicht, Bugs einzubauen. Daher sollte Dein Commit darauf abzielen, vorhandene Fehler zu beseitigen. Wenn Du eine größere Anzahl von Fehlern gefunden und behoben hast, solltest Du dies auch in Deiner Commit-Message vermerken und erklären, warum Du dies getan hast. Später wirst auch Du möglicherweise nach etwas suchen, über das Du nur noch vage bescheid weißt, und genau dann wird eine erfolgreiche Suche in den Commit-Messages von Vorteil sein. Schreibe daher eine Commit-Message im Satz, die das Warum zumindest andeutet, wie zum Beispiel:
Fixed bad allocations in image processing routines.
Wie bereits erwähnt, erleichtern mit abschließendem Doppelpunkt versehene thematische Einleitungen das Finden von Commits erheblich. Es empfiehlt sich, den Commit generisch einzuleiten und z.B. den Namen eines Features, eines Moduls (Funktion), eines Branches, Make-Targets, einer Implementierung o.ä. anzugeben. Ein gutes Beispiel hierfür findet sich in der Linux-Kernelentwicklung.
modulX: Fixed bad allocations in image processing routines
oder um es auf einen bestimmten Vorgang einzugrenzen:
clean up: removed unused variables.
So kann es bei komplexen Änderungen hilfreich sein, in der Commit-Message detaillierter zu beschreiben, welche Schritte unternommen wurden, um das Problem zu lösen oder die Funktionalität zu verbessern. Hierbei sollte man jedoch nicht ins Detail verfallen, sondern die Informationen prägnant und verständlich vermitteln. Dies hilft anderen Entwicklern, die Änderung besser zu verstehen und mögliche Auswirkungen auf andere Teile des Codes zu erkennen.
Sehr nützlich kann es sein, wenn man z.B. lokal viel in Branches arbeitet und hier naturgemäß kleinere Commits macht, diese mit dem Branchnamen markiert.
Branch_cleanups modulX: removed unused variables in ...
So fällt es leichter, die Commits auch noch ohne großes darauf schauen, einem Branch zuzuordnen. Wenn der Branchname auch noch ein Thema darstellt, kann man sogar nach einem Merge in den Master-Branch Rückschlüsse auf die Herkunft ziehen, ohne die Historie genauer zu studieren.
Es wird so schnell klar, sich hierbei Gedanken um etwas Organisation zu machen. Das ist noch nicht mal viel Aufwand. Man ist zumindest sich selbst dankbar und froh darüber, ohne großen Aufwand, irgendwann mal einen Commit zu finden, der genau zu einem Problem oder Vorgang passt. Schaue Dir andere Commits an, vergleiche diese mit Deinen.
Erkläre, was Du gemacht hast, erkläre, warum Du es genau so implementiert hast!
Dass Du am Code etwas programmiert, oder was auch immer Du am Code gemacht hast, kann jeder sehen und lesen, deshalb ist es generell ok dies anzumerken, aber erkläre, warum Du die Funktionalität genau so angepasst oder implementiert hast.
Teile Auffälligkeiten und Besonderheiten mit!
Du hast etwas schönes Neues für Dein Projekt, aber da es noch so neu ist und Du nicht alle Varianten prüfen konntest oder wolltest dann teile dies mit!
Adding a special GUI Option for the new entry XY
Dies beschreibt zwar Deine Arbeit, dies aber auch nur halb. Besser ist es zu mindestens noch mitzuteilen was funktioniert und wo es noch Probleme geben könnte.
Tested a seperate GUI entry, it works for the common way, but the function() for coloring may not working for the old models
Unterlasse unnötige Interjektion
Echt jetzt? Solche Messages sind völlig unbrauchbar und eher peinlich, oder was will uns diese Nachricht sagen? Und welchen Eindruck hinterlässt so eine Message bei interessierten Usern oder Kollegen, die sowas lesen. Wie kommt sowas in einem automatisch generiertem Changelog an, welches für einen öffentlichen Auftritt eines Projektes vorgesehen ist?
Im Eifer des Gefechts erstellte Nachrichten sind grundsätzlich kein Problem, solange aus der Nachricht klar hervorgeht, warum sie in dieser Weise formuliert wurde. Fehlerhafte Commits können immer passieren und schnell korrigiert werden. Dennoch wäre es angebracht, eine sachliche Mitteilung zu verfassen.
Stelle keine anderen Mitglieder bloß!
Solche Ansagen braucht keiner:
Fixed up heavy wrong typo, created by Beginner. Keep crap like that out of the code base.
Es ist wichtig, sachlich und konstruktiv zu bleiben, auch wenn man fehlerhaften Code gefunden hat. Anstatt beleidigender oder abfälliger Kommentare, sollte man sich auf das Problem konzentrieren und eine hilfreiche Lösung anbieten. Also lieber an die eigene Nase fassen, Schreibenergie besser in die eigenen Commit-Nachrichten stecken und Diskussionen auf Plattformen wie GitHub, Mailinglisten oder Möglichkeiten zum Austausch nutzen, die das Projekt ohnehin bereitstellt. Wir alle haben einmal klein angefangen, deshalb ist es besser, respektvoll und unterstützend zu bleiben. Eine bessere Commit-Nachricht könnte lauten:
Fixed wrong typo in function() that come with Revision XYZ
Arbeiten mit Cherry-Picks
Das Übernehmen von Commits aus lokalen Branches und anderen Projekten kann eine wertvolle Ressource sein, um Features oder Fehlerbehebungen in das eigene Projekt zu integrieren. Git bietet hierfür eine optimale Lösung: Du kannst bestimmte Commits aus einem Git-Branch in einen anderen Branch übertragen, ohne den gesamten Branch zu mergen. So kannst Du Änderungen aus einem anderen Branch „abholen“ und in Deinem Projekt „einsetzen“. Um Deinerseits einen erfolgreichen Austausch zu gewährleisten, ist es wichtig, dass auch Deine eigenen Commits den allgemeinen Regeln entsprechen und somit als Cherry-Picks für andere Projekte dienen können. Durch die Beachtung bereits genannter Regeln kannst Du den Austausch und die Zusammenarbeit mit anderen Projekten verbessern. Mit Merge Requests verhält es sich prinzipiell ähnlich.
In fremden Projekten oder Ablegern Deines Projekts kann der Zustand der Commits je nach Qualität der Arbeitsweise der dortigen Beteiligten mehr oder weniger stark schwanken. Es ist daher unerlässlich, bei der Übernahme von Commits aus anderen Repositorys sorgfältig zu prüfen, welche Änderungen übernommen werden sollen. Es kommt nicht selten vor, dass einige Commits zu schlecht sind oder Merge Requests abgelehnt werden müssen, da sie sich nicht mit der Historie Deines Projekts vertragen, sich mit lokalen Änderungen überschneiden und komplexe Konflikte verursachen können. Wenn der Commit trotzdem übernommen werden soll, ist in solchen Fällen eine sorgfältige Korrektur unumgänglich. Weitere Probleme sind oft fehlende oder stark rudimentäre Dokumentation der Commits, was es schwierig macht, den Kontext mit dem Projekt zu verstehen und zu interpretieren.
Es kann besonders ärgerlich sein, wenn man versucht, Commits von Ablegern Deines Projekts zu übernehmen, und dabei auf unsauber angelegte Forks stößt. Solche Forks wurden möglicherweise nicht direkt geklont oder ohne gemeinsame Historie initialisiert, beispielsweise indem sie nur aus einem Codearchiv heraus erstellt wurden. In solchen Fällen kann es schwierig sein, bestimmte Features zu übernehmen, wodurch man gezwungen ist, einige Codeteile „roh“ zu übernehmen. Dies hat auch Auswirkungen auf die Behandlung der Autoren, da es schwieriger wird, deren Beiträge angemessen zu einzupflegen.
Das Ziel sollte es sein, eine passende Historie zu erstellen, die es ermöglicht, zukünftige Cherry-Picks ohne Konflikte zu übernehmen.
Wenn Du Commits mit Cherry-Picking übernimmst, solltest Du besonders auf die Commit-Messages achten, die Du dabei übernimmst. Hier sind einige Dinge zu beachten:
- Konsistenz: Wenn Du Commits aus verschiedenen Branches oder Forks auswählst, achte darauf, dass die Commit-Messages in Deiner Projekt-Historie konsistent bleiben. Es ist am besten, die Terminologie und Formatierung Deines Projekts zu verwenden, um eine einheitliche Commit-Historie beizubehalten. Sind Commit-Ids in den gepickten Commits vorhanden, werden diese mit Sicherheit im eigenen Projekt unbrauchbar. Daher wird man gezwungen sein, diese anzupassen. Siehe dazu den Abschnitt Aufbau einer Commit-Message.
- Klare Beschreibung: Stelle sicher, dass die Commit-Messages eine klare Beschreibung der Änderungen enthalten, die im Commit enthalten sind. Eine gute Commit-Message sollte Dir eine Vorstellung davon geben, welche Änderungen im Commit enthalten sind, warum sie gemacht wurden und welche Auswirkungen sie auf das Projekt haben. Sollte das im Quellcommit nicht gegeben sein, passe ihn entsprechend Deinen Konventionen an.
- Vermeide Redundanz: Wenn Du mehrere Commits hast, die dieselben Änderungen enthalten, fasse die Änderungen in einer Commit-Message zusammen, anstatt dieselbe Message für jeden Commit zu verwenden. Dies kann dazu beitragen, die Commit-Historie sauberer und übersichtlicher zu gestalten.
- Zusammenfassung und Details: Fehlt eine gute Commit-Message, sollte eine kurze Zusammenfassung der Änderungen sowie zusätzliche Details enthalten sein, die Dir helfen, die Änderungen besser zu verstehen. Die Zusammenfassung sollte kurz und prägnant sein, während die Details ausführlicher sein können.
- Rückwärtskompatibilität: Wenn du Commits in einen stabilen Release-Branch zurückportierst, achte darauf, dass die Commit-Messages rückwärts kompatibel sind. (siehe auch: Aufbau einer Commit Message; Stichwort Commit ID). Stelle sicher, dass die Commit-Messages verständlich sind, auch wenn der Leser nicht mit den neuesten Änderungen im Projekt vertraut ist.
- Autoreninformationen: In der Regel sollte man versuchen, die ursprünglichen Autoreninformationen beizubehalten, um eine angemessene Anerkennung der Arbeit der ursprünglichen Entwickler sicherzustellen. Wenn Du jedoch den Code so stark anpassen musst, dass die ursprünglichen Autoreninformationen nicht mehr sinnvoll sind, solltest Du die Autoreninformationen anpassen, um diejenigen Personen zu nennen, die den ursprünglichen Code aktualisiert oder bearbeitet haben. Es ist auch wichtig zu beachten, dass es bei der Zusammenführung mehrerer Commits zu Konflikten mit den Autoreninformationen kommen kann. In diesem Fall solltest Du die Informationen so anpassen, dass sie angeben, wer welchen Teil des gepickten Codes erstellt oder aktualisiert hat. Danksagungen allein dürften nicht ausreichen, um die Autoreninformationen korrekt zu behandeln. Die Autoreninformationen sollten möglichst im Code selbst enthalten sein und korrekt angezeigt werden, wenn der Code in ein Repository integriert wird. Das Hinzufügen von Autoreninformationen im Dateikopf oder in einer Header-Datei des Quellcodes ist eine gute Praxis, um sicherzustellen, dass die Autoreninformationen korrekt und vollständig sind.
- Verwende Git-Tools wie Git Cherry-Pick mit der Option "-x", um sicherzustellen, dass die ursprünglichen Autoreninformationen des Commits automatisch in den Commit-Text eingefügt werden.
- Nichts überstürzen: Es ist wichtig, bei der Entscheidung, ob man ein neues Feature aus einem Fork-Projekt sofort übernehmen soll oder nicht, vorsichtig und überlegt vorzugehen. Wenn das neue Feature noch nicht vollständig getestet wurde oder der Code noch stark fehlerhaft scheint, sollte man vorsichtig sein und warten, bis das Feature ausgereift ist. Es ist auch wichtig zu beachten, dass Fork-Projekte oft von Entwicklern oder kleinen Teams gepflegt werden, die möglicherweise andere Herangehensweisen haben. Es besteht also ein höheres Risiko für Fehler und Inkompatibilitäten. Wenn im Repository, von dem man picken möchte, auffällig viele Revert-Commits zu finden sind, sollte man definitiv vorsichtig sein. Bevor man ein neues Feature aus einem Fork-Projekt übernimmt, sollte man auch sicherstellen, dass es tatsächlich sinnvoll ist und in die eigenen Entwicklungspläne passt. Man sollte sich fragen, ob das Feature wirklich einen Mehrwert für das eigene Projekt bringt oder ob es nur eine nette Ergänzung wäre. Insgesamt sollte man vorsichtig sein und das neue Feature prüfen, bevor man es in das eigene Projekt integriert.
Kommunikation
In gewissen Situationen ist es wichtig, dass die Mitwirkenden eines Projekts in gegenseitigem Austausch stehen, um kontroverse Ansichten zu diskutieren und sicherzustellen, dass unpassende Änderungen vermieden werden. Eine erfolgreiche Zusammenarbeit erfordert dabei Kommunikations- und Kompromissbereitschaft. Da nicht jeder Beteiligte über das gleiche Knowhow und den gleichen Zeitrahmen verfügt, ist es sinnvoll, die Aufgaben zu verteilen. Die Ansprechpartner ergeben sich dann relativ von selbst.
Wenn die Kommunikation ins Stocken gerät, kann es passieren, dass manche Teilnehmer dazu neigen, ungeduldig zu werden und sich entscheiden, ihr eigenes Ding zu machen, entweder spontan oder langfristig heimlich geplant. Es ist ziemlich schlechter Stil, sich als „Abtrünniger“ mittels Ghosting quasi aus dem Staub zu machen und durch mutmaßliche Kontaktverweigerung aufzufallen, da dies den Unmut der übrigen Beteiligten hervorrufen kann und langfristig niemandem hilft.
In Zeiten von Git, spielen Unterprojekte (Forks) eine gewisse Rolle, was bestimmte Vor- und Nachteile mit sich bringt. Je nach Seriosität und Wartungsgrad solcher Projekte, kann das eine wertvolle Bereicherung sein, aber gerade hier kann sich die benannte Kontaktverweigerung mit Ansage negativ auswirken und den Sinn des Ganzen kaputt machen. Man sollte daher den Zugewinn an Möglichkeiten, sich auszutauschen, nicht verspielen.
Kommunikation gegenüber Endnutzern spielt sich insofern ab, als in der Regel Fehler gemeldet werden, deren Behebung sowie Ideen und deren schnelle Umsetzung gefordert werden, jedoch gibt es dafür oft verschiedene Lösungsansätze und Zeitrahmen. Endnutzer sind naturgemäß daran interessiert, Wünsche schnell umgesetzt zu bekommen. Nutzer sehen aber oft nicht die sachlichen bzw. technischen Hintergründe. Bei gewünschten Implementierungen oder Übernahmen von Features ist es leider nicht immer mit einem einfachen Cherry-Pick aus verwandten Fork-Projekten getan, wenn dort schwer durchschaubare, unsaubere oder schlampige "Commit-Kultur" herrscht. Man sollte und kann daher nicht um jeden Preis allen Requests aus der Community bedingungslos nachkommen, nur weil dort ein nettes Feature drin ist, welches man auch gerne hätte. Übereifrige Übernahmen könnten thematische Überschneidungen in den Projekten von Kollegen verursachen und evtl. bessere Lösungsansätze kaputt machen, was zum Teil frustrierende Auswirkungen haben kann. Ständiges durchforschen, weil mal wieder nicht aus den Commits klar erkennbar ist, was diese oder jene Änderung für Hintergründe hatte, weil nicht ersichtlich wird, ob diese Funktionen fehlerfrei, Nachbesserungen geplant oder nötig sein werden, sind nur einige Negativ-Beispiele. Das kann man oft nur schwer vermitteln.
Brauchbare Lösungen und Konzepte lassen sich daher nur effektiv über Kommunikationswege vermitteln, auch hier sollte man die Wirksamkeit schlüssiger Commit-Nachrichten über Projektgrenzen hinaus nicht unterschätzen. Auch für zukünftige Dokumentationen sind diese Mitteilungen nachhaltige Informationsquellen und oft kann sich Kommunikation als Erstes um einen oder mehrere im Kontext stehende Commits entwickeln. Generell sind Commits mit aussagekräftigen Mitteilungen die erste Schnittstelle für Kommunikation und das sogar projektübergreifend. Commitmessages sollte man daher erst recht nicht vernachlässigen.
Langfristig gesehen, kann sich ein Projekt auch nur weiter entwickeln, wenn alles möglichst ausgewogen ineinander greift. Sollte man den Sinn einer Open-Source Gemeinschaft falsch verstanden haben oder der Meinung sein, sich unbedingt aus der Community hervorzutun, indem man versucht einem Projekt seinen ganz eigenen Stempel aufzudrücken, kann dies über kurz oder lang dazu führen, dass bestimmte Features, die nicht essenziell notwendig sind, gezielt gemieden werden und kein Austausch mehr erfolgt, was im Endeffekt zur völligen Inkompatibilität führen kann.
Wann comitten?
Lokal ist es ratsam, Entwicklungsschritte abgetrennt in einem Branch und einzelne Commits zu packen, auch wenn diese zu einer Gesamtaufgabe gehören sollten. Auf diese Weise kann man flexibel reverten oder weitere Branches ableiten, um Tests durchzuführen und anschließend wieder auf den ursprünglichen Branch zu rebasen. Wenn man mit dem Ergebnis zufrieden ist oder der Meinung ist, dass alles stimmig ist, kann man die einzelnen Commits zusammenfassen (z.B. mit dem Befehl git rebase -i) und als Patchsammlung verschicken oder als Entwickler den Entwicklungsbranch rebasen und in das Remote-Repo pushen."
Entwickler sollten nicht jeden lokalen Commit sofort in ein Remote-Repo pushen. Vorabtests sind angebracht. Es ist empfehlenswert, die Commits lokal zu korrigieren und auf den Stand des Remote-Repos zu rebasen, um sie linear zu halten. Auf diese Weise können potenzielle Fehler im Voraus erkannt und korrigiert werden, um häufige Revert-Commits zu vermeiden, die auf mangelnde Sorgfalt hinweisen und für alle Beteiligten ärgerlich sein können. Allerdings ist es wichtig, darauf zu achten, dass die Testphase nicht zu lange dauert, um den Fortschritt nicht zu verzögern und keine wertvolle Zeit für andere Aufgaben zu verschwenden. Eine angemessene Testphase ist jedoch notwendig, um sicherzustellen, dass das Endprodukt den Anforderungen erster öffentlicher Tests entspricht.
Während der Arbeit an einer Aufgabe können auch unerwartete Fehler oder Optimierungsmöglichkeiten erkannt werden, die nicht direkt mit der aktuellen Aufgabe zusammenhängen. In solchen Fällen ist es sinnvoll, die Fehler zu korrigieren oder die Optimierungen vorzunehmen, solange sie den aktuellen Stand nicht negativ beeinflussen. Es ist jedoch wichtig, darauf zu achten, dass diese Änderungen in einer separaten Commit-Serie festgehalten werden, um sie später leichter nachvollziehen und verwalten zu können.
Script zum Erstellen einer ChangeLog
Wenn man die Punkte von oben beachtet kann man mit diesem kleinen Script relativ schnell eine ChangLog Datei erstellen. Das Script ist recht rudimentär und ist sicherlich ausbaufähig und z.B. nur den ChangeLog zwischen zwei Commits oder Tags zu produzieren.
#!/bin/sh
# changelog.sh
# Convert git log to GNU-style ChangeLog file.
# (C) Chris
if test -d ".git"; then
git log --date-order --date=short | \
sed -e '/^commit.*$/d' | \
awk '/^Author/ {sub(/\\$/,""); getline t; print $0 t; next}; 1' | \
sed -e 's/^Author: //g' | \
sed -e 's/>Date: \([0-9]*-[0-9]*-[0-9]*\)/>\t\1/g' | \
# sed -e ‘s/\(.*\)>Date: \([0-9]*-[0-9]*-[0-9]*\)/\2 \1>/g’ | \
sed -e 's/^\(.*\) \(\)\t\(.*\)/\3 \1 \2/g' > ChangeLog
exit 0
else
echo "No git repository present."
exit 1
fi
Das ergibt dann einen solchen Output:
8< --- Carsten Schoenert <c.schoenert_at_t-online_dot_de> 2011-07-10 openvpn: fixing wrong position of patch call in the target ups, a poor copy paste error :-( And one forgotten warning! You should't use your STB as a VPN Gateway from/to the Internet! Every process on the box is running the root previleges, so if someone has taken your box he will full access to your local lan! Stefan Seyfried <seife_at_tuxbox-git_dot_slipkontur_dot_de> 2011-07-09 improve nfsd init script to check exports syntax Stefan Seyfried <seife_at_tuxbox-git_dot_slipkontur_dot_de> 2011-07-09 glibc-pkg: add libnsl to package (needed by samba) Carsten Schoenert <c.schoenert_at_t-online_dot_de> 2011-07-10 openvpn: new target for *the* open source VPN software In the between times some people from the dark side there some quicker than I and make a usable make target for openvpn. I made some little modification for using it in my buildsystem. I added also the opkg build to the target. The opkg package may be usable, i did not tested it realy! The start/stop functionality is yet completely not implemented! So if you have some ideas for the correct implementation feel free to build it. So there is to copy the client.conf.example to /etc/openvpn, or even testing if there is some config, the loaded kernelmodul and so on. Remind: !!! You need the tun.ko kernelmodul to get proper working openvpn !!! Stefan Seyfried <seife_at_tuxbox-git_dot_slipkontur_dot_de> 2011-07-03 add debian-on-coolstream documentation --->8
Code Changes/Source code Repositories
Aktuelle Änderungen lassen sich in den jeweiligen Mailinglisten verfolgen oder in den Logs der jeweiligen Repositories (siehe Listen).
Buildsysteme
Erstellung von USB- u. Flash-Images, OPKG-Paketierung für diverse Platformen
Nur Coolstream Flash-Image
- www.git.wittinobi.de (privat!)
Neutrino-HD/MP
aktive Sub-Projekte
private Developer Sub-Projekte
Libs
Multiplatform
Coolstream
Driver
Coolstream
Tuxbox-SD
Dokumentation
Die Dokumentation, die vor allem dem Benutzer die Funktionsweise der Betriebssoftware vermitteln soll, findet sinnvollerweise im TuxBoxWIKI statt.
Jeder Entwickler ist daher angehalten, entsprechende Änderungen, Ergänzungen usw. zeitnah zu den eingetragenen Änderungen zu dokumentieren, oder zumindest einem TuxBoxWIKI-Autor oder Sysop mitzuteilen, damit diese den Weg auch zum Benutzer findet und keine Lücken entstehen!.
Die Quellcode-Dokumentation sollte direkt im Sourcecode-erfolgen. Dies ist in der Vergangenheit leider nicht immer in dem Maße erfolgt, wie man es gerne gehabt hätte, so dass es hier leider nicht immer so einfach ist, möglichst schnell einzusteigen. Einen wesentlichen Schritt zur Verbesserung im dBox2-Bereich trug die Einführung von Newmake bei, wodurch zumindest der Aufbau einer Entwicklungsumgebung besser gelingen sollte. Im Coolstream-Bereich wurde zumindest im Bereich der Buildsysteme gute Arbeit geleistet. Im Bereich Neutrino-HD gibt es Nachholbedarf.
GIT Zugang
Bei den Git-Repositories sind Anfragen zu Schreibzugängen nicht zwingend notwendig, da man dort dank der dezentralen Struktur von Git, üblicherweise formatierte Patche erzeugt oder in bestimmten Fällen Pull-Requests macht, welche man direkt dem Maintainer der jeweiligen Repos oder einem Entwickler per EMail zukommen lassen kann. Bei Gitorious gibt es diese Funktion direkt auf der Web-Oberfläche bzw. kann seine Änderungen direkt per E-Mail dorthin verschicken! Nähere Informationen, wie man solche Patch-E-Mails erstellt findest Du hier. Aus diesem Grund ist es unter anderem üblich, dass sich jeder Entwickler mit gültige EMail-Adresse und realen Namen in seinen Commits zu erkennen gibt. Fake-Adressen oder Aliaseinträge sind eher schlechter Stil [2]'
Coolstream-GIT
GIT-Buildsysteme:
GIT-Novatux
Patch einreichen
Wer einen Patch zur Verfügung stellen möchte, kann dies natürlich gerne tun. Hierfür kannst du die Anhangsfunktion in den Boards, Mailinglisten oder Upload-Server nutzen. Da als Revisionscontrollsystem nun durchgängig auf Git gesetzt wird ist es ebenfalls möglich und erwünscht bei größeren Patchserien einen Pullrequest in einer der Mailinglisten oder auch im den Boards kund zu tun (unter Angabe des Remote Repository natürlich).
Die Benamung der Patches erfolgt beim Git eigenen Kommando automatisch, ebenso ergibt sich dadurch auch eine Reihenfolge in der die Patche später gegebenenfalls wieder applied werden müssen.
Einige IDE's oder auch SCM-UI's bieten die Möglichkeit an, passende Namen erzeugen zu lassen. Man kann sich auch eigene Scripte dafür anfertigen, die dies übernehmen. Dies bitte aber nur im Ausnahmefall.
Aktuell werden vorwiegend für die Multiplattform als auch für das bisherige Tuxbox-cvs auf Basis von GIT Patche erzeugt und angewendet.
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. Anders als CVS oder auch SVN unterscheidet Git zwischen Committer und Autor des Patches. Dies hat unter Anderem auch 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.
Da mit Git formatierte Patche in der Regel auf lokale Commits des Autors basieren, werden auch die darin bereits vorhandenen Commit Messages übernommen. Sofern diese auch den Patch erklären, ist es für den Entwickler, der den Patch erhält auch schneller nachvollziebar, worum es bei diesem oder jenem Patch geht und braucht sich nicht selbst um die Commit Message zu kümmern. Andererseits kann der Autor vor der Überführung in das Remote-Repo und auch Dank der vorhandenen Autordaten im Repo später um Nachbesserung gebeten werden.
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"
Es ist übrigens unangemessen ungültige, falsche, keine oder gar sinnlose Angaben zu machen und zeugt gegenüber anderen Entwicklern und Contributoren eher von schlechtem Stil und ist deshalb nicht gern gesehen!
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
Um seine Änderungen als Patch weitergeben zu können, müssen die Quellcodeveränderungen zunächst committet werden. Das klingt vorallem für eingefleischte "CVS nach Git-Umsteiger" etwas verwirrend, da man von zentralen Versionskontrollsystemen wie CVS oder SVN in diesem Kontext an evtl. benötigte Schreibrechte für einen Remoteserver denkt und eben nur dahin Commits üblich sind, die eigentlich nur die Entwickler eines Projektes vornehmen. Git arbeitet aber dezentral und alles wird lokal behandelt, da jeder quasi ein vollständiges Repo mit Historie etc. lokal zur Verfügung hat. Commits sind aber die Grundlage im Ablauf der Entwicklungstätigkeit. Patche, die herkömmlich ohne Commits erzeugt werden (git diff), sind auch möglich sind aber mehr als ein Mittel für Schnelltests zu verstehen und erforden nachträgliche Behandlung.
In diversen Communities kann man bei einigen hilfswilligen Usern leider immer wieder feststellen, dass diese Paradigmen recht fest sitzen und sich erkennen lässt, dass man statt auf Git-Werkzeuge zu setzen, alte Vorgehensweisen weiterhin pflegt und z.B. nur komplette Repos immer wieder neu klont und seine Änderungen unsinnigerweise auf vollständige Klone mit Unix-Werkzeugen diff und patch verarbeitet und seine Ergebnisse dann den Entwicklern mitteilt. Das ist unter Umständen sehr umständlich und nicht zuletzt auch für die Entwickler unpraktisch. Es sei daher jedem Umsteiger angeraten, sich Sachen wie Commit, Branch, Stash, pull, Rebase, Merge im Zuammenhang mit Git zu Gemüte zu führen. Wer dafür nicht gewillt ist, kann die nächsten Zeilen getrost überpringen, wird sich aber langfristig auch keinen Gefallen damit tun. Dies ist auch eine Frage des Teamworks innerhalb des Projektes und die unter Git üblichen Vorgehensweisen wird man sehr schnell schätzen lernen.
Commit erzeugen
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 selektiv 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 diesem Befehl zu einem Patch ausgegeben werden.
git format-patch -s [BRANCH]
Der Parameter -s
bewirkt ein SignOff im Patch, also eine Art Unterschrift das Du/Ihr den Patch auch geprüft habt. Dies hilft Irritationen zu vermeiden wenn es mal Diskussionen über einen Patch gibt und wer nun eigentlich den Patch auf sachlich richtig geprüft hat. Es gibt noch weitere Arten einen Patch zu kommentieren, sehr bekannt und üblich sind die Flags "Acked-by:", "Tested-by:" und "Reviewed-by:". Für diese Flags gibt es aber keinen Switch innerhalb git format-patch
. Diese müssen manuell oder per Alias eingefügt werden.
Wenn man z.B. aus seinen lokalen Änderungen genau die letzten Commits der Reihen nach als Patch ausgeben möchte, reicht auch dieser Befehl:
git format-patch -s [BRANCH]~6
~6 bewirkt, das genau die letzten 6 Commits der Reihe nach ausgegeben werden.
Möchte man später trotzdem mehrere Commits zu einem oder weniger Commits zusammenfassen, kann man das über git rebase -i nachholen.
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 ausgegeben 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 -s tuxbox-hd/tuxbox-port
Ergebnis:
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 -s -M -C ac7abd8db402724f9c195b2091c7a92997edce6e~1...ac7abd8db402724f9c195b2091c7a92997edce6e
Heraus kommt ein nummerierter Patch:
0001-target-ntp-add-target-for-ntp.patch
- 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 -s -M -C ac7abd8~1...ac7abd8
Ergebnis:
0001-target-ntp-add-target-for-ntp.patch
Patch aus mehreren Commits erstellen
Angenommen man arbeitet lokal an einer Sache, die man üblicherweise in mehreren Commits und in einem separaten Branch abgearbeitet hat und möchte genau diese Commits nun als Patche weitergeben, kann man diese nun als Folge von Einzelpatches erzeugen. Befindet man sich also in einem lokalen Branch und dieser beinhaltet 2 Commits, und möchte genau diese letzten beiden Commits als Patche haben, würde man das etwa so machen:
$ git format-patch [BRANCH]~2
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. Damit fügt Ihr dem Patch ein Signed-by: <Euer Name> hinzu.
user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git format-patch tuxbox-hd/tuxbox-port --signoff
Ergebnis:
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. 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
Die Anwendung eines solchen Patches ist also 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.
Wenn man auf diese Weise einen unformatierten Patch erhält, hat man als Entwickler leider nun den Aufwand nachträglich einige Daten für einen Commit zu ermitteln, um letztlich einen Commit in das Remoterepo durchzuführen zu können. Nach dem der Patch mit git apply angewendet wurde, muss man die Änderungen also nun selbst samt fehlender Angaben erst lokal committen:
$ git commit -a --author="MrX <MrX@mrxathome.de>" --message="This is my opinion what this patch is doing, but MrX should known it better"
git am
Im Unterschied zu git apply werden mit git am angewendete Patche wie Commits behandelt. Hat man also einen mit git format-patch formatierten Patch erhalten und angewendet, hat man diesen Patch bereits committet und relevante Daten wie z.B. Autor-Informationen, Commit Message in seine lokale Historie übernommen. Git am ist daher gegenüber der git apply Methode vorzuziehen, da hier der Aufwand für den Entwickler minimiert ist und auch die Leistungen von Contributoren eines Projektes gewürdigt werden. Die Chancen für eine Übernahme in das Projektrepo könnten je nach Umfang der Änderungen und gerade wegen des geringeren Aufwands auch steigen.
Ursprünglich ist git am dazu gedacht, Patches direkt aus E-Mails (am steht für ApplyMailbox) zu übernehmen, jedoch werden auch Dateien direkt übernommen. Befinden sich der oder die Patches 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
Git wird die Patches in der richtigen Reihenfolge anwenden sofern die Patches mit einer Nummerierung beginnen wie diese z.B. mit git format-patch automatisch erstellt werden.
Mailinglisten
Öffentlich
- Tuxbox Global, allgemeine Mailingliste
- Tuxbox Commits, nur um Commit-Messages zu empfangen
- Tuxbox Commit-Archive
Intern
- Neutrino-HD für Multiplatform und Buildsystem
- Neutrino-HD Novatux, einschließlich Sendung von Commit-EMails