GitHub가 Git을 망쳤다: 코드를 조용히 삭제한 Merge Queue 버그
Source: Dev.to
GitHub가 Git이 아니게 된 날
2026년 4월 23일 16:05 UTC에 회귀 버그가 GitHub의 머지 큐에 스며들었습니다. 그 후 3시간 반 동안 전 세계 엔지니어들은 풀 리퀘스트를 검토하고 “merge” 버튼을 클릭했으며, 모든 것이 완벽하게 정상인 것처럼 보였습니다:
- 초록색 체크.
- 깔끔한 diff.
- 경고 없음.
하지만 실제로는 무언가가 조용히 끔찍하게 일어나고 있었습니다.
+29 / -34 정도의 합리적인 diff를 가진 PR이 승인되어 큐에 들어갔습니다. 그런데 main에 착륙한 커밋은 +245 / -1,137이라는 규모였습니다. 다른 엔지니어들이 이미 배포하고, 검토하고, 넘어갔던 수천 줄의 코드가 사라진 것이었습니다. 그리고 그 이후의 모든 머지는 그 깨진 히스토리 위에 쌓여갔습니다.
UI에는 문제가 전혀 표시되지 않았고, 상태 페이지에도 장애가 없었습니다. 플랫폼은 모두에게 거짓말을 하고 있었습니다.
Source: …
실제로 발생한 문제
GitHub의 병합 대기열은 대기 중인 각 PR마다 임시 브랜치를 만들어 작동합니다. 일반적으로 이 임시 브랜치는 main의 최신 커밋에 PR의 diff를 적용한 상태에서 시작하고, CI가 실행되어 통과하면 병합됩니다.
4월 23일에 대기열은 이 임시 브랜치를 잘못된 시작점에서 만들기 시작했습니다. main의 현재 최신 커밋에서 브랜치를 만드는 대신, 해당 기능 브랜치가 main과 처음 갈라졌던 지점(수십 혹은 수백 커밋 전)에서 브랜치를 만들었고, 그 전체 내용을 main에 푸시했습니다.
따라서 기능 브랜치가 대기열에 들어갔을 때 main보다 50 커밋 뒤쳐져 있었다면, “병합” 과정에서 다른 사람들의 50 커밋 작업이 조용히 삭제된 것입니다. CI는 임시 브랜치 자체가 내부적으로 일관되었기 때문에 통과했지만, main은 현재 상태와 전혀 맞지 않아 깨졌습니다.
근본 원인: 병합‑베이스 계산을 조정하는 새로운 코드 경로가 아직 출시되지 않은 기능에 대한 feature flag 뒤에 숨겨져야 했지만, 플래그 적용이 불완전해 새로운 동작이 프로덕션에 유출되었고, 모든 squash‑merge 그룹에 적용되었습니다.
이 버그가 특히 심각했던 세 가지 이유
-
PR UI가 거짓 정보를 보여줬다.
+29 / -34를 검토했지만 실제 병합된 커밋은+245 / -1,137이었습니다. 엔지니어들이 승인한 내용과 실제 병합된 내용이 달랐습니다. 이는 코드 리뷰 시스템의 가장 근본적인 계약을 깨는 행위였습니다. -
전혀 알림이 없었다.
병합 충돌도, 체크 실패도, PR에 배너도 없었습니다. 팀은main에 있어야 할 코드가 사라진 것을 누군가가 발견했을 때야 비로소 문제를 인지했습니다. -
레포지토리 활동량에 비례해 피해가 커졌다.
레포가 빨리 병합될수록 기능 브랜치가main에서 더 많이 떠돌아 있었고, 하나의 잘못된 병합이 초래하는 피해도 커졌습니다. 병합 대기열에 가장 많이 의존하던 팀이 가장 큰 타격을 입었습니다.
인간 비용
이것은 이론적인 문제가 아니었습니다. 엔지니어링 팀은 전체 오후를 사고 대응 모드에서 보냈습니다: 커밋 그래프를 뒤지고, 삭제된 코드를 손으로 복원하고, 여러 저장소에 걸쳐 복구를 조율하고, 며칠이 걸릴 수도 있는 지원 티켓을 제출했습니다.
- 한 조직은 GitHub의 머지 큐에서 작업하는 모든 팀이 영향을 받았으며, 각 팀마다 수십 개의 잘못된 커밋이 발생하고 수백 개의 기존 커밋이 누군가 눈치채기 전에 덮어쓰기 되었다고 보고했습니다.
- 한 회사만 해도 200개가 넘는 PR이 손상되었다고 주장했습니다.
GitHub는 나중에 4월 22–23일 영향 기간 동안 230개의 저장소에서 2,092개의 풀 리퀘스트가 영향을 받았다고 밝혔습니다. GitHub COO가 X에 올린 초기 메시지는 그 수치를 2,804개의 PR이라고 했으며, 일부 커뮤니티 구성원들은 개별 기업들이 겪은 상황을 두고 두 숫자 모두에 강하게 반발했습니다.
이 사고는 가용성이 아니라 머지 커밋 정확성에 영향을 주었기 때문에 GitHub의 자동 모니터링으로는 감지되지 않았습니다. GitHub는 UTC 19:38에 고객 지원 문의 증가를 계기로 회귀(regression)를 인지했으며, UTC 20:43에 복구(리버트 및 강제 배포)를 완료했습니다. 3시간 33분 동안의 무음 손상.
왜 상태 페이지는 쓸모 없었는가
GitHub의 상태 페이지를 4월 23일에 확인했다면, 별다른 경고를 보지 못했을 것입니다. 보고된 주요 장애도 없었고, 부분 장애도 없었습니다.
그 이유는 GitHub의 상태 페이지 계산이 **“Degraded Performance”(성능 저하)를 다운타임 수치에서 제외하기 때문입니다. 플랫폼 자체가 다운되지 않았습니다. 개발자들은 여전히 코드를 푸시하고, PR을 열고, merge 버튼을 클릭할 수 있었습니다. merge 를 클릭했을 때 조용히 코드베이스가 파괴되는 현상은 대시보드에 사고로 기록되지 않았습니다.
이는 중요한 차이를 보여줍니다. 가동 시간과 정확성은 동일하지 않다는 점입니다. 거래를 처리하지만 기록을 잘못하는 은행은 “가동 중”이라고 할 수 없습니다. GitHub은 머지를 처리했지만 잘못된 결과를 만들었을 뿐입니다. 상태 페이지는 그런 종류의 실패를 포착하도록 설계되지 않았습니다.
이것은 고립된 나쁜 날이 아니었습니다
한 번만 일어났다면 더 쉽게 넘어갈 수 있었겠지만, 2026년 4월은 GitHub에게 정말 힘든 시기였습니다.
merge‑queue 사고가 있은 4일 뒤인 4월 27일, GitHub의 Elasticsearch 클러스터가 과부하에 걸렸습니다—아마도 봇넷 공격 때문일 가능성이 높으며, 검색 기반 UI가 결과를 반환하지 않기 시작했습니다. 풀‑리퀘스트 목록이 비어 보였고, 이슈가 사라졌습니다… (원문이 여기서 끊깁니다).
GitHub 사고 – 2026 년 4월
사고 타임라인
- 2026 년 4월 22‑23일 – merge‑queue에 버그가 발생해 병합 커밋이 잘못 생성되었습니다. UI에는 정상적인 녹색 병합이 표시됐지만, 실제 히스토리는 손상되었습니다.
- 2026 년 4월 28일 – GitHub의 CTO Vlad Fedorov가 신뢰성에 대한 사과문을 게시했습니다. 같은 아침에 별도의 보안 공지가 발표되었습니다: Wiz 연구원들이 GitHub의
git push파이프라인에서 심각한 원격 코드 실행 취약점(CVE‑2026‑3854, CVSS 8.7)을 발견했습니다. 조작된git push는 GitHub 서버에서 샌드박스되지 않은 코드를 실행할 수 있었습니다. 이 패치는 75 분 만에 배포되었습니다.
5일 안에 3가지 주요 실패 – merge‑queue 정확성 문제, 검색 붕괴, 그리고 핵심
git push경로의 원격 코드 실행(RCE) 취약점.
규모 압박
Fedorov는 GitHub가 원래 2025 년 10월에 10배 용량 증대를 계획했지만, 2026 년 2월까지 AI 기반 개발 도구(Copilot, Cursor, Codex)의 급증으로 30배 재설계가 필요했다고 설명했습니다. 현재 피크 수치는 다음과 같습니다:
- 하루에 9,000만 개의 병합 PR
- 하루에 14억 개의 커밋
더 깊은 아키텍처 문제
GitHub의 병합 대기열은 수동 “Merge pull request”와는 다른 코드 경로를 통해 병합 커밋을 생성합니다. 이 중복은 동작이 조용히 달라질 수 있는 두 곳을 만들게 됩니다.
- 위임 위험 – 대기열은 사람이 할 일을 자동화하지만, 자체 로직을 추가하면 아무도 작성하거나 승인하지 않은 커밋을 만들 수 있습니다.
- GitHub를 넘어선 패턴 – 쓰기 권한을 가진 모든 자동화 시스템(대기열, 봇, AI 에이전트)은 사람이 하지 않을 일을 할 때 보이지 않는 실패 모드를 초래할 수 있습니다.
교훈:
병합 대기열을 피하지 말고, main에 쓰는 모든 작업이 지루하고 잘 이해된 Git 작업에 최대한 가깝게 유지되도록 하세요. 검토자가 감사할 수 없는 새로운 로직은 포함하지 않아야 합니다.
Will Anyone Actually Leave?
Short answer: Probably not in any significant numbers.
- Stickiness: CI pipelines, webhooks, RBAC policies, Actions workflows, third‑party app permissions, team structures, and PR history make migration a multi‑month effort.
- Utility mindset: GitHub is the default platform for open source and most integrations. Developers rarely switch utilities because of a bad week.
What should change:
The baseline of trust. Infrastructure that silently corrupts data, even briefly, requires a solid recovery plan.
Immediate actions for teams:
- Verify – Audit squash merges in merge‑queue groups (≥ 2 PRs) from the April 22‑23 window.
- Document assumptions – List parts of your build/deploy pipeline that assume Git history is correct and make those assumptions visible for review.
GitHub가 말하는 내용
GitHub의 사고 후 대응에는 구체적인 약속이 포함됩니다:
- merge‑correctness validation에 대한 테스트 커버리지를 확대합니다.
- 프로덕션 전, 지원되는 병합 구성 전반에 걸쳐 결과 Git 내용을 검증하는 회귀 검사를 추가합니다.
- 성능에 민감한 코드를 기존 Ruby 코드베이스에서 Go로 마이그레이션합니다.
- 30× scale 요구사항을 충족하기 위해 시스템을 퍼블릭 클라우드 인프라로 이전합니다.
4월 23일 버그는 새로운 코드 경로에 대한 기능 플래그가 완전하지 않아 발생했으며, 즉각적인 해결책은 되돌리기였고, 장기적인 해결책은 다중 PR 병합 대기열 그룹에 대한 보다 풍부한 테스트 커버리지를 제공하는 것입니다.
요약
2026년 4월 23일, GitHub의 병합 대기열이 버전 관리의 핵심 계약을 깨뜨렸습니다: 승인한 것이 바로 병합된다는 것. 이는 오류 없이, 깔끔한 UI와 상태 페이지 항목 없이 조용히 일어났습니다.
- 코드는 Git 객체 저장소에 남아 있었지만, 브랜치 히스토리는 잘못되었습니다.
- 모든 영향을 받은 저장소를 안전하게 복구할 자동화 시스템이 없었으며, 엔지니어가 수동으로 개입해야 했습니다.
핵심 요점: Git은 모든 것이 구축되는 지루하고 신뢰할 수 있는 레이어여야 합니다. 그 레이어가 “흥미로워”진다면, 가장 최악의 방식으로 그렇게 됩니다.
이 내용이 도움이 되었다면 아래에 댓글을 남기거나, 우리가 (때로는 너무) 신뢰하는 도구들에 대한 깊이 있는 분석을 더 받아보세요.
