병렬 Claude Code 세션이 서로의 푸시를 계속 덮어쓰는 문제 해결 — 모든 리포지토리를 위한 단일 대시보드를 갖춘 로컬 머지
요약
병렬 Claude Code 세션이 서로의 푸시를 덮어쓰는 문제를 해결하기 위해 로컬 머지 큐인 'mergetrain'을 구축했습니다. Worktree를 활용해 작업을 격리하고, 대기열에 쌓인 브랜치들을 하나의 기차처럼 조립하여 테스트 후 원자적으로 푸시하는 방식입니다.
핵심 포인트
- 병렬 Claude Code 세션 간의 푸시 충돌 방지
- 서버나 외부 CI 없이 로컬에서 작동하는 머지 큐 구현
- Worktree 기반의 작업 격리 및 원자적 푸시 프로세스
- 에이전트가 읽을 수 있는 JSON 기반 상태 대시보드 제공
- MIT 라이선스의 오픈소스 도구로 제공
Worktrees는 편집 과정을 격리합니다. 하지만 랜딩(landing) 과정을 격리하지는 못합니다. 브랜치 A가 테스트를 통과하고, 브랜치 B가 테스트를 통과하더라도, A 다음에 B를 적용하면 깨질 수 있습니다. 그리고 "main에 절대 푸시하지 마시오"와 같은 CLAUDE.md 규칙들은, 단 하나의 세션이 최악의 순간에 규칙을 깨뜨리기 전까지만 유효합니다. 규칙은 강제력이 없습니다. 그래서 저는 완전히 로컬 머신에서 실행되는 머지 큐(merge queue)인 mergetrain을 구축했습니다. 서버도, GitHub App도, CI 서비스도, 런타임 의존성도 필요 없습니다.
현재 제 루프(loop)가 작동하는 방식은 다음과 같습니다: 각 Claude Code 세션은 자신만의 worktree에서 작업하며, 푸시(push) 대신 대기열에 추가(mergetrain enqueue)합니다. 리포지토리 소유의 pre-push hook이 main으로의 직접적인 푸시를 차단합니다. 하나의 러너(runner)가 대기열에 쌓인 브랜치들을 origin/main 위에 하나의 "기차(train)"로 조립하고, 전체 기차에 대해 한 번의 게이트(gates, 테스트 + 전체 Unity 빌드)를 실행한 다음, 원자적(atomically)으로 푸시합니다. mergetrain hub는 머신 내의 모든 리포지토리에 대해 하나의 읽기 전용 대시보드를 제공합니다: 누가 게이트를 실행 중인지, 무엇이 배포될 준비가 되었는지, 무엇에 주의가 필요한지를 보여줍니다. 에이전트(Agents)는 동일한 정보를 JSON 형식으로 읽을 수 있습니다 (hub status --json). 만약 푸시 도중 제 노트북이 꺼지더라도, mergetrain recover가 원격지에 실제로 무엇이 반영되었는지 물어보고 이를 조정(reconcile)합니다. 아무것도 중복 배포되지 않으며, 아무것도 잘못 라벨링되지 않습니다. 관리되지 않은 배포가 절대 발생해서는 안 되는 리포지토리는 --no-daemon으로 등록합니다: 보드에는 표시되지만, 자동으로 처리되지 않습니다.
제 게임에 3주 동안 직접 사용(dogfooding)해 본 결과: 70개 이상의 기차(trains)가 랜딩되었으며, 이후 덮어쓰기 푸시(trampled pushes)는 0건이었습니다. 무료이며 MIT 라이선스입니다: https://github.com/yongjip/mergetrain — 스크린샷은 README에 있습니다. pip install mergetrain을 실행하고 mergetrain init을 하면 설정과 함께 에이전트들이 자동으로 인식할 수 있는 CLAUDE.md 계약(contract)이 구성됩니다. 다른 사람들은 병렬 에이전트의 통합(integration) 측면을 어떻게 처리하는지 궁금합니다. 제가 찾은 모든 방법은 문제를 회피하거나(파일 잠금, file locking), 호스팅된 PR 파이프라인을 가정하고 있었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 r/ClaudeAI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기