The future of large files in Git is Git

Tyler Cipriani

Git에서 대용량 파일의 미래는 Git이다

원문은 Tyler Cipriani님이 에 게재했습니다. 이 블로그 구독하기

Git에 숙적이 있다면, 그건 대용량 파일일 것이다.

대용량 파일은 Git 저장소를 비대하게 만들고, git clone을 느리게 하며, Git 포지를 엉망으로 만든다.

2015년 GitHub는 Git LFS를 출시했다. 대용량 파일 문제를 임시로 해결하기 위한 Git 확장이다. 하지만 Git LFS는 새로운 복잡성과 저장 비용을 더했다.

한편 Git 프로젝트는 조용히 대용량 파일 문제를 다뤄 왔다. LFS가 아직 죽은 건 아니지만, 최신 Git 릴리스는 LFS가 마침내 쓸모없어지는 미래로 가는 길을 보여준다.

오늘 당장 할 수 있는 일: Git LFS를 Git partial clone으로 대체하기

Git LFS는 대용량 파일을 저장소 외부에 저장하는 방식으로 동작한다.

LFS로 프로젝트를 clone하면 저장소의 히스토리와 작은 파일들은 가져오지만 대용량 파일은 건너뛴다. 대신 Git LFS는 작업 복사본에 필요한 대용량 파일만 다운로드한다.

2017년 Git 프로젝트는 Git LFS와 동일한 이점을 제공하는 partial clone을 도입했다:

Partial clone을 이용하면 clone과 fetch 과정에서 [대용량 바이너리 에셋을] 미리 다운로드하지 않을 수 있고, 이를 통해 다운로드 시간과 디스크 사용량을 줄일 수 있다.

– Partial Clone Design Notes, git-scm.com

Git partial clone과 LFS는 모두 다음과 같은 장점을 제공한다:

  1. 작은 체크아웃 – clone할 때 대용량 파일의 모든 복사본이 아니라 최신 복사본만 가져온다.
  2. 빠른 clone – 대용량 파일 다운로드를 피하므로 clone이 빠르다.
  3. 빠른 설정 – shallow clone과 달리 프로젝트의 전체 히스토리를 가져오므로 바로 작업에 들어갈 수 있다.

partial clone이란?

Git partial clone은 --filter가 적용된 clone이다.

예를 들어 100KB보다 큰 파일 다운로드를 피하려면 다음과 같이 실행하면 된다:

git clone --filter='blobs:size=100k' <repo>

이후 Git은 체크아웃에 필요한 100KB 초과 파일들을 필요할 때 지연(lazy) 다운로드한다.

기본적으로 거슬리는 25MB짜리 PNG 파일이 여러 리비전에 걸쳐 있는 저장소를 git clone하면 clone은 느리고 체크아웃 용량은 터무니없이 커진다:

$ time git clone https://github.com/thcipriani/noise-over-git
Cloning into '/tmp/noise-over-git'...
...
Receiving objects: 100% (153/153), 1.19 GiB

real    3m49.052s

단 하나의 25MB 파일을 체크아웃하는 데 거의 4분이 걸린다!

$ du --max-depth=0 --human-readable noise-over-git/.
1.3G    noise-over-git/.
$ ^ 🤬

그리고 그 단일 25MB 파일의 50개 리비전이 1.3GB의 공간을 차지한다.

하지만 partial clone은 이런 문제를 우회한다:

$ git config --global alias.pclone 'clone --filter=blob:limit=100k'
$ time git pclone https://github.com/thcipriani/noise-over-git
Cloning into '/tmp/noise-over-git'...
...
Receiving objects: 100% (1/1), 24.03 MiB

real    0m6.132s
$ du --max-depth=0 --human-readable noise-over-git/.
49M     noise-over-git/
$ ^ 😻 (the same size as a git lfs checkout)

필터를 적용하자 clone은 97% 빨라졌고(3분 49초 → 6초), 체크아웃 크기는 96% 줄어들었다(1.3GB → 49M)!

하지만 여전히 몇 가지 주의할 점이 있다.

필터링한 데이터가 필요한 명령을 실행하면 Git은 그 데이터를 가져오기 위해 서버에 다녀와야 한다. 그래서 git diff, git blame, git checkout 같은 명령을 실행하려면 Git 호스트에 접속해야 한다.

하지만 대용량 파일의 경우 이는 Git LFS와 동일한 동작이다.

게다가 PNG 파일에 git blame을 마지막으로 실행한 게 언제였는지 기억도 안 난다 🙃.

굳이 수고를 들여야 할까? Git LFS의 문제는 뭘까?

