Git LFS 개발 가이드라인

이 페이지는 GitLab 팀 구성원을 위한 개발자 중심 정보입니다. 사용자 문서는 Git Large File Storage를 참조하세요.

이 다이어그램은 Git LFS를 사용할 때 Git push에 대한 고수준 설명입니다:

Git LFS로 Git 푸시LFS 훅이 파일 유형에 따라 새 파일을 라우팅하는 방법 설명
Git 푸시
LFS 훅
포인터
이진 파일
저장소
LFS 서버

이 다이어그램은 Git LFS를 사용할 때 Git pull에 대한 고수준 설명입니다:

Git LFS를 사용한 Git 풀LFS 훅이 LFS 서버에서 LFS 자산을 가져오고 Git 저장소에서 모든 다른 것을 가져오는 방법 설명
시작
git pull
데이터 가져오기 및
LFS 전송
LFS 포인터
이진
파일
데이터 가져오기 및
이진 파일
사용자
저장소
LFS 훅
LFS 서버

컨트롤러 및 서비스

Repositories::GitHttpClientController

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

Repositories::LfsApiController

#batch

인증 후 batch 액션은 Git LFS 클라이언트가 다운로드 및 업로드(예: pull, push, clone) 중에 호출하는 첫 번째 액션입니다.

Repositories::LfsStorageController

#upload_authorize

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

#upload_finalize

Workhorse가 이미 업로드한 파일에 대한 정보를 포함하는 요청을 처리합니다(자세한 내용은 이 미들웨어를 참조하세요) 그래야 gitlab가 할 수 있습니다:

  • LfsObject를 생성합니다.
  • 기존 LfsObject를 프로젝트와 연결시키는 LfsObjectsProject를 생성합니다.

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 구성이 설정될 수 있으며, 이는 클라이언트가 다른 사용자에게 속한 잠금이 존재하면 푸시를 중단하도록 합니다.
  • 다른 사용자에게 속한 잠금의 존재는 서버 측에서도 검증됩니다.

예제 인증

GitLab Railsgitlab-shellGit 클라이언트GitLab Railsgitlab-shellGit 클라이언트alt[HTTPS를 통해][SSH를 통해]사용자 제공 자격 증명1git-lfs-authenticate2POST /api/v4/internal/lfs_authenticate3만료된 토큰4
  1. 클라이언트는 자격 증명을 저장할 수 있는 몇 가지 방법으로 구성할 수 있습니다.

    인증에 대한 Git LFS 문서를 참조하세요.

  2. gitlab-lfs-authenticategitlab-shell에서 실행합니다.

    gitlab-lfs-authenticate에 관한 Git LFS 문서를 참조하세요.

  3. gitlab-shell은 GitLab API에 요청을 합니다.

  4. 셸에 토큰으로 응답하는 것은 후속 요청에 사용됩니다.

    인증에 관한 Git LFS 문서를 참조하세요.

예제 클론

Syntax error in textmermaid version 10.9.3
  1. Git LFS는 인증 헤더가 있는 파일 다운로드 능력을 요청합니다.

  2. gitlab은 객체 목록과 객체를 찾을 위치를 응답합니다.

    LfsApiController#batch 를 참조하세요.

  3. Git LFS는 이전 응답의 href에 대해 각 파일 요청을 합니다.

    기본 전송 모드로 다운로드를 처리하는 방법을 참조하세요.

  4. gitlab은 원격 객체 저장소가 활성화된 경우 원격 URL로 리디렉션합니다.

    SendFileUpload를 참조하세요.

예시 푸시

