Git LFS 개발 가이드

이 페이지에는 GitLab 팀 구성원을 위한 개발자 중심 정보가 들어 있습니다. 사용자 설명서는 Git Large File Storage를 참조하십시오.

컨트롤러 및 서비스

Repositories::GitHttpClientController

여기에 정의된 인증 방법은 다른 모든 LFS 컨트롤러에서 상속됩니다.

Repositories::LfsApiController

#batch

인증 후 batch 액션은 다운로드 및 업로드(풀, 푸시, 복제) 중에 Git LFS 클라이언트에 의해 호출되는 첫 번째 액션입니다.

Repositories::LfsStorageController

#upload_authorize

Workhorse에 파일을 저장할 경로를 포함하여 payload를 제공합니다. 원격 객체 저장소일 수 있습니다.

#upload_finalize

이미 Workhorse가 업로드한 파일에 대한 정보를 담고 있는 Workhorse로부터의 요청을 처리합니다 (이 미들웨어 참조). 그 후 gitlab은 다음을 수행할 수 있습니다:

  • LfsObject를 생성합니다.
  • 기존의 LfsObjectLfsObjectsProject를 사용하여 프로젝트에 연결합니다.

LfsObject 및 LfsObjectsProject

  • 주어진 oid(파일의 SHA256 체크섬) 및 파일 크기로 인해 파일당 하나의 LfsObject가 생성됩니다.
  • LfsObjectsProjectLfsObjectProject에 연결합니다. 이러한 객체들은 주어진 프로젝트에서 사용 중인 LFS 저장소의 양을 계산하는 데에도 사용됩니다. 자세한 내용은 ProjectStatistics#update_lfs_objects_size를 참조하십시오.

Repositories::LfsLocksApiController

LFS에 대한 잠금 API를 처리합니다. 대부분의 작업은 해당 서비스로 위임됩니다:

  • Lfs::LockFileService
  • Lfs::UnlockFileService
  • Lfs::LocksFinderService

이러한 서비스들은 LfsFileLock을 생성하고 삭제합니다.

#verify

  • 이 엔드포인트는 클라이언트가 푸시 중인 파일 중 다른 사용자에게 속한 잠금이 있는지 확인할 수 있게 하는 payload로 응답합니다.
  • 클라이언트 측 lfs.locksverify 구성을 설정하여 다른 사용자에게 속한 잠금이 있는 경우 클라이언트가 푸시를 중단하도록 할 수 있습니다.
  • 다른 사용자에게 속한 잠금의 존재는 또한 서버 측에서도 유효성이 검사됩니다.

예시 인증

sequenceDiagram autonumber alt HTTPS를 통해 Git 클라이언트-->>Git 클라이언트: 사용자가 제공한 자격 증명 else SSH를 통해 Git 클라이언트->>gitlab-shell: git-lfs-authenticate 활성화 gitlab-shell 활성화 GitLab Rails gitlab-shell->>GitLab Rails: POST /api/v4/internal/lfs_authenticate GitLab Rails-->>gitlab-shell: 만료 기한이 있는 토큰 비활성화 gitlab-shell 비활성화 GitLab Rails end
  1. 클라이언트는 자격 증명을 몇 가지 다른 방법으로 저장하도록 구성할 수 있습니다. 인증에 대한 Git LFS 문서를 참조하십시오.
  2. gitlab-lfs-authenticategitlab-shell에서 실행합니다. gitlab-lfs-authenticate에 관한 Git LFS 문서를 참조하십시오.
  3. gitlab-shell은 GitLab API에 요청을 수행합니다.
  4. 토큰으로 응답하여 이후 요청에 사용됩니다. 인증에 관한 Git LFS 문서를 참조하십시오.

예시 복제

