InfoGrab DocsInfoGrab Docs

Git LFS 개발 가이드라인

요약

대용량 바이너리 파일을 처리하기 위해 Git Large File Storage(LFS)는 여러 구성 요소가 함께 작동합니다. 사용자 문서는 Git Large File Storage를 참조하세요. 다음은 Git LFS 사용 시 Git push 동작을 설명하는 상위 수준 다이어그램입니다:

대용량 바이너리 파일을 처리하기 위해 Git Large File Storage(LFS)는 여러 구성 요소가 함께 작동합니다. 이 가이드라인은 GitLab LFS 코드베이스를 작업할 때의 아키텍처와 코드 흐름을 설명합니다.

사용자 문서는 Git Large File Storage를 참조하세요.

다음은 Git LFS 사용 시 Git push 동작을 설명하는 상위 수준 다이어그램입니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart LR accTitle: Git pushes with Git LFS accDescr: Explains how the LFS hook routes new files depending on type

A[Git push] -->B[LFS hook] B -->C[Pointers] B -->D[Binary files] C -->E[Repository] D -->F[LFS server]

다음 다이어그램은 Git LFS 사용 시 Git pull 동작을 상위 수준에서 설명합니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart LR accTitle: Git pull using Git LFS accDescr: Explains how the LFS hook pulls LFS assets from the LFS server, and everything else from the Git repository

A[User] -->|initiates
git pull| B[Repository] B -->|Pull data and
LFS transfers| C[LFS hook] C -->|LFS pointers| D[LFS server] D -->|Binary
files| C C -->|Pull data and
binary files| A

컨트롤러 및 서비스#

Repositories::GitHttpClientController#

여기에 정의된 인증 메서드는 다른 모든 LFS 컨트롤러가 상속합니다.

Repositories::LfsApiController#

#batch#

인증이 완료되면 batch 액션은 다운로드 및 업로드(pull, push, clone 등) 시 Git LFS 클라이언트가 처음으로 호출하는 액션입니다.

Repositories::LfsStorageController#

#upload_authorize#

Workhorse에 페이로드를 제공하며, Workhorse가 파일을 저장할 경로를 포함합니다. 원격 오브젝트 스토리지일 수 있습니다.

#upload_finalize#

Workhorse가 이미 업로드한 파일에 대한 정보를 담은 Workhorse 요청을 처리합니다(이 미들웨어 참조). 이를 통해 gitlab은 다음 중 하나를 수행합니다:

  • LfsObject 생성.

  • LfsObjectsProject를 사용하여 기존 LfsObject를 프로젝트에 연결.

LfsObject 및 LfsObjectsProject#

  • 파일 oid(파일의 SHA256 체크섬)와 파일 크기가 동일한 파일에 대해 LfsObject는 하나만 생성됩니다.

  • LfsObjectsProjectLfsObjectProject와 연결합니다. 프로젝트를 통해 파일에 접근할 수 있는지 여부를 결정합니다.

  • 이 오브젝트들은 특정 프로젝트가 사용하는 LFS 스토리지 용량을 계산하는 데도 사용됩니다. 자세한 내용은 ProjectStatistics#update_lfs_objects_size를 참조하세요.

Repositories::LfsLocksApiController#

LFS의 잠금 API를 처리합니다. 주로 해당 서비스에 위임합니다:

  • Lfs::LockFileService

  • Lfs::UnlockFileService

  • Lfs::LocksFinderService

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

#verify#

  • 이 엔드포인트는 푸시 중인 파일 중 다른 사용자의 잠금이 걸린 파일이 있는지 클라이언트가 확인할 수 있는 페이로드를 응답합니다.

  • lfs.locksverify 클라이언트 설정을 사용하면, 다른 사용자의 잠금이 존재할 경우 클라이언트가 푸시를 중단하도록 설정할 수 있습니다.

  • 다른 사용자의 잠금 존재 여부는 서버 측에서도 검증됩니다.

인증 예시#

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram autonumber alt Over HTTPS Git client-->>Git client: user-supplied credentials else Over SSH Git client->>gitlab-shell: git-lfs-authenticate activate gitlab-shell activate GitLab Rails gitlab-shell->>GitLab Rails: POST /api/v4/internal/lfs_authenticate GitLab Rails-->>gitlab-shell: token with expiry deactivate gitlab-shell deactivate GitLab Rails end

