화요일 오전 10시 12분, 슬랙에 메시지 하나가 떴다. "main이 3개월 전으로 돌아갔는데요." 새벽 배포를 준비하던 주니어 개발자가 git push --force origin main을 실행한 게 사고의 전부였다. 로컬 main이 이틀 전 상태인 줄 알았던 것이다. 47개 커밋, 데이터베이스 마이그레이션 3건, API 리팩토링 12건, 성능 최적화 패치 8건이 한 줄에 증발했다. 이 날의 손실을 금액으로 환산한 사람은 아무도 없었다. 필자가 직접 계산해봤다.

47개 커밋, 2주 복구, 5만 달러 — 숫자로 까본 force push 사고

사고 발생 직후부터 상황은 빠르게 악화됐다. 엔지니어 6명이 진행 중인 작업을 전면 중단하고 복구에 투입됐다. 이틀 동안 96시간을 쏟아부었다. 시니어 엔지니어 시간당 120달러, 주니어 80달러로 잡으면 인건비만 9,600달러다. 배포는 1주일 밀렸고, 이 지연이 고객사 SLA에 영향을 줘 15,000달러가 추가됐다. 포스트모템 작성과 프로세스 정비 미팅에 5,000달러. 여기에 측정은 안 되지만 더 큰 비용이 있다. 팀이 일주일 동안 신규 기능 개발을 멈췄다는 사실, 그리고 '우리 코드가 언제 또 날아갈지 모른다'는 불안감이다. GitHub의 사고 분석 리포트는 이 평판 손상을 20,000달러로 추산한다. 총합 49,600달러, 한화로 약 6천5백만 원. 한 줄의 명령어가 3개월치 생산량을 통째로 삼킨 셈이다.

스타트업의 경우 이 비용은 더 치명적이다. 시리즈 A를 앞둔 15인 팀이라면 2주간의 개발 공백은 로드맵 전체를 흔든다. 투자사 미팅 자료에 들어갈 기능이 사라지고, 데모데이 직전에 백엔드가 통째로 롤백되는 일도 실제로 있었다. 2024년 한 국내 핀테크 스타트업은 force push 사고로 시리즈 A 일정이 2개월 밀렸다. VC는 "개발 프로세스가 미성숙하다"고 평가했고, 밸류에이션은 15% 깎였다. 복구 인건비보다 훨씬 큰 금액이다.

커밋은 죽지 않는다 — reflog가 90일간 지켜주는 안전망

기술적으로 말하면, git은 커밋을 거의 지우지 않는다. 삭제처럼 보이는 작업도 내부적으로는 '도달 불가능한 객체'로 보존할 뿐이다. 덮어쓴 커밋이라도 GitHub는 90일 동안, 로컬 reflog는 기본 90일 동안 HEAD가 가리켰던 모든 커밋을 기록한다. git fsck --lost-found 명령은 이 고아 객체들을 찾아준다. 복구 시나리오는 생각보다 단순하다. 추가 작업을 즉시 중단하고, reflog에서 사고 직전 HEAD 위치를 확인한 뒤, git show로 해당 커밋 내용을 검증하고, 복구 브랜치를 만들어 앵커로 삼는다. 이후 병합하거나 cherry-pick으로 필요한 커밋만 가져오면 된다.

실제 사고 복구 사례들을 모아보면 패턴이 있다. reset --hard로 날린 커밋은 reflog에서 찾았다. 실수로 지운 브랜치는 reflog의 checkout 기록에서 되살렸다. 엉망이 된 rebase도 rebase 시작 지점이 reflog에 남아 있다. 한 시니어 엔지니어는 "git을 15년 썼지만, 진짜 위기는 reflog를 알기 전과 후로 나뉜다"고 말했다. 복구 기술 자체는 어렵지 않다. 단지 reflog가 있다는 걸 사고 전에 아는 사람이 드물 뿐이다.

진짜 비용은 인건비가 아니다 — 무너진 신뢰와 오염된 파이프라인

사고의 본질은 복구가 아니라 조정에 있다. 커밋을 되살리는 데 이틀이 걸렸다면, 팀원 15명을 전부 일관된 상태로 되돌리는 데는 더 오래 걸렸다. 이미 pull한 개발자의 로컬 브랜치는 깨진 히스토리로 오염됐다. CI/CD 파이프라인이 캐시한 아티팩트는 고아가 됐다. 열려 있던 PR 15개는 전부 쓸모없어졌다. PR마다 달린 리뷰 코멘트 수십 개도 함께 증발했다.

더 무서운 건 복구 이후 찾아오는 신뢰의 붕괴다. "main에 직접 push하지 마세요"라는 Slack 공지가 올라오고, 코드 리뷰가 과도하게 보수적으로 변한다. 사소한 PR도 3명 이상의 승인을 요구하게 되고, 배포 주기는 눈에 띄게 느려진다. 필자가 겪은 한 팀은 force push 사고 이후 배포 빈도가 월 12회에서 4회로 떨어졌다. 안전해졌다고 말할 수 있을까. 오히려 조직의 속도가 죽은 것이다. 복구 인건비 9,600달러는 전체 손실의 일부에 불과하다. 배포 속도 저하, 개발자 사기 하락, 온보딩된 신규 인력의 혼란까지 더하면 실제 비용은 5만 달러를 훌쩍 넘는다.

예방은 개인의 조심성이 아니라 시스템으로 해야 하는 이유다. force push가 필요할 땐 --force-with-lease를 쓴다. 이 옵션은 원격 브랜치가 내가 예상한 상태일 때만 push를 허용한다. 다른 사람이 그 사이 커밋을 올렸다면 push가 거부된다. main 브랜치는 GitHub/GitLab의 브랜치 보호 규칙으로 직접 push를 금지하고, PR 리뷰와 CI 상태 체크를 통과해야만 병합되게 만든다. pre-push hook으로 main을 향한 force push 자체를 차단하는 팀도 늘고 있다. Atlassian의 2025년 DevOps 리포트에 따르면, 브랜치 보호 규칙을 적용한 팀은 force push 관련 사고가 94% 감소했다. hook 한 줄, 설정 3분이면 막을 수 있는 사고다.

오늘 당장 확인해야 할 3가지

git 사고의 진짜 댓가는 복구 인건비가 아니다. 멈춘 배포, 오염된 PR, 그리고 회복에 몇 달이 걸리는 팀의 신뢰다. 반면 예방 비용은 hook 한 줄, 보호 규칙 설정, 그리고 force push 대신 --force-with-lease를 쓰는 습관뿐이다.

지금 당장 할 수 있는 일은 세 가지다. 첫째, GitHub 레포지토리의 Settings → Branches에서 main 브랜치 보호 규칙이 활성화돼 있는지 확인한다. 둘째, 터미널에서 git reflog를 쳐서 본인의 최근 HEAD 히스토리가 보이는지 확인한다. 셋째, git config --global alias.pushf 'push --force-with-lease'로 별칭을 등록한다. 오늘 이 3가지만 해도 5만 달러짜리 전화 한 통은 피할 수 있다.