blog

git push --mirror로 저장소 통째로 복제하기

Front-end / Git#Git#mirror#저장소 이전

회사 저장소를 개인 저장소로 옮기거나 GitLab → GitHub로 이전할 때처럼, 모든 브랜치와 태그를 그대로 복제해야 할 때 --mirror를 사용한다.

권장 방법: bare mirror 클론에서 push

# 1. 원본을 mirror 형태(bare)로 클론
git clone --mirror https://github.com/old-owner/repo.git
cd repo.git

# 2. 비어 있는 새 저장소로 mirror push
git push --mirror https://github.com/new-owner/repo.git

# 3. 작업이 끝나면 임시 디렉터리 삭제
cd .. && rm -rf repo.git

git clone --mirror는 원본의 모든 ref(브랜치, 태그, 기타 ref)를 원본과 같은 이름으로 가져온다. 여기서 push하면 새 저장소가 원본과 동일해진다.

기존 작업 디렉터리에서 remote를 추가해 push하는 경우

git remote add mirror https://github.com/new-owner/repo.git
git push --mirror mirror
git remote remove mirror

동작은 하지만 주의할 점이 있다.

  • --mirror는 로컬의 모든 ref를 그대로 보낸다. 일반 클론에서는 refs/remotes/origin/*(원격 추적 브랜치)까지 대상 저장소에 올라가, 대상에 origin/main 같은 이상한 브랜치가 생길 수 있다.
  • 반대로 로컬에 체크아웃하지 않은 원격 브랜치는 refs/heads/로 올라가지 않는다.
  • 대상 저장소에만 있고 로컬에는 없는 ref는 삭제된다. 강제 push와 같으므로 이미 사용 중인 저장소를 대상으로 하면 안 된다.

그래서 "통째로 복제"가 목적이라면 위의 clone --mirror 방식을 쓴다.

일반 push와 비교

명령보내는 ref대상에만 있는 ref
git push origin main지정한 브랜치유지
git push --all모든 로컬 브랜치유지
git push --tags모든 태그유지
git push --mirror모든 ref삭제

GitHub의 Pull Request ref(refs/pull/*)는 대상 저장소에서 거부되어 ! [remote rejected] 메시지가 출력될 수 있다. 브랜치와 태그가 정상적으로 올라갔다면 무시해도 된다.