Source code management/de

Einleitung

Das Hauptwerkzeug zur Quellcodeverwaltung für das FreeCAD-Projekt ist Git, das in den meisten Betriebssystemen einfach über einen Paketmanager oder direkt von der Website von Git installiert werden kann. Es wird empfohlen, sich mit Git vertraut zu machen, bevor man direkt mit dem FreeCAD-Quellcode arbeitet. Auf der Seite Git documentation findet man das Referenzhandbuch sowie das Pro Git book (beide engl.), um zu lernen, wie das System im Allgemeinen genutzt wird. Das vorliegende Dokument konzentriert sich auf die Verwendung von Git für die FreeCAD-Entwicklung. Die Zusammenstellung von FreeCAD ist unter Kompilieren beschrieben.

Während Git in erster Linie eine Terminal-Anwendung ist, gibt es viele grafische Anwendungen, die die Arbeit mit Branches (Zweigen), das Anwenden von Patches und das Senden von Pull-Requests an einen Main-Branch (Hauptzweig) erleichtern. Beispiele dafür sind git-gui (hilft beim Staging und bei Commits, kann gitk starten), gitk (zeigt die Commmit-Historie an, die erste grafische Benutzeroberfläche, die entwickelt wurde),gitg (Gnome),qgit (Qt), tig (Ncurses), git-cola und GitKraken (proprietär). Eine kurze Einführung in dieses Werkzeug findet man unter Entwicklung von FreeCAD mit GitKraken.

Hinweis: Wenn einem davon schwindelig wird, gibt es eine sehr gute nicht-technische Serie über die Verwendung von Git und Github mit dem Titel 'Git und Github für Dichter'.

Quellcodezugang

Jeder kann auf den FreeCAD-Quellcode zugreifen und eine Kopie davon bekommen, aber nur die FreeCAD-Projektmanager haben Schreibzugriff darauf. Man kann eine Kopie des Codes erhalten, ihn studieren und nach Belieben ändern, aber wenn man möchte, dass die Änderungen in den offiziellen Quellcode aufgenommen werden, musst man einen „Pull-Request“ gegen das Main-Repository durchführen, damit die Änderungen von den Verwaltern überprüft werden können. Diese Art der Entwicklung ist bekannt als der Dictator and Lieutenants Workflow (engl. wörtlich etwa „Diktator und Leutnants-Arbeitsablauf“), da die Kern-Entwickler (Diktatoren) und betrauten Entwickler (Leutnante) den Code filtern, der von unabhängigen Entwicklern und Benutzern eingereicht wird.

Wenn die Quellcode-Änderungen signifikant sind, empfehlen wir, sie im Pull-Request-Abschnitt des FreeCAD-Forums zu erklären.

Typischer Arbeitsablauf zur Entwicklung von Code für FreeCAD; jeder kann den Code aus dem Haupt-Repository beziehen, aber die Hauptentwickler haben das exklusive Recht, Eingaben anderer Entwickler zu überprüfen und zusammenzuführen.

Offizielles GitHub-Repository

Der FreeCAD-Quellcode wird in Github bereitgestellt, https://github.com/FreeCAD/FreeCAD

Um Code beitragen zu können, wird ein GitHub-Konto benötigt.

In der Vergangenheit wurde der Quellcode in einem SVN-Repository bereitgestellt, https://free-cad.svn.sourceforge.net/svnroot/free-cad. Dieses wurde am 10. Oktober 2011 mit commit 120ca87015 nach GitHub verschoben.

Daher gibt es viele Änderungen, die vor dieser Zeit vorgenommen wurden, die nicht in der modernen Git-Commit-Geschichte aufgezeichnet sind. Mehr dazu kann man auf der Seite Geschichte nachlesen.

Git-Benutzernamen festlegen

Entwickler sollten Code in ihr persönliches Repository mit ihrem GitHub-Benutzernamen eintragen. Wenn dieser nicht bereits global gesetzt ist, kann er lokal für das aktuelle Git-Repository wie folgt gesetzt werden:

git config user.name "YOUR_NAME"
git config user.email GITHUB_USERNAME@users.noreply.github.com

Wobei „YOUR_NAME“ den vollständigen Namen oder Spitznamen darstellt, der zur Identifizierung des Autors eines bestimmten Beitrags verwendet wird, und GITHUB_USERNAME den Namen des Accounts auf GitHub angibt.

Remote Repositories

Man lese Was ist der Unterschied zwischen Origin und Upstream auf GitHub? (Stackoverflow), um den Unterschied zwischen origin und upstream im Zusammenhang mit Git zu verstehen. In diesem Abschnitt wird erklärt, wie die richtigen Repositorys für die Entwicklung eingerichtet werden. Im Wesentlichen:

Diese Unterscheidung ist wichtig, da man den Code zunächst in der eigenen Kopie des Repositorys schreiben sollte, bevor man diese Änderungen in das offizielle Repository überträgt.

Basierend auf den obigen Ausführungen gibt es zwei Möglichkeiten, die Git-Entwicklungsumgebung einzurichten:

Wir empfehlen die erste Methode, weil sie einen Schritt schneller ist.

Erste Methode: Auf GitHub forken und den eigenen Fork lokal klonen

Zuerst wird das FreeCAD-Repository in GitHub geforkt, dann klont man diesen persönlichen Fork auf dem Computer und legt schließlich das upstream-Repository fest.

  • Beim GitHub-Konto Anmelden.
  • Zum offiziellen FreeCAD-Repository gehen: https://github.com/FreeCAD/FreeCAD
  • Oben rechts auf der Seite auf die Schaltfläche „Fork“ klicken. Dadurch wird eine persönliche Kopie des FreeCAD-Repositorys unter dem GitHub-Benutzernamen erstellt: https://github.com/GITHUB_USERNAME/FreeCAD
  • Auf dem Rechner den neu erstellten FreeCAD-Fork klonen. Er wird in einem Verzeichnis freecad-source erstellt.
git clone https://github.com/GITHUB_USERNAME/FreeCAD.git freecad-source
  • Sobald der Download abgeschlossen ist, gibt man das neue Quellverzeichnis ein und legt das upstream-Repository fest.
cd  freecad-source
git remote add upstream https://github.com/FreeCAD/FreeCAD.git
  • Das Remote-Repository mit git remote -v überprüfen; die Ausgabe sollte in etwa so aussehen