클론 예시#

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram Note right of Git client: Typical Git clone things happen first Note right of Git client: Authentication for LFS comes next activate GitLab Rails autonumber Git client->>GitLab Rails: POST project/namespace/info/lfs/objects/batch GitLab Rails-->>Git client: payload with objects deactivate GitLab Rails loop each object in payload Git client->>GitLab Rails: GET project/namespace/gitlab-lfs/objects/:oid/ (<- This URL is from the payload) GitLab Rails->>Workhorse: SendfileUpload Workhorse-->> Git client: Binary data end

  • Git LFS가 인증 헤더를 포함하여 파일 다운로드를 요청합니다.

  • gitlab이 오브젝트 목록과 위치를 응답합니다. 자세한 내용은 LfsApiController#batch를 참조하세요.

  • Git LFS가 이전 응답의 href에 있는 각 파일에 대해 요청을 보냅니다. 기본 전송 모드에서 다운로드 처리 방식을 참조하세요.

  • 원격 오브젝트 스토리지가 활성화된 경우 gitlab이 원격 URL로 리다이렉트합니다. SendFileUpload를 참조하세요.

푸시 예시#

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram Note right of Git client: Typical Git push things happen first. Note right of Git client: Authentication for LFS comes next. autonumber activate GitLab Rails Git client ->> GitLab Rails: POST project/namespace/info/lfs/objects/batch GitLab Rails-->>Git client: payload with objects deactivate GitLab Rails loop each object in payload Git client->>Workhorse: PUT project/namespace/gitlab-lfs/objects/:oid/:size (URL is from payload) Workhorse->>GitLab Rails: PUT project/namespace/gitlab-lfs/objects/:oid/:size/authorize GitLab Rails-->>Workhorse: response with where path to upload Workhorse->>Workhorse: Upload Workhorse->>GitLab Rails: PUT project/namespace/gitlab-lfs/objects/:oid/:size/finalize end

  • Git LFS가 파일 업로드를 요청합니다.

  • gitlab이 오브젝트 목록과 업로드 위치를 응답합니다. LfsApiController#batch를 참조하세요.

  • Git LFS가 이전 응답의 href에 있는 각 파일에 대해 요청을 보냅니다. 기본 전송 모드에서 업로드 처리 방식을 참조하세요.

  • gitlab이 Workhorse가 파일을 저장할 경로를 포함한 페이로드를 응답합니다. 원격 오브젝트 스토리지일 수 있습니다. LfsStorageController#upload_authorize를 참조하세요.

  • Workhorse가 파일 저장 작업을 수행합니다.

  • Workhorse가 업로드된 파일 정보를 gitlab에 요청하여 gitlabLfsObject를 생성할 수 있도록 합니다. LfsStorageController#upload_finalize를 참조하세요.

프로젝트 아카이브에 LFS blob 포함#

다음 다이어그램은 GitLab이 프로젝트 아카이브의 LFS 파일을 처리하는 방식을 설명합니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% 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: Smudge->>Git: Git->>Gitaly: Gitaly->>Workhorse: Workhorse->>Client: master.zip

  • 사용자가 UI에서 프로젝트 아카이브를 요청합니다.

  • Workhorse가 이 요청을 Rails에 전달합니다.

  • 사용자에게 아카이브 다운로드 권한이 있으면, Rails는 git-archive를 접두사로 붙인 base64 인코딩된 JSON 페이로드와 함께 Gitlab-Workhorse-Send-Data HTTP 헤더로 응답합니다. 이 페이로드에는 다시 base64로 인코딩된 SendArchiveRequest 바이너리 메시지가 포함됩니다.

  • Workhorse가 Gitlab-Workhorse-Send-Data 페이로드를 디코딩합니다. 아카이브가 이미 아카이브 캐시에 존재하면 Workhorse가 해당 파일을 전송합니다. 그렇지 않으면 Workhorse가 적절한 Gitaly 서버에 SendArchiveRequest를 전송합니다.

  • Gitaly 서버가 git archive <ref>를 호출하여 Git 아카이브를 실시간으로 생성하기 시작합니다. include_lfs_blobs 플래그가 활성화된 경우, Gitaly는 -c filter.lfs.smudge=/path/to/gitaly-lfs-smudge Git 옵션을 사용하여 커스텀 LFS smudge 필터를 활성화합니다.

  • git.gitattributes 파일을 사용하여 LFS 포인터를 식별하면, gitgitaly-lfs-smudge를 호출하고 표준 입력을 통해 LFS 포인터를 제공합니다. Gitaly는 LFS 오브젝트 조회를 가능하게 하기 위해 환경 변수로 GL_PROJECT_PATHGL_INTERNAL_CONFIG를 제공합니다.

  • 유효한 LFS 포인터가 디코딩되면, gitaly-lfs-smudge가 Workhorse에 내부 API 호출을 하여 GitLab에서 LFS 오브젝트를 다운로드합니다.

  • Workhorse가 이 요청을 Rails에 전달합니다. LFS 오브젝트가 존재하고 프로젝트와 연결되어 있으면, Rails는 로컬 디스크의 경우 LFS 오브젝트가 저장된 경로를, 오브젝트 스토리지가 활성화된 경우 사전 서명된 URL을 send-url을 접두사로 붙인 페이로드와 함께 Gitlab-Workhorse-Send-Data HTTP 헤더로 전송하여 ArchivePath를 보냅니다.

  • Workhorse가 파일을 가져와 gitaly-lfs-smudge 프로세스에 전송하면, 해당 프로세스가 표준 출력에 내용을 씁니다.

  • git이 이 출력을 읽어 Gitaly 프로세스에 다시 전송합니다.

  • Gitaly가 데이터를 Rails에 다시 전송합니다.

  • 아카이브 데이터가 클라이언트에 다시 전송됩니다.