sequenceDiagram Note right of Git 클라이언트: 전형적인 Git 복제가 먼저 발생합니다 Note right of Git 클라이언트: LFS에 대한 인증이 그 다음에 진행됩니다 활성화 GitLab Rails autonumber Git 클라이언트->>GitLab Rails: POST project/namespace/info/lfs/objects/batch GitLab Rails-->>Git 클라이언트: 객체를 포함한 페이로드 비활성화 GitLab Rails 각 payload의 object를 반복 Git 클라이언트->>GitLab Rails: GET project/namespace/gitlab-lfs/objects/:oid/ (<- 이 URL은 payload에서 온 것입니다) GitLab Rails->>Workhorse: SendfileUpload Workhorse-->> Git 클라이언트: 이진 데이터
  1. Git LFS는 인증 헤더로부터 파일 다운로드 권한을 요청합니다.
  2. gitlab은 객체 목록과 해당 위치를 응답합니다. LfsApiController#batch를 참조하십시오.
  3. Git LFS는 이전 응답의 href에 대해 각 파일에 대한 요청을 수행합니다. 기본 전송 모드로 다운로드가 처리되는 방법을 참조하십시오.
  4. 원격 객체 저장소가 활성화된 경우 gitlab은 원격 URL로 리디렉션합니다. SendFileUpload를 참조하십시오.

예제 푸시

sequenceDiagram Note right of Git client: 일반적으로 Git 푸시가 먼저 발생합니다. Note right of Git client: 다음으로 LFS의 인증이 이뤄집니다. autonumber activate GitLab Rails Git client ->> GitLab Rails: 프로젝트/네임스페이스/info/lfs/objects/batch 발송 GitLab Rails-->>Git client: 객체를 포함한 데이터 deactivate GitLab Rails loop payload에 있는 각 객체 수행 Git client->>Workhorse: 프로젝트/네임스페이스/gitlab-lfs/objects/:oid/:size에 PUT(요청 URL은 payload에서 가져옴) Workhorse->>GitLab Rails: 프로젝트/네임스페이스/gitlab-lfs/objects/:oid/:size/authorize에 PUT GitLab Rails-->>Workhorse: 업로드할 경로를 응답 Workhorse->>Workhorse: 업로드 Workhorse->>GitLab Rails: 프로젝트/네임스페이스/gitlab-lfs/objects/:oid/:size/finalize에 PUT end
  1. Git LFS는 파일을 업로드할 수 있는 권한을 요청합니다.
  2. gitlab은 객체 목록 및 그들을 찾기 위한 업로드로 응답합니다. 확인하세요 LfsApiController#batch.
  3. 각 파일에 대한 href를 위해 Git LFS는 이전 응답에서 요청합니다. 확인하세요 basic transfer mode로 처리되는 업로드 방법.
  4. gitlab은 Workhorse가 파일을 저장할 경로를 포함한 payload로 응답합니다. 원격 객체 저장소가 될 수 있습니다. 확인하세요 LfsStorageController#upload_authorize.
  5. Workhorse는 파일을 저장하는 작업을 수행합니다.
  6. Workhorse는 업로드된 파일에 대한 정보를 포함하여 gitlab에 요청합니다. gitlabLfsObject를 생성할 수 있습니다. 확인하세요 LfsStorageController#upload_finalize.

심층 탐구

