GitHub, 에이전트 동시 푸시 위한 Git 저장 구조 ‘Rubicon’ 공개
GitHub는 에이전트가 한 저장소에 동시에 푸시할 수 있도록 서버 저장 구조 Rubicon을 공개했습니다. 회사 내부 시험에서는 에이전트 5,000개가 작업하는 저장소에 초당 7,200회의 푸시를 처리하면서 읽기 요청도 낮은 지연으로 제공했다고 밝혔습니다. 객체 저장·참조 갱신·팩 정리를 분리해 각각 확장하며, 게시 당시 제한된 비공개 프리뷰를 제공하고 2027년 초 더 넓게 배포할 계획이었습니다.

GitHub는 2026년 11월 5일 자사 블로그에서 에이전트의 동시 푸시에 대응하기 위한 Git 저장 구조 Rubicon을 공개했습니다. 회사 내부 시험에서는 한 저장소에서 에이전트 5,000개가 작업하며 초당 7,200회의 푸시를 보내는 동안 읽기 요청도 낮은 지연으로 처리했다고 밝혔습니다. 게시 당시 제한된 비공개 프리뷰를 제공하고 있었고, 더 넓은 배포는 2027년 초로 예고했습니다.
Rubicon은 Git 데이터 중 무엇에 동시성 제어가 필요한지 나눠 설계했습니다. 커밋과 파일 내용 같은 Git 객체는 내용으로 이름이 정해지고 한 번 기록된 뒤 바뀌지 않습니다. 서로 다른 푸시가 객체를 저장할 때는 전체 순서를 합의할 필요가 없습니다. 반면 브랜치나 태그가 가리키는 참조를 갱신할 때는 순서를 정해야 합니다. 각 에이전트가 자기 브랜치에 푸시하면 서로 다른 참조의 갱신을 병렬로 처리할 수 있습니다.
클라이언트와 내부 API의 요청은 라우팅과 부하 분산을 맡는 Spokes를 거쳐 해당 저장소에 배정된 가상 복제본으로 전달됩니다. 복제본은 읽기·쓰기 중 한쪽 또는 둘 다를 처리하는 임시 컴퓨트이며, 로컬 디스크는 언제든 다시 만들 수 있는 캐시입니다. Spokes는 가능하면 같은 복제본에 요청을 보내 캐시에 필요한 데이터를 유지합니다. 특정 복제본이 사라져도 다른 복제본이 요청을 처리하고, 새 복제본은 요청이 들어오면서 캐시를 채웁니다. 요청이 어느 복제본에 도착하는지는 데이터의 정확성에 영향을 주지 않습니다.
지속적으로 보존하는 데이터는 두 곳에 나뉩니다. Git 객체를 담은 팩과 읽기를 돕는 자료는 Azure Blob Storage에 저장하고, 참조와 저장소를 구성하는 팩 목록인 매니페스트는 복제 로그 서비스 Ref-CAS에 둡니다. 푸시를 처리하는 복제본은 새 팩을 Blob Storage에 올린 뒤 Ref-CAS에 트랜잭션을 기록해 매니페스트에 팩을 추가하고 참조를 갱신합니다. 따라서 새 참조가 공개될 때는 그 참조가 가리키는 객체가 이미 내구성 있는 저장소에 기록돼 있습니다.
Ref-CAS는 참조를 바꾸는 트랜잭션만 처리합니다. 트랜잭션은 변경 대상 참조만 잠그고, 쓰기 요청자가 예상한 기존 값이 유지되는지 확인합니다. 로그 복제본 과반수가 기록하면 갱신이 공개됩니다. 서로 다른 참조를 바꾸는 푸시는 병렬로 진행할 수 있지만, 같은 참조를 동시에 바꾸면 한 요청만 로그에 추가됩니다. GitHub는 참조 상태만 처리하는 Ref-CAS가 초당 수만 건의 연산을 처리한다고 설명했습니다.
GitHub는 참조 로그를 Blob Storage에 두는 설계도 시험했습니다. 참조 전체의 로그를 하나의 Blob에 두면 읽을 때 변경 여부만 확인하면 되지만, 조건부 쓰기는 한 번에 하나만 진행할 수 있습니다. 이 방식의 쓰기 처리량은 실제로 초당 수백 건대 중간 수준에 머물렀습니다. 참조를 여러 Blob으로 나누면 서로 다른 구간의 쓰기를 병렬화할 수 있지만, 읽을 때는 모든 구간을 확인해야 하고 가장 느린 확인이 전체 지연을 좌우합니다. 읽기 요청이 쓰기보다 훨씬 많은 Git 저장소에서는 이 방식의 읽기 비용이 부담이 됐습니다.
읽기 경로도 참조와 객체 데이터의 분리를 이용합니다. 복제본은 자신이 가진 참조 상태의 로그 순번을 Ref-CAS에 보내 최신 여부를 확인합니다. 저장소에 변화가 없으면 참조 목록을 다시 받을 필요 없이 버전 비교 한 번으로 확인을 마칩니다. 복제본이 뒤처졌다면 최신 참조와 버전, 팩 데이터의 위치 정보를 받은 뒤 요청에 필요한 팩을 Blob Storage에서 캐시로 가져옵니다.
푸시가 팩을 계속 추가하면 객체를 찾을 때 살펴볼 팩도 늘어납니다. 기존 구조에서는 트래픽을 처리하는 복제본이 압축 작업도 맡았고 모든 복제본에서 그 작업을 실행해야 했습니다. Rubicon은 압축을 별도 노드에서 백그라운드로 수행합니다. 노드는 저장소 데이터의 일부인 샤드에 임대를 걸어 한 번에 하나의 작업자만 해당 샤드를 처리하게 합니다. 새 팩을 모아 더 큰 팩으로 합친 뒤 입력과 출력에 든 객체가 정확히 같은지 검사합니다. 이어 새 팩을 매니페스트에 추가하고, 별도 트랜잭션으로 입력 팩을 목록에서 제거한 뒤 나중에 정리합니다. 팩의 해시로 샤드를 나누므로 여러 샤드의 작업은 독립적으로 진행할 수 있습니다. 참조가 끊긴 객체를 제거하는 가비지 컬렉션도 전용 작업자가 맡습니다.
이 구조에서는 가상 복제본을 늘려 읽기와 쓰기를 확장하고, Ref-CAS가 참조 갱신을 처리하며, 압축 노드를 늘려 유지보수 작업을 확장합니다. GitHub는 사용자가 푸시·가져오기·브랜치 생성에 쓰는 Git의 흐름과 보호 기능은 그대로 유지된다고 설명했습니다. 바뀌는 부분은 그 요청을 처리하는 서버 쪽 저장 구조입니다.