AI 코딩 세션 여러 개가 저장소 하나를 같이 쓰면 git이 이렇게 꼬입니다 — 배포는 됐는데 커밋이 없던 코드 17종
앱 48개를 담은 저장소 하나를 AI 코딩 에이전트 세션 여러 개가 동시에 만집니다. 한 세션이 올려 둔 스테이징을 다른 세션의 커밋이 쓸어 가는 사고가 났고, 엿새 동안 쌓인 미커밋 변경 78건 속에는 이미 배포된 게임 17종의 코드가 들어 있었습니다. 그걸 주제별 커밋 11개로 푼 과정과 규칙
혼자 개발하지만 작업하는 손은 여러 개입니다. 앱 48개가 들어 있는 저장소 하나를 놓고 AI 코딩 에이전트(Claude Code) 세션을 여러 개 띄워 둡니다. 한 세션은 새 게임을 만들고, 다른 세션은 기존 앱의 버그를 고치고, 또 다른 세션은 스토어 등록을 합니다.
사람 여러 명이 협업할 때는 각자 자기 컴퓨터에 저장소를 따로 둡니다. 저는 그러지 않습니다. 세션들이 같은 폴더 하나를 같이 씁니다. 빌드 결과물·서명 키·기기 연결이 전부 이 폴더에 걸려 있어서, 세션마다 복사본을 두면 그걸 맞추는 일이 더 커지기 때문입니다. 대신 이 방식에는 사람 협업에서는 잘 안 보이는 함정이 있습니다.
사고 1: 내가 스테이징한 걸 남이 커밋했다
git에는 “다음 커밋에 넣을 것”을 모아 두는 스테이징 영역(index)이 있습니다. 폴더가 하나면 이것도 하나입니다.
10월 3일, 한 세션이 빌드 설정 파일(build.gradle.kts)에서 자기가 고친 블록만 골라 스테이징해 두었습니다. 같은 파일을 다른 세션도 고치고 있었기 때문입니다. 그런데 커밋하기 직전, 다른 세션이 자기 커밋을 하면서 그 스테이징까지 같이 쓸어 담았습니다. 다른 세션 입장에서는 자기 파일만 지정해서 커밋했는데, 이미 올라가 있던 남의 파일이 따라 들어간 겁니다.
수습하려던 다음 커밋은 더 나빴습니다. 공유 스테이징에서 읽은 파일 내용이 그사이 다른 세션 버전으로 바뀌어 있어서, 커밋 메시지는 “검사 추가”인데 실제 내용은 검사 삭제로 들어갔습니다. 커밋 직후 바뀐 줄 수를 보고 바로 알았고(46줄 추가를 예상했는데 203줄 추가·47줄 삭제), 되감지 않고 복원 커밋을 하나 더 쌓아 바로잡았습니다.
교훈은 하나입니다. 스테이징은 “커밋 직전 잠깐”이 아니라 다른 세션의 다음 커밋에 그대로 실리는 공유 상태입니다.
사고 2: 배포는 됐는데 커밋이 없었다
10월 7일, 저장소에 커밋되지 않은 변경이 78건 쌓여 있었습니다. 10월 1일부터 4일까지 여러 세션이 고치고 그대로 둔 것들입니다. 하나씩 열어 보니 이런 게 섞여 있었습니다.
- 토스 혜택 탭 1원 프로모션 미션 코드, 게임 17종분. 이미 토스에 배포돼서 실제로 돌아가고 있는 코드였습니다.
- Google Play 업데이트용 버전 번호 올림 22종
- 새 게임(물리 엔진을 쓰는 성 무너뜨리기)의 뼈대 48개 파일
- 퀴즈 앱 버그 수정, 촬영 도구, 출시 체크리스트 기록
배포는 빌드 결과물을 올리는 일이라 커밋이 없어도 됩니다. 그래서 “올렸으니 끝”이 되기 쉽습니다. 하지만 그 상태로 누가 저장소를 정리하거나 다른 버전으로 되돌리면, 지금 사용자가 쓰고 있는 코드가 어디에도 남지 않습니다.
78건을 커밋 11개로 푼 방법
한 번에 git add -A로 몰아서 커밋하면 1분이면 끝납니다. 그러지 않은 이유는 다음 세션들이 git log를 읽고 “왜 이렇게 됐는지”를 파악하기 때문입니다. 1,300줄짜리 커밋 하나는 아무것도 설명하지 못합니다.
먼저 지금 누가 작업 중인지 확인했습니다. 바뀐 파일들의 마지막 수정 시각을 보니 가장 최근이 사흘 전이었습니다. 스테이징 영역도 비어 있었습니다. 누군가 작업 중이면 그 세션 몫은 건드리지 않았을 겁니다.
위험한 것을 먼저 걸렀습니다. 큰 파일(영상)이 섞였는지, 푸시하면 자동 배포가 도는지, 비밀값이 들어갔는지 봤습니다. 비밀값은 커밋·푸시 때마다 자동으로 검사하는 훅이 걸려 있습니다.
커밋 전에 전부 빌드가 되는지 확인했습니다. 바뀐 게임 24종을 타입 검사하고, 새 게임은 테스트 67개를 돌렸습니다. 깨진 걸 커밋하면 다음 세션이 그 위에서 시작하게 됩니다.
주제별로 나눴습니다. 같은 기능은 한 커밋으로, 날짜 순으로 11개 커밋을 만들었습니다. 1원 프로모션 17종이 한 커밋, 버전 번호 올림이 한 커밋, 새 게임 뼈대가 한 커밋입니다.
한 파일 안에 두 가지 일이 섞인 건 덩어리 단위로 쪼갰습니다. 빌드 설정 파일 하나에 “버전 번호 올림 22종”과 “새 게임 등록”이 섞여 있었습니다. 수정 부분(diff)을 덩어리별로 나눠 버전 번호 줄만 담은 패치를 만들고, 그걸 스테이징에만 적용(git apply --cached)해서 먼저 커밋했습니다. 그다음 남은 새 게임 줄을 새 게임 커밋에 넣었습니다.
커밋할 때마다 스테이징 목록을 대조했습니다. 이번에 넣으려던 파일 목록과 실제로 스테이징된 목록이 하나라도 다르면 커밋하지 않도록 했습니다. 사고 1을 막는 장치입니다.
지금 쓰는 규칙
- 스테이징 영역이 비어 있지 않으면 그 저장소에서는 커밋하지 않는다. 누군가 커밋하려던 중이라는 뜻이다.
- 여러 세션이 같이 고치는 파일은 작업 트리에만 고쳐 두고 넘긴다. 빌드 설정, 앱 목록 같은 파일이다. 꼭 일부만 커밋해야 하면 먼저 사람(저)에게 묻는다.
- 확인과 커밋을 한 명령 안에서 한다. “확인했다”와 “커밋했다” 사이에 다른 세션이 끼어들 수 있다.
- 커밋 직후 바뀐 줄 수가 의도와 같은지 본다. 이번 사고도 그 숫자로 바로 드러났다.
- 배포했으면 커밋까지가 배포다.
AI 에이전트에게 일을 맡기면 코드를 쓰는 속도보다 정리되지 않은 상태가 쌓이는 속도가 먼저 문제가 됩니다. 손이 여러 개면 서로의 손을 확인하는 절차가 필요합니다.
만든 앱들은 GAMES와 APPS에 있습니다. 1원 프로모션 이야기는 토스 혜택 탭에 1원 프로모션을 걸었습니다에 적었습니다.