WorkhorseGitLab RailsGit clientWorkhorseGitLab RailsGit client일반적인 Git 푸시 작업이 먼저 발생합니다.LFS에 대한 인증이 그 다음입니다.loop[페이로드의 각 객체]POST project/namespace/info/lfs/objects/batch1객체가 포함된 페이로드2PUT project/namespace/gitlab-lfs/objects/:oid/:size (URL은 페이로드로부터)3PUT project/namespace/gitlab-lfs/objects/:oid/:size/authorize4업로드할 경로에 대한 응답5업로드6PUT project/namespace/gitlab-lfs/objects/:oid/:size/finalize7
  1. Git LFS는 파일 업로드를 요청합니다.
  2. gitlab은 객체 목록과 그것을 찾기 위한 업로드를 응답합니다. 참조: LfsApiController#batch.
  3. Git LFS는 이전 응답의 href에 대한 각 파일 요청을 합니다. 참조: 기본 전송 모드로 uploads가 처리되는 방법.
  4. gitlab은 Workhorse가 파일을 저장할 경로를 포함한 페이로드로 응답합니다. 원격 객체 저장소가 될 수 있습니다. 참조: LfsStorageController#upload_authorize.
  5. Workhorse는 파일 저장 작업을 수행합니다.
  6. Workhorse는 업로드된 파일에 대한 정보를 gitlab에 요청하여 gitlabLfsObject를 생성할 수 있도록 합니다. 참조: LfsStorageController#upload_finalize.

심층 분석

2019년 4월, Francisco Javier López는 GitLab Git LFS 구현에 대한 심층 분석을 주최했습니다. 이 분석은 이 코드베이스의 일부에서 작업할 수 있는 모든 사람들과 도메인 특정 지식을 공유하기 위한 것입니다. YouTube에서 녹화된 영상Google SlidesPDF에서 슬라이드를 찾을 수 있습니다. 이 심층 분석은 GitLab 11.10 기준으로 정확했으며, 특정 세부 사항은 변경되었을 수 있지만, 여전히 좋은 소개로 작용합니다.

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

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

SmudgeGitGitalyRailsWorkhorseClientSmudgeGitGitalyRailsWorkhorseClientGET /group/project/-/archive/master.zip1GET /group/project/-/archive/master.zip2Gitlab-Workhorse-Send-Data git-archive3SendArchiveRequest4git archive master5OID 123456GET /internal/api/v4/lfs?oid=12345&gl_repository=project-12347GET /internal/api/v4/lfs?oid=12345&gl_repository=project-12348Gitlab-Workhorse-Send-Data send-url9<LFS data>10<LFS data>11<streamed data>12<streamed data>13master.zip14
  1. 사용자가 UI에서 프로젝트 아카이브를 요청합니다.

  2. Workhorse는 이 요청을 Rails에 전달합니다.

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

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

  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 포인터를 식별하면, gitgitaly-lfs-smudge를 호출하고 표준 입력을 통해 LFS 포인터를 제공합니다. Gitaly는 LFS 객체의 조회를 활성화하기 위해 환경 변수로 GL_PROJECT_PATHGL_INTERNAL_CONFIG를 제공합니다.

  7. 유효한 LFS 포인터가 디코드되면, gitaly-lfs-smudge는 GitLab에서 LFS 객체를 다운로드하기 위해 Workhorse에 내부 API 호출을 수행합니다.

  8. Workhorse는 이 요청을 Rails에 전달합니다. LFS 객체가 존재하고 프로젝트와 연결되어 있으면, Rails는 LFS 객체가 있는 경로(로컬 디스크용) 또는 객체 저장소가 활성화된 경우 사전 서명된 URL과 함께 Gitlab-Workhorse-Send-Data HTTP 헤더를 전송합니다. 이 페이로드는 send-url로 시작합니다.

  9. Workhorse는 파일을 검색하여 gitaly-lfs-smudge 프로세스에 전송합니다. 이 프로세스는 내용을 표준 출력으로 작성합니다.

  10. git은 이 출력을 읽고 Gitaly 프로세스에 다시 전송합니다.

  11. Gitaly는 데이터를 Rails에 다시 전송합니다.

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

7단계에서 gitaly-lfs-smudge 필터는 Rails가 아닌 Workhorse와 통신해야 하며, 그렇지 않으면 잘못된 LFS 블롭이 저장됩니다. 이를 지원하기 위해 GitLab은 기본 Omnibus 구성을 변경하여 Gitaly와 Workhorse 간의 통신을 수행하도록 했습니다.

이 변경의 한 가지 부작용: 원본 요청의 상관 ID가 Gitaly(또는 gitaly-lfs-smudge)에 의해 수행되는 내부 API 요청에는 유지되지 않습니다. 8단계에서 수행된 요청과 같은 API 요청의 상관 ID는 무작위 값입니다. 이 Workhorse 문제가 해결될 때까지입니다.

관련 주제