Git에는 추적하는 파일과 추적하지 않는 파일만 있다. 컨테이너형 웹 서비스의 저장소를 정리해 보니, 예제 플러그인 12개가 실제 운영 플러그인이 적재되는 경로 안에서 추적되고 있었다. 사람 눈에는 예제와 운영 파일이 달랐지만 Git에는 같은 경로의 파일이었다.
중첩된 저장소를 운영 루트로 합치려 하자 이 차이가 더 커졌다. 새 루트와 기존 저장소가 겹치는 추적 파일은 274개였고, 저장소의 Compose 파일은 운영에 쓰는 파일과 내용이 달랐다. 단순 재귀 복사는 충돌을 조용히 덮어쓸 수 있었고, checkout은 런타임 파일까지 소스처럼 되돌릴 수 있었다.
.gitignore를 추가하는 것만으로는 부족했다. 이미 추적 중인 파일은 무시 규칙을 넣어도 계속 추적된다. 예제 플러그인은 별도 예제 경로로 옮기고, 실행 중 생성되는 플러그인과 데이터는 Git의 소유 범위에서 빼야 했다. 운영 Compose 파일은 바이트를 그대로 보존했다.
이 기준으로 후보 트리를 먼저 만들었다. 저장소 이력과 하위 모듈은 새 루트와 함께 옮겼고, 충돌 파일은 항목별 목록으로 처리했다. 전체 Docker 빌드와 집중 테스트 70개, 격리된 시작 검사를 통과한 뒤에만 실제 트리를 교체했다.
교체 후에는 소스 해시 97개와 깨끗한 Git 상태, 중첩 checkout 제거, 애플리케이션 진입점을 다시 확인했다. 운영 중인 컨테이너 4개는 재시작하지 않았다. 이미지와 설정 해시, 상태 검사는 작업 전과 같았고 모두 정상 상태를 유지했다.
소스 트리를 합치는 일은 폴더 수를 줄이는 작업으로 끝나지 않는다. Git이 소유할 파일과 운영 환경이 소유할 파일을 먼저 갈라야 한다. 그 경계가 없으면 정리된 디렉터리는 깔끔해 보여도 다음 checkout이 운영 변경 명령이 된다.