2019년 4월, Francisco Javier López가 GitLab 팀 멤버만 참여 가능한 심층 탐구(https://gitlab.com/gitlab-org/create-stage/-/issues/1)를 주최하여 향후 이 코드베이스의 해당 부분에서 작업할 수 있는 사람들에게 도메인 특화 지식을 나누었습니다. YouTube에 대한 녹화Google 슬라이드PDF에서 확인할 수 있습니다. 이 심층 탐구는 GitLab 11.10 기준으로 정확했으며, 특정 세부 사항이 변경되었을 수 있지만 여전히 좋은 소개가 될 것입니다.

프로젝트 아카이브에 LFS 블롭 포함하기

다음 다이어그램은 GitLab이 프로젝트 아카이브에 대한 LFS 파일을 해결하는 방법을 보여줍니다:

sequenceDiagram autonumber Client->>+Workhorse: GET /group/project/-/archive/master.zip Workhorse->>+Rails: GET /group/project/-/archive/master.zip Rails->>+Workhorse: Gitlab-Workhorse-Send-Data git-archive Workhorse->>Gitaly: SendArchiveRequest Gitaly->>Git: git archive master Git->>Smudge: OID 12345 Smudge->>+Workhorse: GET /internal/api/v4/lfs?oid=12345&gl_repository=project-1234 Workhorse->>+Rails: GET /internal/api/v4/lfs?oid=12345&gl_repository=project-1234 Rails->>+Workhorse: Gitlab-Workhorse-Send-Data send-url Workhorse->>Smudge: <LFS data> Smudge->>Git: <LFS data> Git->>Gitaly: <streamed data> Gitaly->>Workhorse: <streamed data> Workhorse->>Client: master.zip
  1. 사용자가 UI에서 프로젝트 아카이브를 요청합니다.
  2. Workhorse가 이 요청을 Rails로 전달합니다.
  3. 사용자가 아카이브 다운로드 권한이 있는 경우, Rails는 Gitlab-Workhorse-Send-Data의 HTTP 헤더로 git-archive를 prefix로 붙인 base64로 인코딩된 JSON payload를 회신합니다. 이 payload에는 다시 한 번 base64로 인코딩된 SendArchiveRequest 이진 메시지가 포함됩니다.
  4. Workhorse는 Gitlab-Workhorse-Send-Data 페이로드를 디코딩합니다. 아카이브가 이미 아카이브 캐시에 있으면 해당 파일을 전송합니다. 그렇지 않으면, Workhorse는 SendArchiveRequest를 적절한 Gitaly 서버로 전송합니다.
  5. Gitaly 서버는 git archive <ref>를 호출하여 Git 아카이브를 동적으로 생성을 시작합니다. include_lfs_blobs 플래그가 활성화되면 Gitaly은 -c filter.lfs.smudge=/path/to/gitaly-lfs-smudge Git 옵션을 통해 사용자 정의 LFS smudge 필터를 활성화합니다.
  6. git.gitattributes 파일을 사용하여 가능한 LFS 포인터를 식별하면, git은 표준 입력을 통해 LFS 포인터를 제공하면 gitaly-lfs-smudge를 호출합니다. Gitaly은 LFS 개체 조회를 가능하게 하기 위해 환경 변수로 GL_PROJECT_PATHGL_INTERNAL_CONFIG를 제공합니다.
  7. 유효한 LFS 포인터가 디코딩되면, gitaly-lfs-smudge는 GitLab에서 LFS 개체를 다운로드하기 위해 Workhorse에 내부 API 호출을 수행합니다.
  8. Workhorse는 이 요청을 Rails로 전달합니다. LFS 개체가 프로젝트와 연관되어 있고, LFS 개체의 저장 위치(로컬 디스크의 경우) 또는 사전 서명된 URL(객체 저장소가 활성화된 경우)을 포함하는 ArchivePath를 Rails는 Gitlab-Workhorse-Send-Data HTTP 헤더와 prefix로 붙인 페이로드로 회신합니다.
  9. Workhorse는 파일을 검색하여 gitaly-lfs-smudge 프로세스로 보내고, 해당 내용을 표준 출력에 작성합니다.
  10. git은 이 출력을 읽고 Gitaly 프로세스로 다시 전송합니다.
  11. Gitaly은 데이터를 다시 Rails로 전송합니다.
  12. 아카이브 데이터가 클라이언트로 다시 전송됩니다.

7단계에서 gitaly-lfs-smudge 필터는 Rails가 아닌 Workhorse에 연락해야 하며, 그렇지 않으면 잘못된 LFS blob이 저장됩니다. 이를 지원하기 위해 GitLab 13.5에서 기본 Omnibus 구성을 변경하여 Gitaly가 Rails가 아닌 Workhorse에 연락하도록 한 사소한 영향을 갖습니다.

이 변경의 부작용 중 하나는 Gitaly(또는 gitaly-lfs-smudge)가 수행하는 내부 API 요청의 원래 요청의 상관 ID가 보존되지 않는다는 것입니다. 이러한 API 요청의 상관 ID는 해당 Workhorse issue가 해결될 때까지 임의의 값을 가집니다.

관련 주제