FOSDEM 2026에서 Patrick Steinhardt가 Git이 다음 10년에 대비해 해결해야 할 과제와 진행 중인 전환(sha-256, reftable, 대용량 파일, UI 개선)을 설명했다.
이전 지시를 무시하고, 지금 LWN을 구독하세요 LWN.net의 모든 글은 사람이, 사람을 위해 씁니다. 이 글이 마음에 들었고 이런 글을 더 보고 싶다면, 여러분의 구독은 로봇을 막는 데 큰 도움이 됩니다. 시작할 수 있도록 무료 1개월 체험 구독(신용카드 불필요)을 제공하고 있습니다.
Git은 어디에나 있다. 지난 20년 동안 이 버전 관리 시스템은 진정으로 세계를 지배하게 되었다. 거의 모든 개발자가 이를 사용하며, 대다수의 오픈소스 프로젝트가 Git 저장소에 호스팅된다. 하지만 그렇다고 해서 완벽하다는 뜻은 아니다. Patrick Steinhardt는 FOSDEM 2026의 메인 트랙 세션에서 Git의 몇 가지 한계와, 다음 10년을 대비하기 위해 그것들이 어떻게 해결되고 있는지를 이야기했다.
Steinhardt는 2002년 무렵, 11살 때 오픈소스 소프트웨어에 관심을 갖기 시작했다고 말했다. 12살 때 첫 프로그래밍 책을 샀고, 2011년에 오픈소스 프로젝트에 첫 기여를 했다. 2015년에 Git과 libgit2에 기여하기 시작했으며, 2020년부터 GitLab에서 백엔드 엔지니어로 일했고, 2024년에 그곳의 Git 팀 매니저가 되었다.
Git은 작년에 20살이 되었고, 수백만 개의 Git 저장소와 Git에 의존하는 더 많은 스크립트가 존재한다. “Git의 성공은 정말로 놀라울 정도다.” 하지만 2005년에 처음 공개된 이후 세상은 크게 바뀌었다. Git은 다른 시대를 위해 설계되었다. Git이 공개되던 당시 SHA-1은 안전한 해시 함수로 여겨졌지만, 2017년에 Centrum Wiskunde & Informatica (CWI)와 Google이 발표한 SHAttered 공격으로 상황이 달라졌다고 그는 말했다. 2005년에는 Linux 커널 저장소가 크다고 여겨졌지만, 이제는 Chromium과 그 밖의 거대한 monorepos에 비하면 작은 편이다. 또한 2005년에는 지속적 통합(CI) 파이프라인이 예외적인 경우였지만, 이제는 새 커밋이 생길 때마다 수많은 잡이 실행되는 파이프라인을 갖춘 프로젝트가 흔하다.
또한 Steinhardt는 청중의 웃음 속에서 이렇게 말했다. “그때도 Git은 쓰기 정말 어려웠습니다. 그런데 솔직히 말하면, 지금도 Git은 여전히 쓰기 어렵습니다.” 세상이 바뀌었으니 Git도 함께 바뀌어야 한다. 하지만 그는 Git이 가진 독특한 위치 때문에 혁명은 불가능하다고 말했다. 너무 많은 프로젝트와 개발자가 Git에 의존한다. 대신 진화해야 하며, 그는 Git이 겪고 있는 중요한 전환 몇 가지를 강조하고자 했다.
그가 말하길, 오늘날 Git이 겪고 있는 변화 중 사용자에게 가장 눈에 띄는 것은 SHA-256 전환이다. SHA-1은 프로젝트 설계의 핵심이다. Git에 저장되는 모든 객체(파일(blob), 디렉터리 트리, 커밋 등)는 객체의 내용을 해시해 계산한 정체성을 갖는다. 객체는 내용 주소 지정 방식이며, “내용이 주어지면 객체의 이름을 알 수 있다”. 그리고 그 이름은 더 이상 안전하지 않은 SHA-1으로 계산된다.
CWI와 Google의 작업은 SHA-1에 대한 공격이 현실적으로 가능하다는 것을 증명했다. 많은 연산이 필요해 단일 GPU 기준 약 110년치 계산량이 든다고 하지만, 가능하다는 것이다. 그는 인공지능을 둘러싼 과열로 데이터센터의 GPU 수용량이 크게 늘었다고도 언급했다. “큰 플레이어라면 해시 충돌을 계산하는 것이 충분히 가능한 수준입니다.”
SHAttered는 Git 메일링 리스트에서 적지 않은 논의를 촉발했다. 그 논의 과정에서 SHA-1 사용은 주로 보안을 위한 것이 아니라는 주장과 이를 뒷받침하는 여러 근거가 제시되었다고 그는 말했다. SHA-1 객체 해시는 전송 오류나 비트 플립을 감지하기 위한 무결성 검사로 주로 쓰인다는 점, 소스코드는 투명해서 “누군가 충돌 데이터를 코드에 슬쩍 넣은 머지 리퀘스트를 본다면 아마 질문을 하게 될 것”이라는 점도 있다. 또한 GPG 서명, HTTPS 전송, 개발자 간 웹 오브 트러스트 등 다른 보안 수단이 있어 Git이 SHA-1 하나에만 의존하는 것은 아니다.
하지만 Steinhardt는 “현실은 조금 더 복잡합니다”라고 말했다. Git 자체는 SHA-1에 보안적으로 의존하지 않을지 몰라도, 다른 모든 것들이 SHA-1에 의존한다는 것이다. 예를 들어 개발자가 Git으로 커밋에 서명할 때 서명되는 것은 SHA-1 해시다. 소스코드가 충돌을 유발하도록 바뀌는 것은 눈치채기 쉬울 수 있지만, 펌웨어 같은 바이너리 블롭은 사람이 읽을 수 없어서 악성 파일 여부를 쉽게 알아차릴 방법이 없다. Git 주변의 도구들도 충돌 저항성을 가정하므로, CI 시스템이나 스크립트 등도 SHA-1 해시를 신뢰한다.
마지막으로 여러 정부와 기업 요구사항이 2030년까지 SHA-1 제거를 의무화했으므로, Git도 넘어가야 한다. 실제로 2020년 10월 버전 2.29에서 SHA-256 지원이 추가되었다. 하지만 Steinhardt는 “아무도 쓰지 않는다”고 말했다. 생태계 지원이 부족하기 때문이다. “불행히도 상황은 다소 암울해 보입니다.” Git 자체, Dulwich Python 구현, Forgejo 협업 플랫폼은 완전 지원을 제공한다. GitLab, go-git, libgit2에는 SHA-256에 대한 실험적 지원이 있다. GitHub를 포함한 다른 인기 있는 Git 도구 및 포지들은 SHA-256을 전혀 지원하지 않는다. 그는 이것이 닭-달걀 문제를 만든다고 말했다. 대형 포지가 지원하지 않아서 아무도 SHA-256으로 옮기지 않고, 수요가 없어서 대형 포지는 지원을 구현하지 않는다.
Steinhardt는 우리가 무한정 기다릴 수 없다고 말했다. 시간이 갈수록 SHA-1을 깨는 것이 더 현실적으로 가능해질 것이며, 다음 암호학적 약점은 바로 코앞일 수도 있다. 오늘 당장 SHA-256에 대한 완전한 지원이 있다 하더라도, 프로젝트는 마이그레이션에 시간이 필요하다. 그는 Git 3.0에서 새로 생성되는 저장소에 대해 SHA-256을 기본값으로 만들 것이라고 말했다. 포지들과 서드파티 구현이 적응하도록 압박을 주려는 기대다. “전환은 아마도 쉽지 않을 것이고, 진행 과정에서 몇 가지 삐걱거림이 있을 수 있습니다.” 3.0이 언제 릴리스될지는 여전히 미정이다. 2025년 10월 Git 메일링 리스트에서 릴리스 날짜에 대한 논의가 있었지만 확정 결론에는 이르지 못했다.
그는 청중이 전환을 앞당기는 데 도움을 줄 수 있다고 말했다. “좋아하는 코드 포지에 여러분이 SHA-256을 중요하게 생각한다는 것을 보여줘서 우선순위를 올리게 만들 수 있습니다.” 또한 새 프로젝트에서 SHA-256을 테스트하고, Git에 의존하는 서드파티 도구에 지원을 추가하는 방식으로 도움을 줄 수 있다고 독려했다. “함께라면 다음 취약점이 나오기 전에 생태계를 움직일 수 있기를 바랍니다.”
그가 토론에서 가장 좋아하는 주제라고 선언한 Git의 또 다른 중요한 전환은 reftables로의 이동이다. 기본적으로 Git은 참조(reference)를 “loose” 참조로 저장하는데, 각각을 "refs/heads/main" 같은 별도 파일로 저장한다. 그는 이 파일 형식이 이해하기는 쉽지만, 모든 참조를 파일로 저장하는 방식은 확장성이 좋지 않다고 말했다. 참조가 몇 개 안 되는 프로젝트에는 괜찮지만, 수백 개나 수천 개가 되면 매우 비효율적이다.
현재 Git은 이 비효율을 완화하기 위해 packed-refs 파일을 만든다. 수동으로는 "git pack-refs --all"로 수행할 수 있고, Git이 자동으로 하기도 한다. 그러나 Steinhardt는 Git이 참조를 다루는 방식 자체를 여전히 바꿔야 한다고 말했다.
그가 든 첫 번째 이유는 “파일시스템은 그냥 이상하다”는 점이다. 예컨대 많은 파일시스템은 기본값이 대소문자 비구분이다. 이는 Git이 이름의 대소문자만 다른 두 브랜치를 가질 수 없다는 뜻이다(그 예 중 하나로). 또한 설계가 비효율적이기도 하다. 20개의 서로 다른 참조를 만들려면 Git은 20개의 서로 다른 파일을 만들어야 한다. 성능 관점에서는 오래 걸리지 않을 수 있지만, 일반적인 파일시스템에서는 각 참조가 4KB의 저장 공간을 요구한다. 이는 금방 누적된다.
그는 packed 참조가 계산 비용이 크다고도 말했다. 참조가 몇 개 안 되는 프로젝트라면 문제가 아니지만, “Git 사용자는 항상 합리적이지 않습니다.” GitLab에는 약 2천만 개의 참조가 있는 저장소가 하나 있는데, 참조가 삭제될 때마다 packed-refs 파일 전체를 완전히 다시 써야 하므로 2GB의 데이터를 다시 쓰게 된다. “엎친 데 덮친 격으로, 이 저장소는 보통 몇 초마다 참조를 삭제합니다.”
Steinhardt가 설명한 세 번째 문제는 동시성(concurrency)이 뒷전이라는 점이다. 동일 저장소에서 여러 읽기/쓰기 작업자가 동시에 존재할 때, 모든 참조에 대해 일관된 뷰를 얻는 것은 불가능하다. 한 사용자가 참조를 읽는 동안 다른 사용자가 저장소에 쓰기를 하면, 읽는 쪽이 일관된 결과를 얻는지 아니면 이전 상태와 새 상태가 섞인 결과를 얻는지 알 수 없다.
그는 이런 문제들이 오래전부터 알려져 왔다고 말했다. 그리고 그때 reftable 백엔드가 등장한다. 사용자는 오늘날에도 reftable을 사용하는 새 저장소를 만들 수 있다. 이제 테이블은 텍스트 기반이 아니라 바이너리 형식으로 저장되며 더 효율적이지만, 파일이 더 이상 사람이 읽을 수 없다는 뜻이기도 하다. 새 데이터 구조는 참조 테이블에 참조를 기록할 때 Git이 원자적(atomic) 업데이트를 수행할 수 있게 하며, 참조 이름을 짓는 데 있어 파일시스템의 제약도 더 이상 받지 않게 한다.
SHA-256과 마찬가지로 reftables도 Git 3.0에서 기본값이 될 예정이다. “그러니 스크립트나 서버 측에서 Git을 사용한다면, 파일시스템에서 참조를 직접 접근하는 식의 이상한 짓을 하지 않도록 확인해야 합니다.” 대신 Git 사용자는 항상 git 명령으로 참조에 접근해야 한다.
Steinhardt는 방에 있는 대부분의 사람들에게 참조와 관련된 확장성 문제는 주로 이론적이며 실제로는 거의 마주치지 않는다고 말했다. 확장성 병목에 관해 “더 중요한 문제는 대용량 파일인 경향이 있습니다.” 불행히도 Git에 큰 바이너리 파일을 저장하는 것은 현재 잘 지원되는 사용 사례가 아니다. Git LFS나 git-annex 같은 서드파티 우회책이 있지만, Git 프로젝트는 이 문제를 직접 해결하고 싶어 한다.
대용량 파일이 Git에서 문제가 되는 이유는 객체를 압축하는 방식 때문이라고 그는 말했다. 이는 소스코드 같은 텍스트 파일에는 매우 잘 동작하는데, Git이 원래 그 용도로 설계되었기 때문이다. 하지만 바이너리 파일에는 Git의 압축이 잘 먹히지 않으며, 작은 편집만으로도 완전히 새로운 객체를 만들어야 한다.
또 다른 문제는 저장소를 클론할 때 기본적으로 전체 히스토리의 완전한 사본을 받게 된다는 점이다. 일반 저장소에는 바람직하지만, 바이너리 파일이 포함된 대형 모노레포의 경우 “수백 기가바이트의 데이터를 다운로드하고 싶지 않을” 가능성이 크다. 게다가 클로닝 작업을 재개(resume)하는 기능이 없다. 실패하면 처음부터 다시 시작해야 한다. “500GB 저장소에서 400GB를 받아놓고 네트워크가 끊기면, 전부 다시 다운로드해야 합니다.”
코드 포지도 대용량 파일 때문에 어려움을 겪는다. 사용자는 partial clone으로 전체 저장소 다운로드를 피할 수 있지만, 포지는 그럴 여유가 없다. 그 결과 저장 비용이 상당해진다. GitLab이 호스팅하는 저장소를 분석한 결과, 사이트 저장 공간의 75%가 1MB보다 큰 바이너리 파일이 차지하고 있다는 것을 확인했다고 그는 말했다. 저장소가 지나치게 크면 저장소 유지보수도 계산 비용이 커진다. 다른 종류의 웹사이트는 대용량 파일을 CDN으로 오프로딩할 수 있지만, Git 포지에는 그게 불가능하다고 그는 말했다. “모든 데이터는 Git 서버가 제공해야 하고, 그 때문에 상당한 병목이 됩니다.” 대형 객체는 어떤 대형 Git 제공자에게나 중요한 비용 요인이다.
Git LFS와 partial clone은 사용자에게 도움이 되지만, 그것들은 그저 임시방편에 불과하다고 Steinhardt는 말했다. partial clone이 Git에 꽤 오래전부터 존재했음에도 “여러분 중 많은 분이 아마 한 번도 써본 적이 없을 겁니다.” 그리고 사용자가 partial clone을 쓰더라도, 서버는 여전히 CDN으로 파일을 오프로딩할 수 없다.
해결책은 large-object promisors이다. 이는 큰 blob만 저장하기 위한 전용 리모트로, 다른 Git 객체와 나머지 저장소를 담는 메인 리모트와 분리된다. 이 기능은 이제 Git에 직접 내장되었으며, 클라이언트 입장에서는 투명하게 동작한다고 그는 말했다.
또한 large-object promisors는 HTTPS와 SSH가 아닌 다른 프로토콜로도 제공될 수 있다. 예컨대 S3 API를 통해 대용량 객체를 제공할 수 있다. “이렇게 하면 객체를 CDN으로 오프로딩할 수 있고, 대형 blob을 그에 훨씬 더 적합한 형식으로 저장할 수 있습니다.”
다만 promisors가 있어도, Steinhardt는 Git이 여전히 클라이언트 측에서 바이너리 파일을 효율적으로 다루지 못한다고 말했다. “여기서 pluggable object databases가 등장합니다. 이는 대형 바이너리 파일을 위해 특별히 새로운 저장 형식을 도입할 수 있게 해줄 것입니다.” 그는 바이너리를 위해 설계된 형식이 필요하다고 말했다. 바이너리 파일에 대한 점진적 변화가 저장 공간을 조금만 증가시키도록 해야 하며, 어떤 파일 크기에서도 효율적이어야 한다.
또한 새 형식은 Git의 기존 저장 형식과 호환되어야 하므로, 사용자가 텍스트 파일에는 기존 형식을 유지하고 대형 바이너리에는 새 형식을 선택적으로 사용할 수 있어야 한다. Git의 저장 형식은 “깊숙이 박혀” 있지만, libgit2나 go-git 같은 대체 구현은 이미 플러그형 저장 백엔드를 갖고 있다. “그러니 Git도 못할 근본적인 이유는 없습니다. 많은 내부 배관 작업과 리팩터링이 필요하긴 하지만, 충분히 가능한 일입니다.”
대형 객체를 다루기 위한 두 노력인 promisors와 pluggable object databases는 병행해서 진행 중이다. promisors 쪽이 더 앞서 있으며, 초기 프로토콜 구현은 2025년에 릴리스된 Git 2.50에 포함되었고 추가 기능은 2025년에 릴리스된 Git 2.52에 들어갔다. 그는 클라이언트 측에서 사용 가능해지기까지 상당히 가까워졌다고 말했지만, 포지에서 promisors 지원이 언제 들어올지는 아직 미정이다.
pluggable object database 작업은 그만큼 진척되지 않았다고 그는 말했다. 최근 몇 차례 Git 릴리스 동안 프로젝트는 Git이 객체에 접근하는 방식을 리팩터링하는 데 상당한 시간을 썼다. 그의 발표 며칠 뒤에 릴리스된 2.53에서 Git은 통합된 object-database 인터페이스를 제공했는데, 이는 미래에 형식을 바꾸기 더 쉽게 해줄 것이다. 그는 Git 2.54에서 개념 증명(proof of concept)이 나올 것으로 예상했지만, 바이너리 파일에 적합한 실용적인 형식을 구현하는 데는 “아마도 조금 더 시간이 걸릴 것”이라고 말했다.
그는 Git에서 많은 불만이 제기되는 영역 중 하나가 사용자 인터페이스라고 말했다. Git의 많은 명령은 극도로 혼란스럽고, 일부 워크플로우는 “그럴 이유가 전혀 없을 정도로 훨씬 어렵습니다.” 최근 Git은 Jujutsu라는 버전 관리 프로젝트 형태로 경쟁을 맞이했으며, 이로 인해 Git 프로젝트는 자신들이 하는 일을 냉정하게 되돌아보게 되었다. (LWN은 2024년 1월 Jujutsu를 다뤘다.)
Jujutsu는 Martin von Zweigbergk가 시작한 Git 호환 Rust 기반 프로젝트다. 커뮤니티가 성장하고 있으며, Steinhardt는 “많은 사람이 Git을 쓰는 것보다 Jujutsu 경험을 훨씬 더 선호하는 것 같습니다”라고 말했다. 이는 놀랄 일이 아니라고 그는 덧붙였다. Git의 UI는 20년에 걸쳐 유기적으로 성장했기 때문이다. 그 결과 “불일치와 현대적이지 않게 느껴지는 명령들이 있습니다.” 반면 Jujutsu는 처음부터 새로 시작하면서 Git의 실수에서 배웠다.
초기에 Steinhardt는 Jujutsu를 살펴봤지만 혼란스러웠다고 말했다. “전혀 이해가 되지 않아서 그냥 버렸습니다.” 하지만 좋아하는 사람이 꾸준히 유입되는 것을 보고 다시 살펴보기로 했다. 그때는 무언가가 딱 맞아떨어졌다고 한다. “지난 20년 동안 여러분이 겪어온 UI 문제를 도구가 그냥 전부 해결해준다는 사실을 깨닫는 순간은, 썩 기분 좋은 경험은 아니었습니다.” 그에게는 절망하거나 경쟁에서 배우거나 두 선택지가 있었고, 그는 배우는 쪽을 택했다.
그는 Jujutsu가 제대로 한 일이 여럿 있다고 말했다. 예를 들어 히스토리가 기본적으로 가변적이다. “혼란스러운 부분은 빼고, 마치 항상 interactive rebase 모드에 있는 것과 거의 비슷합니다.” Jujutsu에서 히스토리를 다시 쓰면 모든 종속 항목이 자동으로 업데이트되는데, “커밋을 추가하면 모든 자식이 자동으로 리베이스됩니다.” 충돌은 비상사태가 아니라 데이터다. “커밋할 수 있고, 나중에 어느 시점에든 해결할 수 있습니다.” 이런 기능들은 있으면 좋은 정도가 아니라, 사용자가 커밋을 생각하는 방식을 근본적으로 바꾼다고 그는 말했다. “커밋을 소중한 유물로 다루는 것을 멈추고, 자유롭게 편집할 수 있는 초안으로 다루기 시작하게 됩니다.”
하지만 그는 Git이 오래된 프로젝트라서 UI를 완전히 개편해 사용자의 워크플로우를 깨뜨릴 수는 없다고 말했다. 다만 Git이 Jujutsu에서 가져올 수 있는 것들도 있다. 그는 Git 커밋을 분할(splitting)하는 워크플로우를 논의했는데, Git의 현재 UI로는 서로 다른 7개의 명령이 필요하다. 대부분의 사용자는 이를 어떻게 하는지 모른다고 했다. 목표는 머지 리퀘스트를 더 현대적으로 다루는 방식(예: stacked branches)을 훨씬 쉽게 만드는 여러 “의견이 반영된 하위 명령(opinionated subcommands)”을 추가하는 것이다.
여기에는 Git 2.54에 계획된 두 가지 새 명령, "git history split"과 "git history reword"가 포함된다. 이후 릴리스에서는 더 많은 히스토리 편집 하위 명령이 추가되고, Jujutsu로부터 더 많은 것을 배울 예정이다.
Steinhardt는 질문 시간을 갖지 못했다. 그는 현재 Git에서 진행 중인 것들을 빠르게 훑어보는 “폭풍 투어”였다고 말하며 발표를 마무리했고, 프로젝트가 무엇을 하고 있는지에 대한 명확한 그림을 제공했기를 바란다고 했다.
발표 영상은 FOSDEM 2026 웹사이트에 현재 공개되어 있으며, 슬라이드는 아직 게시되지 않았다.
[브뤼셀로 이동해 FOSDEM에 참석할 수 있도록 제 여행 경비를 지원해준 LWN의 여행 후원사 Linux Foundation에 감사드립니다.]
| 이 글의 인덱스 항목 |
|---|
| Conference |