7단계에서 gitaly-lfs-smudge 필터는 Rails가 아닌 Workhorse와 통신해야 합니다. 그렇지 않으면 잘못된 LFS blob이 저장됩니다. 이를 지원하기 위해 GitLab은 Gitaly가 Rails 대신 Workhorse와 통신하도록 기본 Linux 패키지 구성을 변경했습니다.

이 변경으로 인한 한 가지 부작용: 원래 요청의 correlation ID가 8단계에서 이루어진 것과 같이 Gitaly(또는 gitaly-lfs-smudge)에 의한 내부 API 요청에 보존되지 않습니다. 이 Workhorse 이슈가 해결될 때까지 해당 API 요청의 correlation ID는 임의 값입니다.

관련 주제#

Git LFS 개발 가이드라인

GitLab v19.1
원문 보기
요약

대용량 바이너리 파일을 처리하기 위해 Git Large File Storage(LFS)는 여러 구성 요소가 함께 작동합니다. 사용자 문서는 Git Large File Storage를 참조하세요. 다음은 Git LFS 사용 시 Git push 동작을 설명하는 상위 수준 다이어그램입니다:

대용량 바이너리 파일을 처리하기 위해 Git Large File Storage(LFS)는 여러 구성 요소가 함께 작동합니다. 이 가이드라인은 GitLab LFS 코드베이스를 작업할 때의 아키텍처와 코드 흐름을 설명합니다.

사용자 문서는 Git Large File Storage를 참조하세요.

다음은 Git LFS 사용 시 Git push 동작을 설명하는 상위 수준 다이어그램입니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart LR accTitle: Git pushes with Git LFS accDescr: Explains how the LFS hook routes new files depending on type

A[Git push] -->B[LFS hook] B -->C[Pointers] B -->D[Binary files] C -->E[Repository] D -->F[LFS server]

다음 다이어그램은 Git LFS 사용 시 Git pull 동작을 상위 수준에서 설명합니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart LR accTitle: Git pull using Git LFS accDescr: Explains how the LFS hook pulls LFS assets from the LFS server, and everything else from the Git repository

A[User] -->|initiates
git pull| B[Repository] B -->|Pull data and
LFS transfers| C[LFS hook] C -->|LFS pointers| D[LFS server] D -->|Binary
files| C C -->|Pull data and
binary files| A

컨트롤러 및 서비스#

Repositories::GitHttpClientController#

여기에 정의된 인증 메서드는 다른 모든 LFS 컨트롤러가 상속합니다.

Repositories::LfsApiController#

#batch#

인증이 완료되면 batch 액션은 다운로드 및 업로드(pull, push, clone 등) 시 Git LFS 클라이언트가 처음으로 호출하는 액션입니다.

Repositories::LfsStorageController#

#upload_authorize#

Workhorse에 페이로드를 제공하며, Workhorse가 파일을 저장할 경로를 포함합니다. 원격 오브젝트 스토리지일 수 있습니다.

