Haben Sie sich bei der Verwendung von Software-Projekten auf GitHub auch schon mal gefragt: „Was ist ein Pull Reqest?“, „Wie erstelle ich eigentlich einen Pull Request?“ und „Wieso benötige ich manchmal einen Fork oder eben nicht?“ Im folgenden Blog Post gehen wir auf alle drei Fragestellungen ein und erklären dies am Beispiel des AIT Dependency Managers auf GitHub.
Ein Pull Request ist im Prinzip nichts anderes als eine Anfrage die gestellt wird, um Änderungen am Code in den Master-Branch übernehmen zu lassen (vereinfacht: „git merge“). Die eigenen Änderungen werden dazu in einem getrennten Feature-Branch vorbereitet und anschließend zur Übernahme beim Repository-Verantwortlichen angemeldet. Der Verantwortliche prüft die Änderungen und überträgt anschließend die Änderungen in das Quell-Repository. An den Commits werden für gewöhnlich keine Änderungen direkt vorgenommen, sodass Metadaten wie der Original-Autor, Commit-Datum, etc. erhalten bleiben. Diese Art der Code-Integration und -Review wird durch verschiedene Plattformen und Tools (z.B. GitHub, Visual Studio) unterstützt und nennt sich Pull Request. Als gutes Vorgehen hat sich dabei etabliert, dass der Entwickler Kommentare hinzufügt, die dem Repository-Verantwortlichen schnell einen Überblick geben, was mit dem Pull Request erreicht werden soll.
Eine Besonderheit bei der Verwaltung bzw. Erstellung der Feature-Branches ist das Fork Konzept. Ein Feature-Branch im Rahmen eines Pull-Requests kann ich als Entwickler entweder im Original-Repository oder in einer Repository-Kopie durchführen. Der Ort hängt schlussendlich von meiner Vertrauensstellung zum Repository ab. Als Mitarbeiter einer Organisation vertraut meistens der Repository-Verantwortlicher mir als Organisationsmitglied mehr als einem externen Mitarbeiter. Der Hintergrund einer niedrigeren Vertrauensstellung ist z.B. fehlendes Wissen über Architektur-Konzepte bzw. Code-Stil(e) oder potentiell negative Auswirkungen auf andere Teile der Applikation.
Um die Vertrauensfrage zu adressieren, wurde das Fork Konzept eingeführt, d.h. dank Git kann jeder Entwickler auf einer 1:1 Kopie seine Arbeit mit Branches, Commits, etc. eigenverantwortlich organisieren, aber kontrolliert seine Änderungen wieder an das Original-Repository übertragen. Das Fork-Konzept hat hier die Aufgabe der Isolation, sodass Entwickler Änderungen in kompletter Isolation auf einer 1:1 Kopie des Repositories vorbereiten und aufbereiten können und anschließend die Änderungen auf sehr einfache Art und Weise vom Quell-Repository-Autor übernommen werden können. Durch die Isolation bleibt hier das Orginal-Repository in einen aufgeräumten Zustand. Eine gute Diskussion zum Thema wann ist „Forken“ sinnvoll und wann nicht finden sie im Artikel von Willy-Peter.
Fork erstellen und Klonen
Die ersten Schritte im Pull Request Prozess sind das Forken und Klonen des gewünschten GitHub Repositories (hier AIT.DependencyManager). Klicken Sie dafür auf der GitHub Repository Webseite ganz oben rechts auf die unscheinbare Schaltfläche „Fork“.
Im Anschluss daran haben Sie in Ihrem GitHub-Account einen eigenen Fork, den Sie wie jedes andere Git Repository klonen können (z.B. : https://github.com/YourGitHubAccount/AIT.DependencyManager).
Für das Klonen haben sie je nach Geschmack mehre Optionen. Klicken Sie zunächst auf die grüne Schaltfläche „Clone or download“. Wenn Sie die GitHub-Extensions for Visual Studio installiert haben, wird Ihnen die Schaltfläche „Open in Visual Studio“ angezeigt, so wie im folgenden Screenshot dargestellt. Über einen Klick wird in einer neuen Visual Studio-Instanz die Eingabemaske für das Klonen eines Repositories geöffnet, die bereits den Link zu Ihrem Fork enthält. Haben Sie die Extension nicht installiert oder möchten Sie eine andere IDE oder die Kommandozeile verwenden, so können den Link zum Repository mit einem Klick auf das Symbol hinter der URL in die Zwischenablage kopieren.
Im Visual Studio ist es beim Klonen empfehlenswert das Repository an einem geeigneten Platz auf Ihrer Festplatte abzulegen und nicht den Standardwert im Windows-Profil-Ordner zu verwenden (siehe Vorschlag im Screenshot: C:\Repos ).
Branchen
Bevor Sie mit dem Entwickeln beginnen, ist es ratsam sich einen eigenen Branch zu erstellen. Das Erstellen eines Branches in Git ist sehr leichtgewichtig. So hat sich in Git das Vorgehen etabliert jedes Feature in einem eigenen lokalen Branch zu entwickeln. Dadurch kann die Sicherheit, Nachvollziehbarkeit, Übersichtlichkeit und schlussendlich auch Wartbarkeit während der Entwicklungsphase durch regelmäßiges commiten erreicht werden. Trotzdem bleibt der Code und die Historie das Urspung-Branches sauber, in dem der Code erst dann zurückfließt, wenn dieser das gewünschte Qualitätsniveau erreicht hat.
Das Erstellen eines Branches in einem öffentlichen GitHub Repository in Visual Studio funktioniert identisch wie bei Branches in einem privaten Repositories Git-Server (z.B. TFS, VSTS, etc.) auch. Klicken Sie zunächst in der Statuszeile auf den Pfeil beim aktuellen Branch (siehe Screenshot – in diesem Fall „master“). Mit einem weiteren Klick auf „New Branch…“ öffnet sich die Eingabemaske, in der noch ein Branch-Name vergeben und der Ursprungs-Branch ausgewählt werden muss.
Commit und Publish
Nach der Codeänderung wird der Code mit einem „Commit“ in das lokale Repository eingecheckt.
Das Remote-Repository (in diesem Fall GitHub) hat zu diesem Zeitpunkt noch keine Kenntnis, dass offline ein Branch erstellt wurde und Änderungen eingecheckt wurden. Wie im folgenden Screenshot zu sehen ist, werden Sie beim ersten „Push“ aufgefordert, Ihren Branch auf GitHub zu veröffentlichen (Outgoing Commits -> „Publish“).
Jetzt haben Sie Ihre Quellcodeänderung in Ihrem GitHub-Account in einem Branch innerhalb Ihres Forks veröffentlicht und können den Pull Request Prozess beginnen.
Pull Request
Den Abschluss bildet das Übermitteln der Änderungen via Pull Request. Zum Auslösen des Pull Requests melden Sie sich zunächst in Ihren GitHub-Account an und öffnen Sie ihren Fork. Klicken Sie auf die Schaltfläche „Compare & pull request“
Vor dem Abschicken geben Sie als letzten Schritt noch eine Beschreibung für Ihren Pull Request an und schicken ihn ab.
Als Ergebnis Ihres Pull Requests erhält der Verwalter des Repositories eine Benachrichtigung, dass ein neuer Pull Request eingegangen ist. Er wird jetzt Ihre Änderungen prüfen und entscheiden, ob er die Codeänderung(en) akzeptiert oder ablehnt. Der Prozess aus Sichtweise des Repository-Verwalters wird in einem extra Blog-Post behandelt.
Fazit
Im Rahmen dieses Blogposts wurde vorgestellt, dass Pull Requests kein Hexenwerk sind und jeder Entwickler mit einfachen Schritten sich an GitHub Projekten beteiligen kann. Sie haben dabei sowohl für den Entwickler als auch den Projekt-Verwalter mehrere Vorteile. Der Projektverantwortliche auf der einen Seite kann vor der Übernahme neuen Code auf diverse Aspekte prüfen und nur „guten“ Code integrieren. Der externe Projektmitarbeiter hingegen kann durch Rückmeldung(en) vom Projektverantwortlichen lernen (Bsp.: neue Code-Stile, Patterns, Architektur, Codequalität, etc.). Aufgrund der Isolation kann der neue Projektmitarbeiter zudem durch seine Änderungen keinen direkten Schaden anrichten und geniest durch die Isolation auch eine Art von Schutz.
Sehr gut erklärt. Danke