origin	https://github.com/GITHUB_USERNAME/FreeCAD.git (fetch)
origin	https://github.com/GITHUB_USERNAME/FreeCAD.git (push)
upstream	https://github.com/FreeCAD/FreeCAD.git (fetch)
upstream	https://github.com/FreeCAD/FreeCAD.git (push)
  • Jetzt kann die Entwicklung beginnen.

Zweite Methode: FreeCAD direkt auf den lokalen Rechner klonen

Zuerst wird das FreeCAD-Repository in GitHub geforkt, jedoch wird das ursprüngliche FreeCAD-Repository auf den lokalen Rechner geklont und dann die Remotes über das Terminal geändert.

  • Beim GitHub-Konto anmelden.
  • Zum offiziellen FreeCAD-Repository gehen: https://github.com/FreeCAD/FreeCAD
  • Oben rechts auf der Seite auf die Schaltfläche „Fork“ klicken. Dadurch wird eine persönliche Kopie des FreeCAD-Repositorys unter dem GitHub-Benutzernamen erstellt: https://github.com/GITHUB_USERNAME/FreeCAD
  • Das ursprüngliche FreeCAD-Repository klonen. Es wird in einem Verzeichnis freecad-source erstellt.
git clone https://github.com/FreeCAD/FreeCAD.git freecad-source
  • Sobald der Download abgeschlossen ist, wird das neue Quellverzeichnis aufgerufen und das Repository origin festgelegt.
cd freecad-source
git remote add origin https://github.com/GITHUB_USERNAME/FreeCAD.git
  • Dann wird das upstream-Repository eingerichtet.
git remote add upstream https://github.com/FreeCAD/FreeCAD.git
  • Das Remote-Repository mit git remote -v bestätigen; die Ausgabe sollte ähnlich wie diese sein
origin	https://github.com/GITHUB_USERNAME/FreeCAD.git (fetch)
origin	https://github.com/GITHUB_USERNAME/FreeCAD.git (push)
upstream	https://github.com/FreeCAD/FreeCAD.git (fetch)
upstream	https://github.com/FreeCAD/FreeCAD.git (push)
  • Jetzt kann die Entwicklung beginnen.

Wenn das Remote-Repository aus irgendeinem Grund zwar existiert, aber auf die falsche Adresse verweist, kann die Situation durch Umbenennen des Namens des Remote-Repository behoben werden. Beispielsweise sollte origin auf den persönlichen Fork zeigen; wenn er auf das ursprüngliche FreeCAD-Repository zeigt, wird der Name dieses Remote-Repository in upstream geändert und das origin-Repository manuell hinzugefügt.

git remote rename origin upstream
git remote add origin https://github.com/GITHUB_USERNAME/FreeCAD.git
git remote -v

Es können auch weitere Informationen mit dem Schlüsselwort show angezeigt werden.

git remote show origin
git remote show upstream

Git-Entwicklungsprozess

Niemals auf dem eigenen lokalen Main-Branch entwickeln. Stattdessen wird ein lokaler Branch für die Entwicklung erstellt, und dieser lokalen Branch dann über einen Pull-Request mit dem vorgeschalteten Main-Branch zusammengeführt. Hierzu liest man Git-Branchse, Grundlegendes Branching und Merging und GitHub - An einem Projekt mitwirken, um mehr zu erfahren.

Generischer Arbeitsablauf zur Entwicklung von Code für FreeCAD unter Verwendung von git; das Main-Repository wird online geforked und auf einen Offline-Computer geklont (0); neue Branches (1) werden verwendet, um lokale Änderungen und Ergänzungen des Codes zu übergeben (2); die Forks werden auf den neuesten Online-Code zurückgeführt (3), und dann zum Remote-Repository verschoben (pushed) (4); dann wird ein Pull-Request erstellt, um den Code in das Main-Repository einzufügen (5). Dann wird der persönliche Klon mit dem neuen Main-Code aktualisiert (a); dieser aktualisierte Main-Code wird ebenfalls an das Remote-Repository (b) geschickt, um denselben Code sowohl online als auch offline zu haben.

Branching (Verzweigen)

Anstatt an der Main-Version des Codes zu arbeiten, empfiehlt die bewährte Methode mit Git die Erstellung eines neuen Branches, wann immer man an einer neuen Funktion arbeiten möchte. Branches sind kostengünstig, sie kopieren nicht den gesamten Quellcode-Baum, sondern erzeugen lediglich einen Zeitpunkt, an dem Code geschrieben wird; daher helfen Branches dabei, die laufende Arbeit vom Hauptcode getrennt zu halten.

Die Verwendung eines neuen Branchs erfolgt in zwei Schritten: Zuerst wird der Branch erstellt, und dann wird zu ihm gewechselt:

git branch myNewBranch
git checkout myNewBranch

Alternativ können beide Schritte mit einer einzigen Anweisung ausgeführt werden:

git checkout -b myNewBranch

Jetzt können die Branches mit checkout geändert werden, wann immer daran gearbeitet werden muss. Um die Branches in dem Projekt und dem aktuellen Branch zu sehen, wird die Operation branch allein verwendet oder -v oder -vv für weitere Informationen hinzugefügt:

git branch
git branch -vv

Nachdem Änderungen vorgenommen wurden und diese Änderungen übertragen wurden, wird die Operation log mit den folgenden Optionen verwendet, um die Branches zu visualisieren

git log --oneline --decorate --graph --all

Committing (Übergeben)

Sobald man sich in einem neuen Branch befindet, bearbeitet man die gewünschten Quelldateien mit einem Texteditor. Um zu sehen, welche Dateien geändert wurden, verwendet man die Operationen status und diff; wenn man mit den Änderungen zufrieden ist, wird die Änderungen mit der Operation commit gespeichert:

git status
git diff
git commit -a

Anders als bei SVN muss man ausdrücklich angeben, welche Dateien übergeben werden; mit der Option -a werden alle geänderten Dateien gespeichert. Der voreingestellte Texteditor, z. B. nano oder vim, wird zum Verfassen einer commit-Nachricht geöffnet.

Alternativ fügt man die Mitteilung dem commit hinzu:

git commit -a -m "Fix the bug in the clone function."

Werden neue Dateien oder Verzeichnisse erstellt, muss zuerst die Aktion add ausgeführt werden, die sie zum lokalen Repository hinzufügt, bevor die Änderungen übergeben werden.

