git worktree move submodule error가 날 때 안전한 이동 순서

git worktree move submodule error가 나면 --force나 Finder 이동부터 하면 안 된다. 상위 worktree와 submodule의 변경을 각각 확인한 뒤 현재 경로를 유지하거나, 변경을 원격에 보존해 새 위치에 clone하거나, 로컬 주 저장소를 새 경로로 clone하는 방법을 고른다.

submodule이 있는 linked worktree의 직접 이동은 막고 새 clone에서 상위와 submodule commit을 확인하는 개념도

먼저 두 저장소의 변경을 따로 확인하세요

Mac에서는 Command + Space를 누르고 터미널을 여세요. 아래 /현재/worktree/경로를 실제 경로로 바꿉니다.

git -C "/현재/worktree/경로" status --short --branch
git -C "/현재/worktree/경로" submodule status --recursive
git -C "/현재/worktree/경로" submodule foreach --recursive 'git status --short --branch'

첫 명령은 상위 worktree, 마지막 명령은 각 submodule 안의 변경을 보여 준다. 어느 쪽이든 변경이 나오면 먼저 각 저장소에서 별도로 커밋하거나 안전한 위치에 복사한다. 상위 저장소의 커밋만으로 submodule 내부의 아직 커밋하지 않은 파일이 자동 보존되지는 않는다.

clean인데도 왜 move가 실패하나요?

Git 공식 worktree 문서는 submodule을 포함한 linked worktree를 git worktree move로 옮길 수 없다고 설명한다. 2026-09-19 macOS Git 2.38.1 재현에서도 상위와 submodule이 모두 clean인 상태에서 move는 exit 128로 끝났다.

fatal: working trees containing submodules cannot be moved or removed

git submodule deinit -f --all 뒤에도 같은 오류가 났다. 따라서 deinit이나 force를 성공이 확인된 해결책처럼 반복하면 안 된다. git worktree repair도 수동으로 옮겨진 경로의 연결을 복구하는 명령이며, 이 move 제한을 허용하는 옵션은 아니다.

가장 안전한 선택은 무엇인가요?

경로 변경이 꼭 필요하지 않다면 현재 worktree를 그대로 쓰는 것이 가장 간단하다. 이미 사라진 경로의 등록만 남았다면 stale worktree를 prune하는 순서를 먼저 확인한다.

새 경로가 꼭 필요하고 원격 저장소를 사용할 수 있다면 다음 순서로 진행합니다.

  1. 각 submodule 안의 변경을 먼저 커밋하고, 원격 방식을 쓸 때는 그 submodule commit을 해당 원격에 push한다.
  2. 상위 worktree에서 바뀐 submodule 경로를 git add한 뒤 다시 커밋한다. 이 상위 commit이 새 submodule commit을 가리키는 gitlink를 보존한다.
  3. 상위 저장소의 필요한 branch를 원격에 push하고 웹 저장소에서 상위·submodule commit이 모두 보이는지 확인한다.
  4. 새 경로에 저장소를 clone하고 해당 branch를 checkout한다.
  5. git submodule update --init --recursive를 실행한다.
  6. 새 경로에서 상위 commit과 각 submodule commit이 원래 값과 같은지 확인한다.
  7. 새 경로 검증이 끝난 뒤에만 기존 worktree 정리를 별도 작업으로 진행한다.

복사 가능한 검증 명령은 다음과 같습니다.

git -C "/현재/worktree/경로" rev-parse HEAD
git -C "/새/clone/경로" rev-parse HEAD
git -C "/현재/worktree/경로" submodule status --recursive
git -C "/새/clone/경로" submodule status --recursive

두 경로의 상위 commit과 submodule commit이 각각 같아야 한다. 원격을 쓸 수 없거나 아직 커밋할 수 없는 변경이 있다면 기존 폴더를 지우지 않고 현재 경로를 유지한다.

로컬 전용 branch는 어떻게 새 경로로 옮기나요?

상위 저장소의 branch를 외부 원격에 push하지 않았더라도 주 저장소를 로컬 원본으로 clone하면 새 경로에서 복원할 수 있다. 단, 이 설명은 상위 branch에만 해당한다. submodule의 새 commit은 상위 저장소 clone에 포함되지 않는다. 그 commit이 .gitmodules의 URL에서 실제로 접근 가능하지 않으면 아래 절차를 진행하지 말고 기존 경로를 보존한다.

git -C "/현재/worktree/경로" rev-parse --path-format=absolute --git-common-dir

출력이 /주/저장소/.git처럼 나오면 .git을 뺀 /주/저장소를 아래 원본 경로로 사용합니다. 현재 branch 이름도 기록합니다.

git -C "/현재/worktree/경로" branch --show-current
git clone --no-local "/주/저장소" "/새/clone/경로"
git -C "/새/clone/경로" switch "로컬-branch-이름"
git -C "/새/clone/경로" submodule update --init --recursive

--no-local은 하드링크 최적화 대신 실제 Git 객체를 복사해 새 clone을 독립시킨다. 이 명령은 외부 서버로 push하지 않는다. submodule URL이 사내 서버나 로컬 경로라면 새 경로에서 접근 가능한지 따로 확인해야 한다.