Git LFS는 Git의 대용량 파일 문제를 사용자에게 떠넘긴다.

그리고 그 문제는 심각하다:

  • 🖕 높은 벤더 종속성 – GitHub가 Git LFS를 만들 당시 다른 대용량 파일 시스템들—Git Fat, Git Annex, Git Media—은 서버에 구애받지 않았다. 하지만 GitHub는 사용자를 자사의 독자적인 서버 구현에 종속시키고 사용료를 부과했다.1
  • 💸 비싸다 – GitHub는 저장소를 무료로 호스팅해주며 성공했다. 하지만 Git LFS는 유료 제품으로 시작했다. 요즘은 무료 티어가 있지만 가격 책정은 GitHub 마음대로다. 오늘날 GitHub에서 50GB짜리 저장소를 운영하면 저장 비용으로 연간 40달러가 든다. 반면 Amazon S3 스탠다드 스토리지에 50GB를 저장하는 비용은 연간 13달러다.
  • 😰 되돌리기 어렵다 – 일단 Git LFS로 옮기고 나면 히스토리를 다시 쓰지 않고는 그 결정을 되돌릴 방법이 없다.
  • 🌀 지속적인 설정 비용 – 모든 협업자가 Git LFS를 설치해야 한다. Git LFS가 설치되어 있지 않으면 협업자는 기대한 대용량 파일 대신 혼란스러운 메타데이터로 가득한 텍스트 파일을 받게 된다.

미래: Git large object promisor

대용량 파일은 Git 포지에도 문제를 일으킨다.

GitHub와 GitLab은 큰 파일을 호스팅하는 데 비용이 더 많이 들기 때문에 파일 크기에 제한을 둔다2. Git LFS는 대용량 파일을 CDN으로 오프로드해 서버 측 비용을 낮게 유지한다.

하지만 Git 프로젝트에는 새로운 해법이 있다.

올해 초 Git은 새로운 기능인 large object promisor를 병합했다. large object promisor는 사용자에게 번거로움을 주지 않으면서 LFS와 동일한 서버 측 이점을 제공하는 것을 목표로 한다.

이 작업은 특히 서버 측을, 특히 이미 바이너리 형식으로 압축된 대형 blob을 개선하는 것을 목표로 한다.

이 작업은 Git LFS의 대안을 제공하는 것을 목표로 한다

– Large Object Promisors, git-scm.com

large object promisor란?

large object promisor는 대용량 파일만 보관하는 특수한 Git 리모트다.

밝고 찬란한 미래에는 large object promisor가 이렇게 동작할 것이다:

  1. 대용량 파일을 Git 호스트에 push한다.
  2. 백그라운드에서 Git 호스트가 그 대용량 파일을 large object promisor로 오프로드한다.
  3. clone할 때 Git 호스트가 promisor에 대해 Git 클라이언트에 알려준다.
  4. 클라이언트는 Git 호스트에서 clone하면서 promisor 리모트로부터 대용량 파일을 자동으로 가져온다.

하지만 그 밝고 찬란한 미래까지는 아직 갈 길이 멀다.

Git large object promisor는 아직 진행 중인 작업이다. large object promisor의 일부는 2025년 3월에 Git에 병합됐다. 하지만 할 일이 더 남아 있고 풀어야 할 열린 질문들도 있다.

그래서 지금으로서는 대용량 파일에 대해서는 여전히 Git LFS에 묶여 있다. 하지만 large object promisor가 널리 보급되면 GitHub에서도 100MB가 넘는 파일을 push할 수 있게 될지도 모른다.

Git에서 대용량 파일의 미래는 Git이다.

Git 프로젝트가 대용량 파일에 대해 깊이 고민하고 있으니 여러분이 애쓸 필요는 없다.

오늘날 우리는 Git LFS에 머물러 있다.

하지만 곧 Git에서 대용량 파일을 다루는 유일한 장애물은 MP3 라이브러리를 Git에 넣는 건 나쁜 생각이라는 어렴풋하고 불길한 직감뿐일 것이다.


Edited by Refactoring English


  1. 나중에 다른 Git 포지들도 자체 LFS 서버를 만들었다. 오늘날에는 여러 Git 포지에 push하거나 LFS transfer agent를 사용할 수 있지만, 이 모든 것이 기여자의 설정을 더 어렵게 만든다. 잠금을 풀기 위해 추가 노력을 기울이지 않는 한 사실상 종속된 상태에 머물게 된다.↩︎

  2. 파일 크기 제한: 100MB for GitHub, 100MB for GitLab.com↩︎

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.

댓글