git add path
git commit -a

Wobei path eine beliebige Datei oder ein beliebiges Verzeichnis sein kann.

Gute Commit-Nachrichten schreiben

Man sollte versuchen, in kleinen Schritten zu arbeiten, d. h. häufig Commits durchzuführen, nachdem man eine kleine Ergänzung in dem Code vorgenommen hat. Wenn man die Änderungen nicht in einem Satz zusammenfassen kann, ist es wahrscheinlich schon zu lange her, dass man einen Commit durchgeführt hat.

Bei größeren Änderungen ist es wichtig, dass man hilfreiche und nützliche Beschreibungen der Arbeit bereitstellt. FreeCAD hat ein Format übernommen, das im Buch Pro Git erwähnt wird und aus einer kurzen Nachricht und einem längeren beschreibenden Absatz besteht.

Kurze Zusammenfassung der Änderungen (maximal 50 Zeichen)
 
 Falls erforderlich, fügt man einen ausführlicheren Erläuterungstext
 hinzu. Man beschränkt sich dabei auf etwa 72 Zeichen. In manchen
 Kontexten wird die erste Zeile als Betreff einer E-Mail und der Rest
 des Textes als Hauptteil behandelt. Die Leerzeile zwischen der
 Zusammenfassung und dem Hauptteil ist entscheidend (es sei denn,
 man lässt den Hauptteil ganz weg); Werkzeuge wie rebase können
 verwirrt werden, wenn man beides zusammen ausführt.
 
 Weitere Absätze folgen nach Leerzeilen. 
 
  - Aufzählungspunkte sind auch in Ordnung.
 
  - Typischerweise wird für den Aufzählungspunkt ein Bindestrich oder
    Sternchen verwendet, dem ein einzelnes Leerzeichen vorangestellt
    ist, mit Leerzeilen dazwischen, aber die Konventionen variieren hier.

Wenn in einem Branch viele verwandte Arbeiten ausgeführt werden, sollten viele kleine Commits vorgenommen werden (siehe einen Beitrag im Forum). Wenn diese Änderungen in den Main-Branch eingefügt werden sollen, sollten folgende Befehle ausgeführt werden:

git log main..myNewBranch

um die einzelnen Commit-Nachrichten zu sehen. Es kann eine Nachricht von hoher Qualität geschrieben werden, wenn ein Merge durchgeführt wird.

Wenn mit dem Hauptzweig zusammengeführt wird, wird die Option --squash verwendet und ein Commit mit der Qualitäts-Commit-Meldung durchgeführt. So kann sehr großzügig mit den Commits umgegangen werden und die Commit-Nachricht detailliert gestaltet werden, ohne zu viele unterschiedliche Beschreibungen zu verwenden.

Commits zusammenführen

Squashing bezeichnet den Vorgang, bei dem mehrere aufeinanderfolgende Commits zu einem einzigen zusammengefasst werden. Dies kann sinnvoll sein, wenn man viele kleine Commits vorgenommen hat, die man als einen einzigen Commit präsentieren möchte, beispielsweise wenn man eine einzelne Variable geändert, Rechtschreibfehler korrigiert und die Abstände im Code angepasst hat. Man sollte nur kleine Commits zu einer einzigen Datei zusammenfassen; größere Änderungen am Code, die sich über mehrere Dateien erstrecken, sollten die vollständige Commit-Historie enthalten.

Mit git log --oneline können viele Commits nacheinander angezeigt werden, wobei der neueste Commit ganz oben steht. In diesem Beispiel werden ausgehend von „Feature A“ viele Commits vorgenommen, um „Feature B“ zu implementieren. Wir möchten alle Commits, die zu „Feature B“ gehören, zu einem einzigen zusammenfassen.

871adb OK, feature B is fully implemented
1c3317 Whoops, it is not ready yet...
87871a I'm almost ready!
643d0e Code cleanup
af2581 Fix this and that
4e9baa Good implementation
d94e78 Prepare the module for feature B
6394da Feature A

Den Befehl rebase wird mit der Option --interactive oder -i verwendet, um verschiedene Commits auszuwählen und zusammenzufassen. Den Hash des Commits unmittelbar vor dem ersten verwenden, den man zusammenfassen möchte, in diesem Fall den, der „Feature A” entspricht.

git rebase -i 6394da

(Tipp: Wenn man weiß, wie viele Commits bearbeiten werden sollen, kann man git rebase -i HEAD~n verwenden, um die letzten n Commits zu bearbeiten.)

Der Befehlszeilen-Editor, wie nano oder vim, wird geöffnet und zeigt erneut die Commits an, wobei nun der ältere Commit oben steht. Vor jedem Commit wird das Wort pick angezeigt. Das Wort pick löschen und stattdessen das Wort squash oder nur den Buchstaben s schreiben, mit Ausnahme des ersten Eintrags; dieser Commit ist der älteste, sodass alle zukünftigen Commits darin zusammengefasst werden.

pick d94e78 Prepare the module for feature B
s 4e9baa Good implementation
s af2581 Fix this and that
s 643d0e Code cleanup
s 87871a I'm almost ready!
s 1c3317 Whoops, it is not ready yet...
s 871adb OK, feature B is fully implemented

Die Datei speichern und den Editor schließen.

Der Editor wird erneut geöffnet. Jetzt kann man eine längere Nachricht hinzufügen, die alle Änderungen so beschreibt, als wären sie ein einziger Commit. Die Datei speichern und den Editor erneut schließen. Damit sind diese Commits zu einem einzigen Commit mit der verfassten neuen Commit-Nachricht zusammengefasst.

git log --oneline kann erneut verwendet werden, um den neuen Commit-Verlauf anzuzeigen. In diesem Fall wird nur ein einziger Commit für „Feature B“ angezeigt, und zwar über dem unveränderten Commit für „Feature A“.

c83d67 OK, feature B is fully implemented now, with proper module setup, and clean code.
6394da Feature A

Wenn man für FreeCAD programmiert, bitten wir darum, jede Commit-Meldung mit dem Modul zu beginnen, das davon betroffen ist. Eine Commit-Meldung für eine Änderung am Sketcher könnte beispielsweise lauten:

Sketcher: gerade Linien etwas krümmen

Gerade Linien sind irgendwie hässlich, daher fügt dieser Commit ihnen ein wenig Krümmung hinzu, damit sie optisch ansprechender sind. Sie funkeln auch ein wenig und ändern mit der Zeit ihre Farbe.

