프로토콜
Pitmaster은 git 서버와 통신하기 위한 여러 네트워크 전송 프로토콜을 지원합니다. Smart HTTP이 기본 전송 방식이며, 더 폭넓은 호환성을 위한 추가 프로토콜도 제공됩니다.
Smart HTTP(기본)
권장 전송 방식입니다. HTTPS을 통해 작동하며 가장 널리 배포된 프로토콜입니다. 사용자 지정 헤더나 인증 정보를 위한 API은 없습니다. 인증 정보는 URL(https://user:token@host/repo.git)로만 전달할 수 있으며, PHP은 이를 Basic 인증으로 보냅니다. clone()은 인증 정보를 포함한 URL을 .git/config의 remote.origin.url로 저장합니다. 요청에는 PHP의 스트림 래퍼를 사용하므로 allow_url_fopen을 활성화해야 합니다.
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient(timeout: 30);
$discovery = $http->discoverRefs('https://github.com/user/repo.git');
자세한 내용은 Smart HTTP을 참조하세요.
프로토콜 v1
기존 smart HTTP 프로토콜입니다. 검색 중에 모든 ref를 전송하고 want/have/done 행으로 협상합니다.
use Pitmaster\Protocol\ProtocolV1;
프로토콜 v2
구조화된 명령(ls-refs, fetch)을 사용하는 최신 프로토콜입니다. 클라이언트가 ref 목록을 필터링할 수 있어 ref가 많은 저장소에서 더 효율적입니다.
clone() 및 fetch()은 항상 프로토콜 v1을 사용합니다. 프로토콜 v2은 SmartHttpClient::discoverRefsV2() 및 UploadPackClient::fetchV2()을 통한 smart HTTP에서 명시적으로 사용할 수 있습니다.
바보 HTTP
smart HTTP 프로토콜을 지원하지 않는 서버를 위한 대체 방식입니다. dumb 프로토콜은 일반 HTTP GET 요청으로 객체와 pack을 하나씩 가져옵니다.
use Pitmaster\Protocol\DumbHttpClient;
$client = new DumbHttpClient();
Dumb HTTP의 제한 사항:
- 협상이 없습니다(클라이언트가 모든 항목을 다운로드해야 함)
- 전송 중 델타 압축이 없습니다
- smart HTTP보다 훨씬 느립니다
- 일부 서버(GitHub, GitLab)는 이를 지원하지 않습니다
dumb 프로토콜은 다음을 가져옵니다:
GET /info/refs(일반 텍스트, pkt-line 없음)GET /HEAD(기본 브랜치)GET /objects/info/packs(사용 가능한 pack 목록)GET /objects/pack/pack-<hash>.pack및.idx(목록에 있는 각 pack과 해당 인덱스)GET /objects/<xx>/<rest>(ref 끝점에서 순회하는 개별 느슨한 객체)
5단계는 서버에 pack 목록이 없을 때만 실행됩니다. pack 목록이 있으면 서버에 느슨한 파일로만 존재하는 객체는 다운로드되지 않습니다(#18). dumb 클라이언트는 40자(SHA-1) 객체 ID만 허용합니다. smart HTTP 교환에 실패하면 clone() 및 fetch()는 dumb HTTP로 대체합니다.
SSH
SSH 전송 방식은 로드된 경우 ssh2 PHP 확장을 사용합니다. 그렇지 않으면 proc_open()를 통해 시스템 ssh 클라이언트를 시작합니다. 두 경우 모두 원격에서 git-upload-pack 또는 git-receive-pack을 실행합니다.
use Pitmaster\Protocol\SshClient;
$client = new SshClient();
SSH URL:
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git
확장이 필요하지 않습니다. 두 경로의 동작은 서로 다릅니다:
시스템 ssh 클라이언트(ssh2이 로드되지 않은 경우 사용). Pitmaster은 ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>을 실행하므로 인증 및 호스트 키 확인은 사용자의 SSH 설정과 에이전트를 따릅니다. 다음 환경 변수로 명령을 조정할 수 있습니다:
| 변수 | 효과 |
|---|---|
PITMASTER_SSH_COMMAND |
ssh 대신 실행할 실행 파일 |
PITMASTER_SSH_IDENTITY_FILE |
-i <file>으로 전달됩니다 |
PITMASTER_SSH_KNOWN_HOSTS |
-o UserKnownHostsFile=<file>로 전달됩니다 |
PITMASTER_SSH_STRICT_HOST_KEY_CHECKING |
-o StrictHostKeyChecking=<value>로 전달됩니다 |
이 경로는 프로세스를 시작하므로 ['processes' => false]로 연 핸들에서는 사용할 수 없습니다.
ssh2 확장(로드된 경우 항상 우선 사용). Pitmaster은 ~/.ssh/id_rsa로 인증을 시도하고, RSA 키가 있지만 거부된 경우 ~/.ssh/id_ed25519으로 시도하며, 그 외에는 SSH 에이전트를 사용합니다. PITMASTER_SSH_* 변수는 무시되며 이 경로에서는 서버의 호스트 키를 확인하지 않습니다(#22).
SSH 전송 방식은 git-upload-pack 또는 git-receive-pack를 원격 명령으로 실행하고, smart HTTP과 동일한 pkt-line 프로토콜을 사용해 SSH 채널로 통신합니다.
Git 프로토콜(TCP)
기본 git 프로토콜은 PHP 소켓을 사용해 TCP 포트 9418으로 통신합니다. GitProtocolClient은 ref 검색과 upload-pack(페치)를 지원하지만 푸시는 할 수 없습니다. clone() 및 fetch()는 git:// URL을 이 프로토콜로 전달하지 않으므로 클라이언트를 직접 사용하세요.
use Pitmaster\Protocol\GitProtocolClient;
$client = new GitProtocolClient();
Git URL:
git://github.com/user/repo.git
특징:
- 인증이 없습니다(실제로는 읽기 전용)
- 암호화되지 않습니다
- 대부분의 호스팅 제공업체에서 사용이 중단되었습니다
- smart HTTP과 동일한 pkt-line 프레이밍을 사용합니다
git 프로토콜은 초기 요청으로 서비스 이름과 저장소 경로를 전송한 다음, 표준 pkt-line ref 검색 및 pack 협상을 진행합니다.
번들
Git 번들은 ref 정보가 포함된 오프라인 pack 파일입니다. 네트워크 연결 없이 저장소 데이터를 전송할 수 있습니다.
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은 v2 및 v3 번들 헤더를 읽습니다. 번들을 가져오는 Repository 메서드는 없습니다. packData()를 .git/objects/pack/에 기록하고 PackIndexer::writeIndex()으로 인덱스를 만든 다음 직접 ref를 업데이트하세요.
번들 형식:
# v2 git bundle\n
-<prerequisite hash>\n (zero or more)
<hash> <refname>\n (one or more)
\n
<pack data> (standard pack file format)
번들은 다음과 같은 경우에 유용합니다:
- USB 드라이브를 통한 물리적 매체 전송
- 증분 백업
- 네트워크와 분리된 환경에서 클론에 데이터 미리 채우기
얕은 클론
Pitmaster은 제한된 깊이의 커밋 기록만 가져오는 얕은 클론을 지원합니다.
use Pitmaster\Protocol\ShallowClone;
Pitmaster::clone($url, $path, $depth) 또는 $repo->fetch($remote, $depth)에 깊이를 전달하세요. 요청에 shallow 기능과 deepen 행이 추가됩니다:
want <hash>
deepen <depth>
서버는 이력이 잘린 위치를 나타내는 shallow <hash> 줄을 응답으로 보냅니다. Pitmaster은 깊이만으로 얕은 경계를 계산하고, 계산 결과가 없으면 서버의 shallow 줄을 사용합니다. 결과는 .git/shallow에 저장됩니다. ShallowClone::readShallow(), writeShallow(), isShallow()은 해당 파일을 직접 사용합니다.
프로토콜 비교
| 프로토콜 | 인증 | 암호화 | 푸시 | 일반적인 용도 |
|---|---|---|---|---|
| Smart HTTP | URL의 인증 정보 | HTTPS | 예 | 기본 전송 방식 |
| Dumb HTTP | URL의 인증 정보 | HTTPS | 아니요 | 이전 버전 호환용 대체 방식 |
| SSH | SSH 키 또는 에이전트 | SSH | 예 | 비공개 저장소, CI |
| Git (TCP) | 없음 | 없음 | 아니요 | 읽기 전용 미러 |
| Bundle | 해당 없음 | 해당 없음 | 해당 없음 | 오프라인 전송 |
전송 방식 선택
Pitmaster::clone(), $repo->fetch(), $repo->push()은 URL에서 전송 방식을 선택합니다:
| URL 패턴 | 전송 방식 |
|---|---|
ssh://... |
SSH |
user@host:path |
SSH |
그 외 (https://..., http://...) |
Smart HTTP; clone 및 fetch는 dumb HTTP으로 대체 시도 |
git:// URL 및 로컬 경로는 이 메서드에서 지원되지 않습니다. smart HTTP 클라이언트로 전달되어 실패합니다. git://에는 GitProtocolClient를 직접 사용하세요. 사용자 이름과 포트를 모두 포함하는 HTTPS URL(https://user@host:8443/repo.git)는 현재 SSH URL(#17)로 잘못 인식됩니다.