#upload_finalize#

Workhorse가 이미 업로드한 파일에 대한 정보를 담은 Workhorse 요청을 처리합니다(이 미들웨어 참조). 이를 통해 gitlab은 다음 중 하나를 수행합니다:

  • LfsObject 생성.

  • LfsObjectsProject를 사용하여 기존 LfsObject를 프로젝트에 연결.

LfsObject 및 LfsObjectsProject#

  • 파일 oid(파일의 SHA256 체크섬)와 파일 크기가 동일한 파일에 대해 LfsObject는 하나만 생성됩니다.

  • LfsObjectsProjectLfsObjectProject와 연결합니다. 프로젝트를 통해 파일에 접근할 수 있는지 여부를 결정합니다.

  • 이 오브젝트들은 특정 프로젝트가 사용하는 LFS 스토리지 용량을 계산하는 데도 사용됩니다. 자세한 내용은 ProjectStatistics#update_lfs_objects_size를 참조하세요.

Repositories::LfsLocksApiController#

LFS의 잠금 API를 처리합니다. 주로 해당 서비스에 위임합니다:

  • Lfs::LockFileService

  • Lfs::UnlockFileService

  • Lfs::LocksFinderService

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

#verify#

  • 이 엔드포인트는 푸시 중인 파일 중 다른 사용자의 잠금이 걸린 파일이 있는지 클라이언트가 확인할 수 있는 페이로드를 응답합니다.

  • lfs.locksverify 클라이언트 설정을 사용하면, 다른 사용자의 잠금이 존재할 경우 클라이언트가 푸시를 중단하도록 설정할 수 있습니다.

  • 다른 사용자의 잠금 존재 여부는 서버 측에서도 검증됩니다.

인증 예시#

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram autonumber alt Over HTTPS Git client-->>Git client: user-supplied credentials else Over SSH Git client->>gitlab-shell: git-lfs-authenticate activate gitlab-shell activate GitLab Rails gitlab-shell->>GitLab Rails: POST /api/v4/internal/lfs_authenticate GitLab Rails-->>gitlab-shell: token with expiry deactivate gitlab-shell deactivate GitLab Rails end

클론 예시#

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram Note right of Git client: Typical Git clone things happen first Note right of Git client: Authentication for LFS comes next activate GitLab Rails autonumber Git client->>GitLab Rails: POST project/namespace/info/lfs/objects/batch GitLab Rails-->>Git client: payload with objects deactivate GitLab Rails loop each object in payload Git client->>GitLab Rails: GET project/namespace/gitlab-lfs/objects/:oid/ (<- This URL is from the payload) GitLab Rails->>Workhorse: SendfileUpload Workhorse-->> Git client: Binary data end

  • Git LFS가 인증 헤더를 포함하여 파일 다운로드를 요청합니다.

  • gitlab이 오브젝트 목록과 위치를 응답합니다. 자세한 내용은 LfsApiController#batch를 참조하세요.

  • Git LFS가 이전 응답의 href에 있는 각 파일에 대해 요청을 보냅니다. 기본 전송 모드에서 다운로드 처리 방식을 참조하세요.

  • 원격 오브젝트 스토리지가 활성화된 경우 gitlab이 원격 URL로 리다이렉트합니다. SendFileUpload를 참조하세요.

푸시 예시#

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram Note right of Git client: Typical Git push things happen first. Note right of Git client: Authentication for LFS comes next. autonumber activate GitLab Rails Git client ->> GitLab Rails: POST project/namespace/info/lfs/objects/batch GitLab Rails-->>Git client: payload with objects deactivate GitLab Rails loop each object in payload Git client->>Workhorse: PUT project/namespace/gitlab-lfs/objects/:oid/:size (URL is from payload) Workhorse->>GitLab Rails: PUT project/namespace/gitlab-lfs/objects/:oid/:size/authorize GitLab Rails-->>Workhorse: response with where path to upload Workhorse->>Workhorse: Upload Workhorse->>GitLab Rails: PUT project/namespace/gitlab-lfs/objects/:oid/:size/finalize end

  • Git LFS가 파일 업로드를 요청합니다.

  • gitlab이 오브젝트 목록과 업로드 위치를 응답합니다. LfsApiController#batch를 참조하세요.

  • Git LFS가 이전 응답의 href에 있는 각 파일에 대해 요청을 보냅니다. 기본 전송 모드에서 업로드 처리 방식을 참조하세요.

  • gitlab이 Workhorse가 파일을 저장할 경로를 포함한 페이로드를 응답합니다. 원격 오브젝트 스토리지일 수 있습니다. LfsStorageController#upload_authorize를 참조하세요.

  • Workhorse가 파일 저장 작업을 수행합니다.

  • Workhorse가 업로드된 파일 정보를 gitlab에 요청하여 gitlabLfsObject를 생성할 수 있도록 합니다. LfsStorageController#upload_finalize를 참조하세요.