Behebt Fehler #1234.

Der Pull Request lässt sich leichter überprüfen und schneller zusammenführen, wenn man darauf achtet, die Commits vor dem Einreichen mit Rebase zu strukturieren und zu beschreiben.

Die Arbeit in das GitHub-Repository übertragen

Die lokalen Branches auf dem Computer werden nicht automatisch mit den Remote-Servern synchronisiert, die man als origin oder upstream angegeben hat (siehe Remote-Repositorys); Man muss die Branches explizit auf die Remote-Server übertragen, für die man Schreibzugriff haben muss. Sobald man dies getan hat, werden die Branches öffentlich und können von anderen Entwicklern überprüft werden.

Für FreeCAD sollte man den lokalen Zweig in das Remote-Repository origin übertragen, d. h. https://github.com/GITHUB_USERNAME/FreeCAD. Man muss bei jedem Push den Benutzernamen und das Passwort eingeben, es sei denn, man hat Credential Caching eingerichtet. Weitere Informationen sind unter Commits an ein Remote-Repository übertragen zu finden.

git push origin myNewBranch

Wenn man mit einem einzelnen Branch arbeitet, muss man möglicherweise mehrmals interaktiv Rebase, Squash und Fix Commits durchführen. In diesem Fall ist der Branch-Verlauf nicht einfach und man kann ihn nicht in das Remote-Repository pushen. Möglicherweise erhält man eine Meldung wie die folgende, die besagt, dass ein „Fast-Forward”-Push nicht möglich ist.