submodule update가 not our ref 또는 commit을 찾지 못했다는 오류로 끝나면 submodule의 로컬 전용 commit이 URL 쪽 저장소에 없는 상태일 수 있다. 이때 상위 gitlink를 이전 commit으로 되돌리거나 강제로 정리하면 안 된다. 기존 worktree와 submodule 폴더를 그대로 보존하고, 해당 submodule commit을 접근 가능한 원격에 보존하거나 submodule 원본을 별도로 안전하게 복제한 뒤 다시 진행한다. 이번 직접 재현은 submodule 원본에 이미 존재한 commit만 확인했으며, submodule의 미전송 새 commit 이동은 확인하지 않았다.

명령이 멈추면 다음처럼 분기한다.

오류 뜻 다음 행동
repository ... does not exist 주 저장소 경로가 틀렸거나 접근할 수 없음 rev-parse --git-common-dir 출력에서 .git을 뺀 경로를 다시 확인한다.
invalid reference 또는 pathspec ... did not match 새 clone에 branch가 없음 기존 worktree에서 branch 이름과 commit을 다시 확인하고 기존 폴더를 유지한다.
submodule clone 인증·경로 오류 submodule URL에 접근할 수 없음 .gitmodules의 URL과 로그인·로컬 경로를 해결할 때까지 기존 폴더를 지우지 않는다.

새 경로가 완전한지 어떻게 확인하나요?

기존 경로를 정리하기 전에 상위 commit, submodule commit, 변경 상태를 모두 대조하세요.

git -C "/현재/worktree/경로" rev-parse HEAD
git -C "/새/clone/경로" rev-parse HEAD

git -C "/현재/worktree/경로" submodule status --recursive
git -C "/새/clone/경로" submodule status --recursive

git -C "/새/clone/경로" status --short --branch

두 rev-parse HEAD가 같고, submodule status --recursive의 경로별 commit이 같아야 한다. 새 경로의 status 출력에 예상하지 않은 변경이 있으면 기존 경로를 정리하면 안 된다.

기존 linked worktree는 언제 정리하나요?

검증이 끝난 뒤 주 저장소에서 일반 제거를 먼저 시도한다.

git -C "/주/저장소" worktree remove "/현재/worktree/경로"

일반 제거가 같은 submodule 제한으로 멈추면 기존 경로를 그대로 보존한다. remove --force는 폴더를 삭제하며 경로 오입력·중첩 경로·ignored 파일까지 함께 확인해야 하므로 이 초보자용 절차에서는 실행 명령을 제공하지 않는다. 디스크 정리가 꼭 필요하면 별도 백업 뒤 숙련자 검토를 받아 진행한다. 로컬 재현에서 remove --force는 exit 0을 반환했지만, 재현 스크립트의 후속 파싱 오류 때문에 폴더와 등록의 사후 상태를 확인하지 못했다. 이 결과를 완료 근거로 쓰지 않는다.

자주 묻는 질문

git worktree repair로 바로 해결할 수 있나요?

아니다. repair는 수동 이동 등으로 끊어진 연결을 복구하는 명령이다. submodule이 든 linked worktree의 move 제한을 해제하지 않는다.

remove --force를 두 번 써야 하나요?

횟수를 먼저 정하면 안 된다. 이 글의 재현은 사후 상태까지 확인하지 못했으므로 강제 제거를 해결 절차로 권하지 않는다. 새 clone을 검증한 뒤에도 기존 경로를 보존하고, 디스크 정리는 별도 백업과 숙련자 검토 뒤 진행한다.

검증 범위

  • 확인일: 2026-09-19~20
  • 환경: macOS, Git 2.38.1, 비민감 임시 저장소와 로컬 submodule
  • 확인: 초기화된 submodule을 포함한 clean linked worktree에서 move exit 128, deinit 뒤 동일 오류, 로컬 주 저장소에서 --no-local clone 후 로컬 전용 branch checkout, 상위·submodule commit 일치, 일반 remove exit 128, commit 대조 후 remove --force exit 0 반환
  • 미확인: 재현 스크립트의 후속 파싱 오류 때문에 강제 제거 직후 폴더와 worktree 등록의 사후 상태는 별도 확인하지 못함
  • 미확인: 최신 Git 전체 버전, Codex Desktop의 자동 이동 동작, 정확 월간 검색량과 독자 직접 피드백

검증 기준

직접 만든 실습 자료와 새 도구 소식

AI 도구로 만든 실습 자료, 달라진 기능과 강의 소식을 준비하고 있습니다. 발송을 시작하면 안내해 드려요. 먼저 확인 메일에서 본인 이메일을 확인해 주세요.

신청하기 전에 첫 소식 미리보기에서 내용과 자료를 확인해 보세요.

질문이나 의견을 남겨주세요

이름을 입력하지 않아도 돼요. ‘깜짝 놀란 올빼미’ 같은 별명이 자동으로 붙어요.