Zum Inhalt springen

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.

PHP
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.

PHP
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.

PHP
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:

  1. GET /info/refs (Klartext, kein pkt-line)
  2. GET /HEAD (Standard-Branch)
  3. GET /objects/info/packs (Liste verfügbarer Packs)
  4. GET /objects/pack/pack-<hash>.pack und .idx (jedes aufgeführte Pack und sein Index)
  5. 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.

PHP
use Pitmaster\Protocol\SshClient;

$client = new SshClient();

SSH-URLs:

Code
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.

PHP
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();

Git-URLs:

Code
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.

PHP
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:

Code
# 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.

PHP
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:

Code
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).