프로젝트 아카이브에 LFS blob 포함#

다음 다이어그램은 GitLab이 프로젝트 아카이브의 LFS 파일을 처리하는 방식을 설명합니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% 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: Smudge->>Git: Git->>Gitaly: Gitaly->>Workhorse: Workhorse->>Client: master.zip

  • 사용자가 UI에서 프로젝트 아카이브를 요청합니다.

  • Workhorse가 이 요청을 Rails에 전달합니다.

  • 사용자에게 아카이브 다운로드 권한이 있으면, Rails는 git-archive를 접두사로 붙인 base64 인코딩된 JSON 페이로드와 함께 Gitlab-Workhorse-Send-Data HTTP 헤더로 응답합니다. 이 페이로드에는 다시 base64로 인코딩된 SendArchiveRequest 바이너리 메시지가 포함됩니다.

  • Workhorse가 Gitlab-Workhorse-Send-Data 페이로드를 디코딩합니다. 아카이브가 이미 아카이브 캐시에 존재하면 Workhorse가 해당 파일을 전송합니다. 그렇지 않으면 Workhorse가 적절한 Gitaly 서버에 SendArchiveRequest를 전송합니다.

  • Gitaly 서버가 git archive <ref>를 호출하여 Git 아카이브를 실시간으로 생성하기 시작합니다. include_lfs_blobs 플래그가 활성화된 경우, Gitaly는 -c filter.lfs.smudge=/path/to/gitaly-lfs-smudge Git 옵션을 사용하여 커스텀 LFS smudge 필터를 활성화합니다.

  • git.gitattributes 파일을 사용하여 LFS 포인터를 식별하면, gitgitaly-lfs-smudge를 호출하고 표준 입력을 통해 LFS 포인터를 제공합니다. Gitaly는 LFS 오브젝트 조회를 가능하게 하기 위해 환경 변수로 GL_PROJECT_PATHGL_INTERNAL_CONFIG를 제공합니다.

  • 유효한 LFS 포인터가 디코딩되면, gitaly-lfs-smudge가 Workhorse에 내부 API 호출을 하여 GitLab에서 LFS 오브젝트를 다운로드합니다.

  • Workhorse가 이 요청을 Rails에 전달합니다. LFS 오브젝트가 존재하고 프로젝트와 연결되어 있으면, Rails는 로컬 디스크의 경우 LFS 오브젝트가 저장된 경로를, 오브젝트 스토리지가 활성화된 경우 사전 서명된 URL을 send-url을 접두사로 붙인 페이로드와 함께 Gitlab-Workhorse-Send-Data HTTP 헤더로 전송하여 ArchivePath를 보냅니다.

  • Workhorse가 파일을 가져와 gitaly-lfs-smudge 프로세스에 전송하면, 해당 프로세스가 표준 출력에 내용을 씁니다.

  • git이 이 출력을 읽어 Gitaly 프로세스에 다시 전송합니다.

  • Gitaly가 데이터를 Rails에 다시 전송합니다.

  • 아카이브 데이터가 클라이언트에 다시 전송됩니다.

7단계에서 gitaly-lfs-smudge 필터는 Rails가 아닌 Workhorse와 통신해야 합니다. 그렇지 않으면 잘못된 LFS blob이 저장됩니다. 이를 지원하기 위해 GitLab은 Gitaly가 Rails 대신 Workhorse와 통신하도록 기본 Linux 패키지 구성을 변경했습니다.

이 변경으로 인한 한 가지 부작용: 원래 요청의 correlation ID가 8단계에서 이루어진 것과 같이 Gitaly(또는 gitaly-lfs-smudge)에 의한 내부 API 요청에 보존되지 않습니다. 이 Workhorse 이슈가 해결될 때까지 해당 API 요청의 correlation ID는 임의 값입니다.

관련 주제#