-
1. Erste Schritte
-
2. Git Grundlagen
-
3. Git Branching
- 3.1 Branches auf einen Blick
- 3.2 Einfaches Branching und Merging
- 3.3 Branch-Management
- 3.4 Branching-Workflows
- 3.5 Remote-Branches
- 3.6 Rebasing
- 3.7 Zusammenfassung
-
4. Git auf dem Server
- 4.1 Die Protokolle
- 4.2 Git auf einem Server einrichten
- 4.3 Erstellung eines SSH-Public-Keys
- 4.4 Einrichten des Servers
- 4.5 Git-Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Von Drittanbietern gehostete Optionen
- 4.10 Zusammenfassung
-
5. Verteiltes Git
-
6. GitHub
-
7. Git Tools
- 7.1 Revisions-Auswahl
- 7.2 Interaktives Stagen
- 7.3 Stashen und Bereinigen
- 7.4 Deine Arbeit signieren
- 7.5 Suchen
- 7.6 Den Verlauf umschreiben
- 7.7 Reset entzaubert
- 7.8 Fortgeschrittenes Merging
- 7.9 Rerere
- 7.10 Debuggen mit Git
- 7.11 Submodule
- 7.12 Bundling
- 7.13 Replace (Ersetzen)
- 7.14 Anmeldeinformationen speichern
- 7.15 Zusammenfassung
-
8. Git einrichten
- 8.1 Git Konfiguration
- 8.2 Git-Attribute
- 8.3 Git Hooks
- 8.4 Beispiel für Git-forcierte Regeln
- 8.5 Zusammenfassung
-
9. Git und andere VCS-Systeme
- 9.1 Git als Client
- 9.2 Migration zu Git
- 9.3 Zusammenfassung
-
10. Git Interna
-
A1. Anhang A: Git in anderen Umgebungen
- A1.1 Grafische Schnittstellen
- A1.2 Git in Visual Studio
- A1.3 Git in Visual Studio Code
- A1.4 Git in IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git in Sublime Text
- A1.6 Git in Bash
- A1.7 Git in Zsh
- A1.8 Git in PowerShell
- A1.9 Zusammenfassung
-
A2. Anhang B: Git in deine Anwendungen einbetten
- A2.1 Die Git-Kommandozeile
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Anhang C: Git Kommandos
- A3.1 Setup und Konfiguration
- A3.2 Projekte importieren und erstellen
- A3.3 Einfache Snapshot-Funktionen
- A3.4 Branching und Merging
- A3.5 Projekte gemeinsam nutzen und aktualisieren
- A3.6 Kontrollieren und Vergleichen
- A3.7 Debugging
- A3.8 Patchen bzw. Fehlerkorrektur
- A3.9 E-mails
- A3.10 Externe Systeme
- A3.11 Administration
- A3.12 Basisbefehle
6.5 GitHub - Skripte mit GitHub
Skripte mit GitHub
Jetzt haben wir alle wichtigen Funktionen und Workflows von GitHub kennengelernt, aber jede große Gruppe oder jedes Projekt wird Anpassungen haben, die sie vornehmen möchte, oder externe Dienste, die sie integrieren möchte.
Glücklicherweise ist GitHub, in vielerlei Hinsicht, ziemlich leicht anzupassen. In diesem Abschnitt erfährst du, wie du das GitHub-Hook-System und seine API verwendest, damit GitHub so funktioniert, wie wir es uns wünschen.
Dienste und Hooks
Der Bereich Hooks und Services der GitHub-Repository-Administration ist der einfachste Weg, um GitHub mit externen Systemen interagieren zu lassen.
Dienste
Schauen wir uns zuerst die Services (Dienste) an. Sowohl die Hooks- als auch die Dienste-Integration findest du im Abschnitt Einstellungen deines Repositorys. Dort haben wir uns zuvor mit dem Hinzufügen von Mitwirkenden und dem Ändern des Standard-Branch deines Projekts beschäftigt. Unter der Registerkarte „Webhooks und Dienste“ siehst du so etwas wie Konfiguration von Diensten und Hooks.
Es gibt Dutzende von Diensten, aus denen du wählen kannst. Die meisten davon sind Integrationen in andere kommerzielle und Open-Source-Systeme. Die meisten von ihnen betreffen kontinuierliche Integrationsdienste (engl. Continuous-Integration-Services), Bug- und Issue-Tracker, Chatroom-Systeme und Dokumentationssysteme. Wir werden uns mit der Konfiguration eines sehr einfachen Systems befassen, dem E-Mail-Hook. Wenn du „E-Mail“ aus der Auswahlliste „Add Service“ wählst, erhältst du einen Konfigurationsbildschirm wie unter E-Mail-Service-Konfiguration.
Wenn wir in diesem Fall auf die Schaltfläche „Dienst hinzufügen“ klicken, erhält die von uns angegebene Mail-Adresse jedes Mal eine E-Mail, wenn jemand in das Repository pusht. Dienste können auf viele verschiedene Arten von Ereignissen lauschen, aber die meisten sind ausschließlich auf Push-Events spezialisiert und bearbeiten diese Daten dann.
Wenn es ein System gibt, das du verwendest und das du mit GitHub integrieren möchtest, solltest du hier überprüfen, ob es eine bestehende Service-Integration gibt. Angenommen, du verwendest Jenkins, um auf deiner Code-Basis Tests durchzuführen. Du könntest die eingebaute Service-Integration von Jenkins aktivieren, um jedes Mal einen Testlauf zu starten, wenn jemand in dein Repository pusht.
Hooks
Wenn du eine speziellere Lösung benötigst oder mit einem Dienst oder einer Website interagieren möchtest, der nicht in dieser Liste enthalten ist, kannst du stattdessen das generischere Hooks-System verwenden. GitHub Repository-Hooks sind denkbar einfach. Gib eine URL an und GitHub wird bei jedem gewünschten Event über HTTP Nutz-Daten an diese URL senden.
Im Regelfall kannst du einen kleinen Webservice einrichten, um nach einem GitHub-Hook-Inhalt zu suchen und dann die empfangenen Daten weiter zu verarbeiten.
Um einen Hook zu aktivieren, klicke in Konfiguration von Diensten und Hooks auf die Schaltfläche „Webhook hinzufügen“. Das führt dich zu einer Seite, die wie Web-Hook Konfiguration aussieht.
Die Konfiguration für einen Web-Hook ist relativ einfach.
In den meisten Fällen gibst du einfach eine URL und einen geheimen Schlüssel ein und klicken auf „Webhook hinzufügen“.
Es gibt ein paar Optionen, bei denen GitHub veranlasst wird dir eine Payload zu senden – die Vorgabe ist, eine Payload nur für das push
Ereignis senden, wenn jemand neuen Code in einen beliebigen Branch deines Repositorys schiebt.
Schauen wir uns ein kleines Beispiel für einen Webservice an, den du für die Verwaltung eines Web-Hooks einrichten kannst. Wir verwenden das Ruby Web-Framework Sinatra, da es relativ übersichtlich ist und du leicht sehen kannst, was wir tun.
Nehmen wir an, wir wollen eine E-Mail erhalten, wenn eine bestimmte Person zu einem bestimmten Branch unseres Projekts pusht und eine bestimmte Datei ändert. Mit einem solchen Code könnten wir das ziemlich einfach machen:
require 'sinatra'
require 'json'
require 'mail'
post '/payload' do
push = JSON.parse(request.body.read) # parse the JSON
# gather the data we're looking for
pusher = push["pusher"]["name"]
branch = push["ref"]
# get a list of all the files touched
files = push["commits"].map do |commit|
commit['added'] + commit['modified'] + commit['removed']
end
files = files.flatten.uniq
# check for our criteria
if pusher == 'schacon' &&
branch == 'ref/heads/special-branch' &&
files.include?('special-file.txt')
Mail.deliver do
from 'tchacon@example.com'
to 'tchacon@example.com'
subject 'Scott Changed the File'
body "ALARM"
end
end
end
Hier nehmen wir den JSON-Inhalt, den GitHub uns liefert, und schauen nach, wer sie zu welchem Branch gepusht hat und welche Dateien bei allen Commits, die gepusht wurden, angefasst wurden. Dann überprüfen wir das anhand unserer Kriterien und senden eine E-Mail, wenn sie den Anforderungen entspricht.
Um so etwas zu entwickeln und zu testen, hast du eine ansprechende Entwicklerkonsole auf dem gleichen Bildschirm, auf dem du den Hook eingerichtet hast. Du kannst die jüngsten Aktualisierungen sehen, die GitHub für diesen Webhook vorgenommen hat. Für jeden Hook kannst du nachvollziehen, wann er zugestellt wurde, ob er erfolgreich war und Body und Header für Anfrage (engl. request) und Antwort (engl. response) prüfen. Das ermöglicht ein unglaublich einfaches Testen und Debuggen deines Hooks.
Das andere großartige Feature ist, dass du jede der Payloads neu ausliefern kannst, um deinen Service einfach zu testen.
Weitere Informationen wie man Webhook schreiben kann und welche Event-Typen man überwachen kann, findest du in der GitHub-Developer-Dokumentation unter https://developer.github.com/webhooks/.
Die GitHub API
Dienste und Hooks bieten die die Möglichkeit, Push-Benachrichtigungen über Ereignisse zu erhalten, die in deinem Repositorys stattfinden. Aber was ist, wenn du weitere Informationen über diese Ereignisse benötigst? Was ist, wenn du eine Automatisierung benötigst, wie z.B. das Hinzufügen von Mitwirkenden oder das Labeln von Issues?
Hier kommt die GitHub API zum Zug. GitHub verfügt über eine Vielzahl von API-Endpunkten, um fast alles zu automatisieren, was du manuell auf der Website tun kannst. In diesem Abschnitt erfahren wir, wie man sich authentifiziert und mit der API verbindet, wie man ein Issue kommentiert und wie man den Status eines Pull-Requests über die API ändert.
Grundlegende Anwendung
Die elementarste Aufgabe, die du lösen kannst, ist eine einfache GET-Anfrage an einen Endpunkt, der keine Authentifizierung erfordert. Das kann ein Benutzer- oder Lese-Informationen in einem Open-Source-Projekt sein. Wenn wir beispielsweise mehr über einen Benutzer mit Namen „schacon“ erfahren möchten, können wir so etwas verwenden:
$ curl https://api.github.com/users/schacon
{
"login": "schacon",
"id": 70,
"avatar_url": "https://avatars.githubusercontent.com/u/70",
# …
"name": "Scott Chacon",
"company": "GitHub",
"following": 19,
"created_at": "2008-01-27T17:19:28Z",
"updated_at": "2014-06-10T02:37:23Z"
}
Es gibt unzählige Endpunkte wie diesen, um Informationen über Organisationen, Projekte, Issues, Commits zu erhalten – so ziemlich alles, was du öffentlich auf GitHub sehen kannst.
Du kannst die API sogar verwenden, um beliebige Markdown-Funktionen zu rendern oder eine .gitignore
Vorlage zu finden.
$ curl https://api.github.com/gitignore/templates/Java
{
"name": "Java",
"source": "*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see https://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
"
}
Ein Issue kommentieren
Wenn du jedoch eine Aktivität auf der Website durchführen möchtest, wie z.B. einen Kommentar zu einem Issue oder Pull Request oder wenn du private Inhalte einsehen oder mit diesen interagieren möchtest, musst du sich authentifizieren.
Es gibt mehrere Möglichkeiten, sich zu authentifizieren. Du kannst die Basisauthentifizierung nur mit deinem Benutzernamen und Passwort verwenden, aber im Allgemeinen ist es eine bessere Idee, einen persönlichen Zugriffstoken zu verwenden. Du kannst den über die Registerkarte „Anwendungen“ auf deiner Einstellungsseite generieren.
Du wirst gefragt, welchen Geltungsbereich du für dieses Token möchtest und es wird eine Beschreibung angezeigt. Achte darauf, eine gute Beschreibung zu verwenden, damit du dir sicher bist, das Token entfernen zu können, wenn dein Skript oder deine Anwendung nicht mehr verwendet wird.
GitHub zeigt dir den Token nur ein einziges Mal an, also kopiere und speicher ihn sorgfältig ab. Du kannst diese Funktion nun verwenden, um dich in deinem Skript zu authentifizieren, anstatt einen Benutzernamen und ein Passwort zu verwenden. Das ist angenehm, weil du den Umfang dessen, was du tun möchtest, einschränken kannst und das Token widerruflich ist.
Das hat auch den Vorteil, dass die Abfrage-Rate erhöht wird. Ohne Authentifizierung bist du auf 60 Anfragen pro Stunde beschränkt. Wenn du dich authentifizierst, kannst du bis zu 5.000 Anfragen pro Stunde stellen.
Also nutzen wir es, um einen Kommentar zu einem unserer Issues abzugeben.
Nehmen wir an, wir wollen einen Kommentar zu einem bestimmten Problem, Issue #6, abgeben.
Dazu müssen wir einen HTTP POST Request an repos/<user>/<repo>/issues/<num>/comments
mit dem Token stellen, den wir gerade als Autorisierungs-Header generiert haben.
$ curl -H "Content-Type: application/json" \
-H "Authorization: token TOKEN" \
--data '{"body":"A new comment, :+1:"}' \
https://api.github.com/repos/schacon/blink/issues/6/comments
{
"id": 58322100,
"html_url": "https://github.com/schacon/blink/issues/6#issuecomment-58322100",
...
"user": {
"login": "tonychacon",
"id": 7874698,
"avatar_url": "https://avatars.githubusercontent.com/u/7874698?v=2",
"type": "User",
},
"created_at": "2014-10-08T07:48:19Z",
"updated_at": "2014-10-08T07:48:19Z",
"body": "A new comment, :+1:"
}
Wenn du jetzt zu diesem Issue gehst, kannst du den Kommentar sehen, den wir gerade erfolgreich gepostet haben, wie in Kommentar, veröffentlicht von der GitHub API zu sehen ist.
Du kannst die API verwenden, um so ziemlich alles zu tun, was du auf der Website tun kannst – das Erstellen und Setzen von Meilensteinen, das Zuweisen von Personen zu Issues und Pull-Requests, das Erstellen und Ändern von Labels, auf Commit-Daten zugreifen, das Erstellen neuer Commits und Branches, das Öffnen, Schließen oder Mergen von Pull-Requests, das Erstellen und Bearbeiten von Teams, das Kommentieren von Code-Zeilen in einem Pull-Request, das Durchsuchen der Website und so weiter und so fort.
Den Status eines Pull-Requests ändern
Ein abschließendes Beispiel werden wir uns ansehen, da es wirklich praktisch ist, wenn du mit Pull-Requests arbeitest. Jeder Übertragung können ein oder mehrere Zustände zugeordnet sein. Es gibt eine API für das Hinzufügen und Abfragen dieser Stati.
Die meisten der Dienste für kontinuierliche Integration und Tests nutzen diese API, um auf Pushes zu reagieren, indem sie den Code testen, der gepusht wurde, und dann Bericht erstatten, wenn dieser Commit alle Tests bestanden hat. Du kannst damit auch überprüfen, ob die Commit-Nachricht korrekt formatiert ist, ob der Einreicher alle deine Contributions-Richtlinien befolgt hat, ob die Übertragung gültig signiert wurde – und vieles mehr.
Angenommen, du richtest einen Webhook in deinem Repository ein, der einen kleinen Webdienst aufruft, der in der Commit-Nachricht nach einer Zeichenkette Signed-off-by
sucht.
require 'httparty'
require 'sinatra'
require 'json'
post '/payload' do
push = JSON.parse(request.body.read) # parse the JSON
repo_name = push['repository']['full_name']
# look through each commit message
push["commits"].each do |commit|
# look for a Signed-off-by string
if /Signed-off-by/.match commit['message']
state = 'success'
description = 'Successfully signed off!'
else
state = 'failure'
description = 'No signoff found.'
end
# post status to GitHub
sha = commit["id"]
status_url = "https://api.github.com/repos/#{repo_name}/statuses/#{sha}"
status = {
"state" => state,
"description" => description,
"target_url" => "http://example.com/how-to-signoff",
"context" => "validate/signoff"
}
HTTParty.post(status_url,
:body => status.to_json,
:headers => {
'Content-Type' => 'application/json',
'User-Agent' => 'tonychacon/signoff',
'Authorization' => "token #{ENV['TOKEN']}" }
)
end
end
Das ist hoffentlich relativ einfach zu verstehen.
In diesem Web-Hook-Handler schauen wir uns jeden Commit an, der gerade gepusht wurde, wir suchen nach der Zeichenkette 'Signed-off-by' in der Commit-Nachricht und POST(en) via HTTP den Status an den API-Endpunkt /repos/<user>/<repo>/statuses/<commit_sha>
.
In diesem Fall kannst du einen Zustand ('success', 'failure', 'error'), eine Beschreibung des Geschehens, eine Ziel-URL, auf die der Benutzer für weitere Informationen zugreifen kann, und einen „Kontext“ senden, falls es mehrere Zustände für einen einzelnen Commit gibt. So kann beispielsweise ein Testdienst einen Status liefern und ein Validierungsdienst wie dieser ebenfalls einen Status – das Feld „Kontext“ zeigt, wie sie sich voneinander unterscheiden.
Wenn jemand einen neuen Pull-Request auf GitHub öffnet und dieser Hook eingerichtet ist, siehst du vielleicht etwas wie Commit-Status via API.
Du siehst nun ein kleines grünes Häkchen neben dem Commit, der in der Nachricht die Zeichenkette „Signed-off-by“ enthält und ein rotes Kreuz, wenn der Autor vergessen hat, den Commit zu signieren. Du kannst auch sehen, dass der Pull-Request den Status des letzten Commits auf dem Branch annimmt und dich warnt, falls es einen Fehler gibt. Das ist besonders nützlich, wenn du diese API für Prüfergebnisse verwendest, damit du nicht versehentlich etwas zusammenführst, bei dem der letzte Commit die Tests nicht besteht.
Octokit
Obwohl wir in diesen Beispielen fast alles durch curl
und einfache HTTP-Requests gemacht haben, gibt es mehrere Open-Source-Bibliotheken, die diese API auf eine eigenständigere Form verfügbar machen.
Zum Zeitpunkt des Entstehen dieses Buchs umfassen die unterstützten Sprachen Go, Objective-C, Ruby und .NET.
Besuche https://github.com/octokit für weitere Informationen zu diesen Themen, da sie einen großen Teil des HTTP-Codes für dich übernehmen.
Hoffentlich können dir diese Tools helfen, GitHub anzupassen und zu modifizieren, um sich so besser an deinem individuellen Workflows anzupassen. Eine vollständige Dokumentation der gesamten API sowie Anleitungen für häufige Aufgaben findest du unter https://developer.github.com.