Protokolle
Pitmaster unterstützt mehrere Netzwerktransportprotokolle für die Kommunikation mit git-Servern. Smart-HTTP ist der primäre Transport. Weitere Protokolle sorgen für umfassendere Kompatibilität.
Smart HTTP (primär)
Der empfohlene Transport. Funktioniert über HTTPS und ist das am weitesten verbreitete Protokoll. Es gibt kein API für benutzerdefinierte Header oder Zugangsdaten. Zugangsdaten lassen sich nur in URL (https://user:token@host/repo.git) übergeben, die PHP als Basic-Authentifizierung sendet. clone() speichert das URL einschließlich der Zugangsdaten als remote.origin.url in .git/config. Anfragen verwenden die Stream-Wrapper von PHP, daher muss allow_url_fopen aktiviert sein.
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient(timeout: 30);
$discovery = $http->discoverRefs('https://github.com/user/repo.git');
Ausführliche Informationen findest du unter Smart HTTP.
Protokoll v1
Das traditionelle Smart-HTTP-Protokoll. Bei der Ermittlung werden alle Refs gesendet; die Aushandlung nutzt Want-, Have- und Done-Zeilen.
use Pitmaster\Protocol\ProtocolV1;
Protokoll v2
Das neuere Protokoll mit strukturierten Befehlen (ls-refs, fetch). Effizienter bei Repositories mit vielen Refs, da der Client die Ref-Liste filtern kann.
clone() und fetch() verwenden immer Protokoll v1. Protokoll v2 ist explizit über Smart HTTP mit SmartHttpClient::discoverRefsV2() und UploadPackClient::fetchV2() verfügbar.
Dumb HTTP
Fallback für Server, die das Smart-HTTP-Protokoll nicht unterstützen. Das Dumb-Protokoll ruft Objekte und Packs einzeln über einfache HTTP-GET-Anfragen ab.
use Pitmaster\Protocol\DumbHttpClient;
$client = new DumbHttpClient();
Einschränkungen von Dumb HTTP:
- Keine Aushandlung (der Client muss alles herunterladen)
- Keine Delta-Komprimierung während der Übertragung
- Deutlich langsamer als Smart HTTP
- Einige Server (GitHub, GitLab) unterstützen es nicht
Das Dumb-Protokoll ruft Folgendes ab:
GET /info/refs(Klartext, kein pkt-line)GET /HEAD(Standard-Branch)GET /objects/info/packs(Liste verfügbarer Packs)GET /objects/pack/pack-<hash>.packund.idx(jedes aufgeführte Pack und sein Index)GET /objects/<xx>/<rest>(einzelne lose Objekte, ausgehend von den Ref-Tips durchsucht)
Schritt 5 wird nur ausgeführt, wenn der Server keine Packs aufführt. Listet er Packs auf, werden Objekte, die auf dem Server nur als lose Dateien vorliegen, nicht heruntergeladen (#18). Der Dumb-Client akzeptiert nur 40-stellige Objekt-IDs (SHA-1). clone() und fetch() greifen auf Dumb HTTP zurück, wenn der Smart-HTTP-Austausch fehlschlägt.
SSH
Der SSH-Transport verwendet die Erweiterung ssh2 PHP, wenn sie geladen ist. Andernfalls startet er den System-ssh-Client über proc_open(). In beiden Fällen wird auf dem Remote git-upload-pack oder git-receive-pack ausgeführt.
use Pitmaster\Protocol\SshClient;
$client = new SshClient();
SSH-URLs:
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git
Eine Erweiterung ist nicht erforderlich. Die beiden Wege verhalten sich unterschiedlich:
System-ssh-Client (wird verwendet, wenn ssh2 nicht geladen ist). Pitmaster führt ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command> aus. Authentifizierung und Host-Key-Prüfung richten sich daher nach deiner SSH-Konfiguration und deinem Agent. Mit diesen Umgebungsvariablen lässt sich der Befehl anpassen:
| Variable | Wirkung |
|---|---|
PITMASTER_SSH_COMMAND |
Auszuführbare Datei anstelle von ssh |
PITMASTER_SSH_IDENTITY_FILE |
Wird als -i <file> übergeben |
PITMASTER_SSH_KNOWN_HOSTS |
Wird als -o UserKnownHostsFile=<file> übergeben |
PITMASTER_SSH_STRICT_HOST_KEY_CHECKING |
Wird als -o StrictHostKeyChecking=<value> übergeben |
Dieser Weg startet einen Prozess und ist daher bei Handles, die mit ['processes' => false] geöffnet wurden, nicht verfügbar.
ssh2-Erweiterung (wird bei Verfügbarkeit immer bevorzugt). Pitmaster authentifiziert sich mit ~/.ssh/id_rsa, dann mit ~/.ssh/id_ed25519, falls der RSA-Schlüssel vorhanden, aber abgelehnt wird, und andernfalls über den SSH-Agent. Die Variablen PITMASTER_SSH_* werden ignoriert und der Host-Key des Servers wird bei diesem Weg nicht geprüft (#22).
Der SSH-Transport führt git-upload-pack oder git-receive-pack als Remote-Befehl aus und kommuniziert über den SSH-Kanal mit demselben pkt-line-Protokoll wie Smart HTTP.
Git-Protokoll (TCP)
Das native git-Protokoll kommuniziert über TCP-Port 9418 mit PHP-Sockets. GitProtocolClient implementiert die Ref-Erkennung und upload-pack (Abruf), kann aber keine Daten übertragen. clone() und fetch() leiten git://-URLs nicht dorthin weiter; verwende daher direkt den Client.
use Pitmaster\Protocol\GitProtocolClient;
$client = new GitProtocolClient();
Git-URLs:
git://github.com/user/repo.git
Eigenschaften:
- Keine Authentifizierung (in der Praxis schreibgeschützt)
- Keine Verschlüsselung
- Von den meisten Hosting-Anbietern als veraltet eingestuft
- Verwendet dasselbe pkt-line-Framing wie Smart HTTP
Das Protokoll git sendet den Dienstnamen und den Repository-Pfad als erste Anfrage. Danach folgt die standardmäßige Ref-Erkennung und Pack-Aushandlung im pkt-line-Format.
Bundles
Git-Bundles sind Offline-Packdateien mit Ref-Informationen. Sie ermöglichen die Übertragung von Repository-Daten ohne Netzwerkverbindung.
use Pitmaster\Protocol\Bundle;
// Read a bundle file
$bundle = Bundle::open('/path/to/repo.bundle');
$refs = $bundle->refs();
$packData = $bundle->packData();
$prerequisites = $bundle->prerequisites();
// Create one
$bundle = Bundle::create(['refs/heads/main' => $commitId], $packData);
$bundle->writeTo('/path/to/out.bundle');
Pitmaster liest Bundle-Header der Versionen v2 und v3. Eine Repository-Methode zum Importieren eines Bundles gibt es nicht: Schreibe packData() nach .git/objects/pack/, erstelle den Index mit PackIndexer::writeIndex() und aktualisiere die Refs selbst.
Bundle-Format:
# v2 git bundle\n
-<prerequisite hash>\n (zero or more)
<hash> <refname>\n (one or more)
\n
<pack data> (standard pack file format)
Bundles eignen sich für:
- Übertragungen per USB-Laufwerk
- Inkrementelle Backups
- Das Bereitstellen von Klonen in abgeschotteten Umgebungen
Shallow-Klone
Pitmaster unterstützt Shallow-Klone, bei denen nur eine begrenzte Tiefe des Commit-Verlaufs abgerufen wird.
use Pitmaster\Protocol\ShallowClone;
Übergib Pitmaster::clone($url, $path, $depth) oder $repo->fetch($remote, $depth) eine Tiefe. Die Anfrage fügt die Fähigkeit shallow und eine deepen-Zeile hinzu:
want <hash>
deepen <depth>
Der Server antwortet mit shallow <hash>-Zeilen, die angeben, wo der Verlauf abgeschnitten wurde. Pitmaster berechnet die flache Grenze anhand der Tiefe selbst und verwendet die shallow-Zeilen des Servers, wenn diese Berechnung nichts ergibt. Das Ergebnis wird in .git/shallow gespeichert. ShallowClone::readShallow(), writeShallow() und isShallow() arbeiten direkt mit dieser Datei.
Protokollvergleich
| Protokoll | Authentifizierung | Verschlüsselung | Übertragung | Typische Verwendung |
|---|---|---|---|---|
| Smart HTTP | Zugangsdaten in URL | HTTPS | Ja | Primärer Transport |
| Dumb HTTP | Zugangsdaten in URL | HTTPS | Nein | Legacy-Fallback |
| SSH | SSH-Schlüssel oder Agent | SSH | Ja | Private Repositories, CI |
| Git (TCP) | Keine | Keine | Nein | Spiegel mit Lesezugriff |
| Bundle | Nicht zutreffend | Nicht zutreffend | Nicht zutreffend | Offline-Übertragung |
Transportauswahl
Pitmaster::clone(), $repo->fetch() und $repo->push() wählen den Transport anhand von URL aus:
| Muster von URL | Transport |
|---|---|
ssh://... |
SSH |
user@host:path |
SSH |
Alles andere (https://..., http://...) |
Smart HTTP; Klonen und Abrufen greifen auf Dumb HTTP zurück |
git://-URLs und lokale Pfade werden von diesen Methoden nicht unterstützt: Sie werden an den Smart-HTTP-Client weitergegeben und schlagen fehl. Verwende für git:// direkt GitProtocolClient. Ein HTTPS URL, das sowohl einen Benutzer als auch einen Port enthält (https://user@host:8443/repo.git), wird derzeit fälschlich als SSH-URL erkannt (#17).