error: failed to push some refs to 'https://github.com/USER/FreeCAD.git'
hint: Updates were rejected because a pushed branch tip is behind its remote
hint: counterpart. Check out this branch and integrate the remote changes
hint: (e.g. 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Um den Branch endgültig in das Remote-Repository zu übertragen, muss man einen „Force Push“ durchführen. Dadurch wird der Remote-Branch vollständig mit dem aktuellen Branch überschrieben, den man offline hat.

git push -f origin myNewBranch

Der reguläre Entwickler hat keinen Schreibzugriff auf das upstream-Repository https://github.com/FreeCAD/FreeCAD, daher sollte man niemals Code auf diesen Remote-Server übertragen.

Rebasing aus dem Upstream

Während man am eigenen Branch arbeitet, entwickelt sich der offizielle FreeCAD-Code durch Commits anderer Entwickler weiter und weicht somit zunehmend von dem Code ab, den man in seinem persönlichen Fork hat.

      .-----A origin/myNewBranch
     / 
-----o-----------Z FreeCAD upstream/main

Wenn man bereit ist, den Branch mit dem Haupt-Repository von FreeCAD zusammenzuführen, muss man daher die eigene Kopie des Repositorys „rebasen”, damit sie so nah wie möglich am offiziellen Repository ist. Weitere Informationen sind unter Git Branching – Rebasing zu finden.

git checkout myNewBranch
git pull --rebase upstream main

Dadurch wird der Code aus dem main-Branch des upstream-Repositorys (der offiziellen FreeCAD-Quelle) heruntergeladen und mit dem aktuellen Branch (myNewBranch) zusammengeführt, sodass die Änderungen über dem neuesten offiziellen Code erscheinen. Wenn niemand dieselben Dateien wie man selbst geändert hat, wird die Zusammenführung ohne Probleme gelingen. Wenn einige Dateien gleichzeitig von verschiedenen Personen geändert wurden, kann es zu einem Konflikt kommen, der gelöst werden muss.

                  .-----A' origin/myNewBranch
                 /
-----o-----------Z FreeCAD upstream/main

Zusammenfassend lässt sich sagen, dass man sich im entsprechenden Branch befindet, den Upstream-Code rebasen und dann mit dem Push fortfahren muss.

git checkout myNewBranch
git pull --rebase upstream main
git push origin myNewBranch

Der Befehl pull entspricht einem Befehl fetch, gefolgt von einem Befehl merge. Wenn die Option --rebase verwendet wird, wird anstelle eines einfachen Befehls merge der Befehl rebase ausgeführt.

git pull upstream

git fetch upstream
git merge FETCH_HEAD
git pull --rebase upstream main

git fetch upstream
git rebase main

Zusammenführen des Branch (Pull-Request)

Nachdem die Änderungen lokal committet, den Branch aus dem Upstream-Repository rebased und den Branch online gepusht wurden, kann man einen „Pull Request“ initiieren. Ein Pull Request teilt den Administratoren des offiziellen FreeCAD-Repositorys mit, dass man den neuen Code in dem Branch mit dem offiziellen Code zusammenführen möchte.

Zusammenfassend sieht der Entwicklungsprozess wie folgt aus:

  1. FreeCAD forken und eine lokale Kopie dieses Forks erstellen.
  2. Einen Branch auf dem Fork erstellen und zu diesem Branch wechseln.
  3. Programmieren! So viel oder so wenig comitten wie man möchte und gute Commit-Meldungen schreiben, um den Überblick über die Arbeit zu behalten.
  4. Wenn man mit der Arbeit zufrieden ist, verwendet man git rebase -i HEAD~n (wobei n die Gesamtzahl der Commits ist), um die Commits zu einer logischen Gruppe mit guten Commit-Meldungen zusammenzufassen (jede Meldung sollte mit dem Namen des Moduls beginnen, auf das sie sich bezieht, z. B. „Sketcher: gerade Linien etwas krümmen“).
  5. GitHub verwenden, um den Code wie unten beschrieben als „Pull Request (PR)” einzureichen.

Sobald man den Code in das origin-Repository https://github.com/GITHUB_USERNAME/FreeCAD übertragen hat, bietet einem GitHub die Möglichkeit, einen Vergleich durchzuführen und einen Pull-Request für das upstream-Repository zu erstellen. Durch Klicken auf Compare & pull request öffnet sich eine Oberfläche, in der man auswählen kann, welches Repository die „Basis” und das Ziel der Zusammenführung ist und welches der „Head” mit dem zusätzlichen Code ist. Das System führt eine schnelle Überprüfung durch und teilt mit, ob es Konflikte mit den von einem geänderten Dateien gibt. Wenn man an Dateien gearbeitet hat, die niemand anderes geändert hat, kann der Branch problemlos zusammengeführt werden.

GitHub zeigt einen Texteditor an, in dem man eine Nachricht mit einer Dokumentation der Änderungen verfassen kann: Dieser Editor ist bereits mit einer Willkommensnachricht (die man löschen kann), einer Checkliste (die man durchgehen sollte) und einer Erinnerung versehen, die Änderung im Wiki zu dokumentieren, sobald sie akzeptiert wurde. Um die Checkliste zu verwenden, geht man nacheinander alle Punkte durch und ändert [ ] in [X], um anzuzeigen, dass man diesen Schritt durchgeführt hat. GitHub zeigt auch die Anzahl der Commits im Branch, die Anzahl der geänderten Dateien und eine Ansicht mit den Unterschieden zwischen „base” und „head” an, sodass jeder sofort die beabsichtigten Änderungen sehen kann. Diese noch einmal auf Dinge wie versehentlich hinzugefügte Leerzeilen oder umfangreiche Formatierungsänderungen überprüfen, die die IDE hinter dem Rücken vorgenommen hat.

base repository: FreeCAD/FreeCAD    base: main  <----  head repository: GITHUB_USERNAME/FreeCAD    compare: myNewBranch

Able to merge. These branches can be automatically merged.

Auf Pull-Anfrage erstellen klicken, um fortzufahren. Es erscheint eine Meldung, dass einige Überprüfungen am Code durchgeführt werden muss. Dabei handelt es sich um ein System, das FreeCAD automatisch kompiliert und die Unit-Tests ausführt. Wenn die Tests erfolgreich sind, hat die Pull-Anfrage eine bessere Chance, in den Hauptcode integriert zu werden, andernfalls wird ein Bericht erstellt, in dem die aufgetretenen Fehler aufgeführt sind. Siehe FreeCAD-Pull-Anfragen.

Some checks haven’t completed yet

* continuous-integration/travis-ci/pr Pending — The Travis CI build is in progress  |Required|

Wenn die Tests erfolgreich sind, wird eine Meldung wie die folgende angezeigt

Alle Prüfungen wurden bestanden.

* continuous-integration/travis-ci/pr — The Travis CI build passed  |Required|

Dieser Zweig hat keine Konflikte mit dem Basis-Zweig. Nur diejenigen mit Schreibzugriff auf dieses Repository können Pull-Requests zusammenführen.

Jetzt muss man warten, bis die Administratoren den Branch zusammenführen. Man wird benachrichtigt, sobald dies geschehen ist.

Pull request successfully merged and closed

You’re all set — the GITHUB_USERNAME:myNewBranch branch can be safely deleted.
If you wish, you can also delete your fork of FreeCAD/FreeCAD.

Wenn man möchte, kann man den gerade zusammengeführten Zweig oder sogar den gesamten FreeCAD-Fork löschen, da der eigene Code bereits am Ende des Hauptzweigs enthalten ist.

-----o-----------Z----A' FreeCAD upstream/main

Hinweis: Man Kann während man auf die Genehmigung der Zusammenführung wartet, weiter an demselben Zweig arbeiten (git commit -a). Wenn man erneut git push ausführt, wird ein zweiter Zusammenführungs-Commit in derselben Pull-Anfrage in die Warteschlange gestellt und ein weiterer automatisierter Test durchgeführt. Das heißt, solange die Zusammenführungen noch nicht von den Administratoren genehmigt wurden, kann man weiterhin Änderungen an dem origin-Repository vornehmen, wodurch diese Commits in derselben Pull-Anforderung an das upstream-Repository in die Warteschlange gestellt werden. Bei kleinen Änderungen ist es oft wünschenswert, viele einzelne Commits mit einer einzigen Pull-Anforderung in die Warteschlange zu stellen. Für umfangreiche Ergänzungen zum Quellcode sollte man einen weiteren Branch erstellen, die Funktionen dort entwickeln und dann einen separaten Pull-Request für diesen Branch einreichen.

Die Pull-Request-Schnittstelle kann immer dann verwendet werden, wenn man Code aus den eigenen Repositorys an ein anderes Repository in GitHub übermitteln möchte. Man kann sie auch verwenden, um Code in die umgekehrte Richtung zusammenzuführen, d. h. von den Branches anderer Personen zu dem eigenen oder sogar zwischen den eigenen Branches. Im letzten Fall kann man die Zusammenführungen sofort selbst genehmigen, da man selbst der Eigentümer der Branches ist.

base repository: SomeProject/Some_Software  base: main       <----  head repository: GITHUB_USERNAME/Some_Software  compare: add_new_functions
base repository: GITHUB_USERNAME/FreeCAD    base: myNewBranch  <----  head repository: FreeCAD/FreeCAD                compare: main
base repository: GITHUB_USERNAME/FreeCAD    base: myNewBranch  <----  head repository: GITHUB_USERNAME/FreeCAD        compare: fix-many-bugs-branch

Das GitHub Repositorium auf dem neuesten Stand halten

Sobald man FreeCAD geforkt hat, existiert das persönliche Repository unabhängig vom Original. Wenn das ursprüngliche Repository neue Commits enthält, informiert GitHub einen darüber, dass das persönliche Repository hinsichtlich der Anzahl der Commits hinterherhinkt:

This branch is 5 commits behind FreeCAD:main.

In ähnlicher Weise informiert GitHub einen, wenn man einen Entwicklungszweig mit neuem Code erstellt hat, dass dieser Zweig in der Anzahl der Commits voraus ist, d. h., dieser Zweig enthält Änderungen, die noch nicht in das offizielle FreeCAD-Repository übernommen wurden:

This branch is 3 commits ahead of FreeCAD:main.

Während der Entwicklung sind beide Fälle möglich, da der eigene Branch möglicherweise keine Commits anderer Entwickler enthält, aber neue Commits von einem enthält:

This branch is 2 commits ahead, 14 commits behind FreeCAD:main.

Bei der Entwicklung von Code wird empfohlen, den Zweig, an dem man gerade arbeitet, neu zu rebasen, da der Zweig dadurch immer vor dem FreeCAD-Hauptcode bleibt.

Was den ursprünglichen main-Zweig betrifft, so wird dieser niemals automatisch von GitHub aktualisiert; dies muss man selbst tun. Zum main-Zweig wechseln, dann pull von upstream ausführen (wodurch fetch und merge ausgeführt werden) und diesen aktualisierten main-Zweig dann in das Remote-Repository origin übertragen.

git checkout main
git pull upstream main
git push origin main

Nachdem dies erledigt ist, teilt GitHub mit, dass man mit dem upstream-Repository synchronisiert ist.

This branch is even with FreeCAD:main.

Nachdem der main nun auf dem neuesten Stand ist, kann man zu diesem wechseln und den anderen Zweig löschen, den man zuvor zur Entwicklung einer Funktion verwendet hat.

git checkout main
git branch -d myNewBranch

Um den Branch im Remote-Repository origin zu löschen, kann man den Befehl push verwenden. Normalerweise pusht man einen lokalen Zweig; dadurch wird ein Remote-Zweig mit dem gleichen Namen wie der lokale Zweig erstellt.

git push origin myNewBranch

Wenn jedoch die Notation local_name:remote_name verwendet wird, wird der lokale Zweig im Remote-Repository unter einem anderen Namen erstellt:

git push origin myNewBranch:someRemoteBranch

Daher kannst du den entfernte Fernzweig löschen, indem du einen leeren lokale Zweig schiebst:

git push origin :myNewBranch
git push origin :someRemoteBranch

Da man nun nur noch über ein aktuelles main verfügt, kann man einen neuen Zweig erstellen und die Schritte zum Ändern von Dateien, Committen, Pushen, Einreichen eines Pull-Request, Zusammenführen und Aktualisieren wiederholen.

git checkout main
git checkout -b anotherBranch

Wenn man den bereits benutzerdefinierten Branch nicht löschen möchte, kann man eine Aktualisierung erzwingen, sodass er mit dem aktualisierten main übereinstimmt. Anschließend kann man damit tun, was man möchte, einschließlich weiterer Commits hinzufügen und ihn in das Remote-Repository origin pushen.

git checkout myNewBranch
git reset --hard main
git push -f origin myNewBranch

Ein solches hartes Zurücksetzen eines Branches ist in der Regel nicht erforderlich. In den meisten Fällen sollten man die Reihenfolge befolgen: Einen neuen Branch erstellen, die Änderungen committen, diese Änderungen pushen, den Zweig mergen und ihn anschließend löschen.

Erweiterte Git Operationen

Suchen

Einige praktische Werkzeuge, die einem bei der Suche helfen:

Dateinamen suchen

git ls-files verwenden, um das Repository nach Dateien zu durchsuchen, deren Dateiname eine bestimmte Zeichenfolge enthält. Das folgende Beispiel gibt alle Dateien zurück, deren Dateiname die Zeichenfolge 'dxf' enthält.

git ls-files *dxf*


Suche nach einer Zeichenkette

git grep verwenden, um das Repository nach Dateien zu durchsuchen, die eine bestimmte Zeichenfolge enthalten. Das folgende Beispiel gibt alle Instanzen der Dateien zurück, die die Zeichenfolge 'dxf' enthalten.

git grep dxf


Auflösen von Zusammenführungskonflikten

Das Zusammenführen von Branches mit git merge oder das Rebasing des Branches mit git rebase führt gelegentlich zu Konflikten, da Dateien möglicherweise gleichzeitig von einem anderen Autor geändert wurden. In diesem Fall sollte man sich die Änderungen beider Seiten, die des anderen Autors und die eigenen, ansehen und dann entscheiden, wie man beide Änderungssätze bestmöglich einarbeiten kann. Dies ist in der Regel ein manueller Prozess, der nicht automatisiert werden kann. Der Programmierer muss den Code verstehen und entscheiden, welcher Code verschoben, umgeschrieben oder entfernt werden muss, um den Konflikt zu lösen.

Sobald ein Konflikt auftritt, kann eine Meldung wie diese erscheinen.

CONFLICT (content): Merge conflict in src/Mod/source_code.py
error: Failed to merge in the changes.
Patch failed at 1234 Some commit message when editing source_code.py

Wenn ein spezielles Diff-Tool für Git installiert und konfiguriert ist, beispielsweise Gnome's Meld, kann der Konflikt mithilfe der Operation mergetool untersucht und gelöst werden.

git mergetool

Das Meld-Tool zeigt normalerweise drei Spalten an: Die beiden seitlichen Spalten zeigen die beiden in Konflikt stehenden Dateien an, während die mittlere Spalte den neuen Code anzeigt, der schließlich gespeichert und committet wird. Daher sollte diese mittlere Spalte so bearbeitet werden, dass sie den Code beider seitlichen Spalten integriert. Sobald der Konflikt gelöst und der neue Quellcode (die mittlere Spalte) gespeichert ist, kann das Meld-Tool geschlossen werden. Dann kann der Vorgang merge oder rebase fortgesetzt werden.

git merge --continue
git rebase --continue

Weitere Informationen zum Zusammenführen und Lösen von Konflikten finden Sie unter:

Änderungen untersuchen

Den Verlauf einer einzelnen Datei anhand verschiedener Commits mit dem Befehl log überprüfen:

git log --patch path

Wobei path ein beliebiges Verzeichnis oder eine beliebige Datei sein kann. Anstelle von --patch können auch die Kurzformen -p oder -u verwendet werden.

Änderungen zwischen zwei Zweigen untersuchen

Die Änderungen zwischen zwei Zweigen mit den Operationen log und diff unter Angabe der Namen der Zweige überprüfen:

git log main..myBranch
git diff main..myBranch

Der Befehl log zeigt die Commits an, während diff die tatsächlichen Änderungen in den Dateien anzeigt.

Dateien und Verzeichnisse zurücksetzen

Wenn man versehentlich Änderungen an einer Datei oder einem Verzeichnis vorgenommen hat, möchte man diese Änderungen möglicherweise vollständig rückgängig machen, um den vorherigen Zustand des Quellcodes wiederherzustellen.

Dies kann schnell mit der Operation checkout durchgeführt werden:

git checkout path
git checkout .

Dadurch wird path (eine Datei oder ein Verzeichnis) in den Zustand am Anfang des Zweigs zurückgesetzt, wobei nicht festgeschriebene Änderungen verworfen werden. Wenn path der einzelne Punkt . ist, werden alle Dateien im aktuellen Verzeichnis wiederhergestellt.

Wenn man versehentlich Dateien und Verzeichnisse hinzugefügt hat, kann man den Befehl clean verwenden:

git clean -df

Dadurch werden alle Dateien und Verzeichnisse (-df) gelöscht, die nicht vom Repository verfolgt werden, d. h. diejenigen, die zuvor nicht mit dem Befehl add hinzugefügt wurden.

Um das Repository vollständig zurückzusetzen und alle nicht festgeschriebenen Änderungen zu verlieren, verwendet man den Befehl reset:

git fetch
git reset --hard FETCH_HEAD

Wobei FETCH_HEAD die Spitze des upstream-Repositorys ist. Es kann auch ein anderer Commit verwendet werden.

Der Befehl revert macht ebenfalls Änderungen rückgängig. Allerdings fügt dieser Befehl dazu einen weiteren Commit zur Historie hinzu, was in vielen Fällen nicht erwünscht ist.

Beschneiden alter Zweige

Wenn man viele Branches in das upstream-Repository übertragen hat, möchten man diese Branches möglicherweise aus dem lokalen System entfernen, da sie bereits zusammengeführt wurden. Der Zweig im Online-Repository origin kann unmittelbar nach dem Zusammenführen gelöscht werden. Anschließend kann man die lokalen Verweise auf diesen Zweig entfernen, indem man die Optionen --prune oder prune für die Operationen fetch und remote verwenden.

git fetch --prune origin
git remote prune origin

Schließlich kannst du die Zweige lokal löschen

git branch -D myBranch

Es empfiehlt sich außerdem, nach einer Weile eine Garbage Collection durchzuführen, indem man den Befehl gc verwendet. Dadurch werden unnötige Dateien bereinigt und lokale Dateirevisionen komprimiert, um die lokale Festplattennutzung des Repositorys zu optimieren.

git gc

Arbeiten mit Patches

Obwohl Git Ihnen dir erlaubt, verschiedene Code Zweige mit git merge zusammenzuführen (in deinem Computer) oder einer Pull Anfrage (Fernrepositorium) gibt es Zeiten, in denen es wünschenswert sein kann, einen traditionellen "Patch" zu erstellen, der als Anhang per Email verschickt werden kann. Der folgende Arbeitsablauf erklärt, wie dies zu tun ist.

Patches erstellen

git branch -v
git checkout myBranch
git format-patch main --stdout > ../myCode.patch
git format-patch HEAD^
git format-patch HEAD~1

Die Anzahl der Zirkumflex-Zeichen ^ oder die Zahl 1 geben die Anzahl der zu berücksichtigenden Commits an, d. h. ^^^ oder ~3 erstellt drei Patches für drei Commits.

git format-patch HEAD^

Dadurch wird ein Patch oder eine Reihe von Patches mit der folgenden Namenskonvention erstellt

XXXX-commit-message.patch

wobei XXXX eine Zahl zwischen 0000 und 9999 ist und die Commit-Nachricht den größten Teil des Dateinamens ausmacht, zum Beispiel

0001-fix-ViewProjMatrix-getProjectionMatrix.patch

Patches anwenden

Git kann Patches oder Diffs zusammenführen. Weitere Informationen zu diesem Vorgang findet man unter Patches mit Git anwenden.

Wenn du die Patch Datei bereits in deinem System hast, wende sie einfach an.

git apply myCode.patch

Man kann curl verwenden, um einen Patch von einer Website herunterzuladen, und ihn dann über git anwenden.

curl -O https://some.website.org/code/myCode.patch
git apply myCode.patch

.diff oder .patch am Ende der URL eines GitHub-Commits, Pull-Requests oder Vergleichsansicht hinzufügen, damit die Website die Nur-Text-Ansicht dieser Seite anzeigt.

Man kann curl auf einen bestimmten Commit-Patch im Repository verweisen und ihn direkt an git weiterleiten, um den Patch anzuwenden.

curl https://github.com/FreeCAD/FreeCAD/commit/c476589652a0f67b544735740e20ff702e8d0621.patch | git apply -

Einen Patch rückgängig machen

Wenn man einen Patch anwendet, werden einige Dateien geändert. Diese Änderungen sind jedoch erst dann dauerhaft, wenn man die Änderungen festschreibt. Wenn man einen Patch rückgängig machen möchte, befolgen man daher die folgenden Anweisungen.

Dadurch werden die vorgenommenen Änderungen rückgängig gemacht, sofern noch Zugriff auf die ursprüngliche Patch-Datei besteht.

git apply -R myCode.patch

Alternativ werden dadurch nicht festgeschriebene Änderungen an dem Zweig entfernt.

git checkout -f

Git-Commits zwischenspeichern (stashing)

Angenommen, man arbeiten an einem Branch und nimmt einige Änderungen an der Quelle vor, die außerhalb des Umfangs des aktuellen Branches liegen. Mit anderen Worten: Diese Änderungen wären besser in einem anderen Branch als dem aktuellen aufgehoben. Mit dem Befehl git stash kann man diese nicht festgeschriebenen lokalen Änderungen vorübergehend speichern.

git stash

Wenn man diese Commits in Zukunft verwenden möchte, kann man die Commits aus dem Zwischenspeicher (Stash) in den Arbeitszweig „herausholen“.

git stash pop

Wenn man feststellt, dass einem die gespeicherten Commits nicht mehr gefallen, kann man die Commits vollständig aus dem Stash löschen.

git stash drop

Man kann mehrere Stash-Commits mit

git stash list

Weitere Informationen findet man unter Nützliche Tricks, die man vielleicht noch nicht über Git Stash weiß.

GitHub Anfragen lokal herausfinden

GitHub-Pull-Anfragen lokal überprüfen


Blame-Funktion

Die Blame-Funktion auf GitHub ist nützlich, um herauszufinden, welcher Commit jede einzelne Codezeile eingeführt oder zuletzt geändert hat. Um sie zu aktivieren, wechselt man beim Anzeigen einer Datei von der Registerkarte Code zur Registerkarte Blame oder wählt eine bestimmte Zeile aus (auf deren Nummer klicken), die Taste ... drücken und View git blame wählen. Weitere Informationen zur Blame-Funktion findet man in diesem Forumbeitrag. Der zugehörige Git-Befehl ist hier dokumentiert.

Halbieren (bisect)

git bisect ist eine Methode, um den spezifischen Commit zu finden, der einen Fehler verursacht hat.

Es müssen zwei Commits gefunden werden:

Dann Folgendes über das Terminal eingeben:

git bisect start
git bisect good abcd
git bisect bad efgh

Ergebnis: git checkt den Mittelpunkt zwischen den beiden Commits aus.

Der nächste Schritt besteht darin, den Code zu erstellen und zu testen. Wenn das System funktioniert, fährt man mit der Eingabe von folgendem Befehl fort:

git bisect good

Den vorherigen Schritt wiederholen, indem man den Code erstellt und testet.

Wenn das System defekt ist, gibt man Folgendes ein:

git bisect bad

Die vorherigen Schritte wiederholen und dabei je nach Ergebnis der Tests good oder bad anwenden.

Schließlich wird git mitteilen, dass wxyz der erste fehlerhafte Commit ist.

Um den bisect-Prozess zu beenden, gibt man schließlich Folgendes ein:

git bisect reset

Hinweis: git bisect dauert sehr lange, wenn gute und schlechte Ergebnisse weit auseinander liegen.

FreeCAD Revisionsnummer

Im Gegensatz zu Subversion, das für seine Revisionen eine fortlaufende Nummer verwendet, erzeugt Git bei jedem Commit SHA-1-Hashwerte. Ein Hashwert ist eine lange alphanumerische Zeichenfolge, die wie folgt aussieht

9b3ffef570596e184006287434fba54a4b03ccc3

Letzte Revisionsnummer

Um die neueste Revisionsnummer eines bestimmten Branches zu ermitteln, verwendet man den Befehl rev-list mit der Option --count. Gibt den Namen des Branches, des Remote-Repositorys, des Tags oder eines speziellen Zeigers wie HEAD an, um den letzten Commit in diesem bestimmten Objekt anzugeben.

git rev-list --count main
git rev-list --count HEAD
git rev-list --count origin

Oder man durchsucht das Repository auf GitHub und liest die Anzahl der Commits, die in dem jeweiligen Branch gemeldet werden.

Revisionsnummer eines bestimmten Commit Hashes

Da es sich bei dem Hash um eine alphanumerische Zeichenfolge handelt, ist es nicht sehr sinnvoll, zu entscheiden, ob ein bestimmter Commit älter oder neuer als ein anderer Hash ist. Um die Revisionsnummer eines bestimmten Hashs zu ermitteln, verwendet man erneut die Operation rev-list. Als Eingabe kann der vollständige Hash oder ein eindeutiger Teil-Hash verwendet werden, wobei in der Regel die ersten 7 Ziffern ausreichen.

git rev-list --count ab1520b872821414c6ce4a15fb85d471ac2a2b03
git rev-list --count 9948ee4

Revisions Hash einer bestimmten Commit Nummer

Wenn wir die Commit-Nummer haben, beispielsweise 15000, und den entsprechenden Hash finden möchten, müssen wir die Anzahl der Commits seit diesem Zeitpunkt bis zum letzten Commit (HEAD) berechnen. Zunächst muss die neueste Commit-Nummer abgerufen werden.

git rev-list --count HEAD
17465

Dann subtrahiert man den gewünschten Commit.

17465 - 15000 = 2465

Dann den Befehl log verwenden, um alle Commits und Hashes anzuzeigen. Die Option --skip überspringt die von uns berechneten Unterschiede zwischen den Commits, sodass wir direkt zu dem gesuchten Hash gelangen.

git log --skip=2465
commit 44c2f19e380e76b567d114a6360519d66f7a9e24

Da das Protokoll möglicherweise zwei nahe beieinander liegende Commits anzeigt, überprüfen, ob es sich um die richtige Commit-Nummer handelt. Wenn sie um eins abweicht, einfach den nächsten Commit in der Reihenfolge wählen (vor oder nach) und erneut überprüfen.

git rev-list --count 44c2f19e38
15000

Revisionsnummer in der FreeCAD Oberfläche

Die Versionsnummer, die mit dem Std Über Werkzeug angezeigt wird, ist in src/Build/Version.h definiert, was zur Kompilierzeit erstellt wird, wenn das Werkzeug cmake ausgeführt wird. Lies Versionsnummer aus der Git Quelle extrahieren für weitere Informationen.

Hinzufügen weiterer (Fern) Repositorien

Mehrere Mitarbeiter des FreeCAD Projekts haben ihre eigenen Git Repositorien, in denen sie ihre Arbeit aufbauen oder neue Ideen ausprobieren, bevor sie bereit sind, in den offiziellen Quellcode aufgenommen zu werden. Vielleicht möchtest du ihre Quellen bekommen, um ihren Code selbst zu testen, wenn sie eine Pull Anfrage stellen.

Verwende den Befehl git fern Befehl, um diese anderen Repositorien hinzuzufügen, so dass du deren Code holen und abrufen kannst.

git checkout main
git remote add OTHER_USER OTHER_URL
git fetch OTHER_USER
git checkout -b OTHER_BRANCH OTHER_USER/OTHER_BRANCH

Lass uns zum Beispiel Bernds Fernrepositorium hinzufügen:

git remote add bernd http://github.com/berndhahnebach/FreeCAD_bhb

Der git holen Befehl lädt die Referenzen von diesem Fernrepositorium herunter.

git fetch bernd

Liste alle Zweige in deinem eigenen Repositorium und die von deinen hinzugefügten Fernen auf. Bernds Zweige werden als Fern/bernd/<Zweigname> angezeigt.

git branch -a

Lass uns nun eine zusammenfassende Liste der letzten 10 Commits von bernds femdev Zweig ansehen.

git log -10 --oneline remotes/bernd/femdev

Jetzt können wir den gewünschte Zweig zur Inspektion herausfinden.

git checkout remotes/bernd/femdev

Dann können wir einen lokalen Zweig erstellen, der auf dem entfernten Zweig basiert. Diesen lokalen Zweig können wir modifizieren und unseren eigenen Code hinzufügen.

git checkout -b local_branch_name /remotes/bernd/femdev

Du kannst den git rebase des neu erhaltenen Zweigs auf den upstream/main Zweig umstellen, um sicherzustellen, dass er den neuesten Code verwendet. Wenn es Konflikte gibt, müssen diese an diesem Punkt gelöst werden.

git pull --rebase upstream main

Der neue Zweig ist bereit, modifiziert und kompiliert zu werden, wie in Kompilieren beschrieben.

Besuche die Entwicklungsabteilung des FreeCAD Forums, um mehr über die Entwicklung zu erfahren.

Weiterführende Literatur