솔직히 말해서, 최근 회사 상황이 녹록지 않았다.
최근 들어 새로운 기능 개발이나 수정사항도 없던 상황.
IDC에 구축한 모든 서비스를 임대서버로 옮겨야 한다는 결정사항이 내려왔다.
(이관하느라 바빠서 글 안 올린다고 변명하는 거 맞다.)
데이터베이스 이관은 서비스 중단이 필수이기 때문에, 우선 소스를 먼저 이관하기로 결정했다.
현재 상황
- GitLab 사용 중.
- 3가지 종류의 브랜치(운영, 개발, 기능)를 운영.
- 운영 (Master, 서비스되고 있는 코드)
- 개발 (Development, 통합 테스트 코드)
- 기능 / 이슈 (Feature / Hotfix, 개발자별 기능 개발 / 이슈 대응 코드)
- 이관할 서버의 GitLab은 신규 설치 돼있음.
- 기존 프로젝트와 동일하게 프로젝트도 생성 돼있음.
이관 전략
운영 브랜치만 옮기고, 다 버린다.

우리가 사용하는 브랜치 전략은 위 다이어그램과 같다.
운영 중 드러나 문제점은 다음과 같다.
- Hotfix / Feature 브랜치가 과도하게 쌓여있다.
- 별도로 브랜치를 삭제하는 프로세스가 없다.
- 통합테스트(IntefrationTest) 브랜치의 오염도가 높다.
- 각종 임시 / 테스트 코드, 병합뒤 운영에 배포되지 않는 커밋들이 쌓여있다.
이러한 문제점과 더불어서 최근 신규 / 수정 개발이 없었다.
이는 현재의 운영 코드가 조직의 요구사항에 적합하다고 판단하는 근거가 됐다.
따라서, 운영 브랜치만 이관하기로 결정했다.
결론적으로, 운영에 반영되지 않은 브랜치나 커밋은 모두 미련 없이 버리는 것이 이번 이관의 핵심 원칙이다.
이관 시나리오
보통 저장소 서버에서 서버로 직접 이관하는 게 가장 간편하겠지만,
인프라 담당자분의 업무가 바빠서 지원이 어려운 상황이다.
어차피 이관된 소스들은 개발자 PC에도 복사해 둘 필요가 있고,
이번 기회에 브랜치 정리와 확인 작업까지 겸해서
내 PC로 클론 한 뒤 진행하는 방식으로 결정했다.

- 하나의 디렉터리를 만든다.
- 해당 디렉터리에 기존 저장소에서 대상이 되는 모든 프로젝트의 운영 브랜치를 해당 프로젝트 이름의 디렉터리로 클론 한다.
- 해당 프로젝트 이름의 디렉터리로 이동한다.
- 기존 원격 저장소 정보를 삭제한다.
- 새로운 원격 저장소 정보를 입력한다.
- 새로운 원격 저장소에 푸시한다.
- 이 과정을 모든 프로젝트에 반복한다.
이관 실행 절차
1) 깃 명령어 실행
일단 하나만 해보자.
mkdir [이관용 디렉터리]
cd [이관용 디렉터리]
git clone -b [브랜치명] --single-branch [기존 저장소 주소] [디렉터리]
cd [디렉터리]
git remote remove origin
git remote add origin [신규 저장소 주소]
git push origin [로컬 브랜치명]:[원격 브랜치명]
Line 1 : [이관용 디렉터리] 생성
Line 2 : 생성된 [이관용 디렉터리]로 이동
Line 3 : [기존 저장소 주소]에서 [브랜치명] 브랜치만 [디렉터리]로 클론
Line 4 : 생성된 [디렉터리]로 이동
Line 5 : 기존저장소에 지정되어 있던 origin 삭제
Line 6 : [신규 저장소 주소]로 새 origin 생성
Line 7 : [로컬 브랜치명] 브랜치를 [원격 브랜치명] 브랜치로 원격에 푸시
위와 같은 방식으로, 대상이 되는 프로젝트마다 Line 2 ~ 7까지 반복해서 적어두고 실행해도 된다.
근데, 확인해 보니 이관 대상 프로젝트가 30갠데.. 이걸 언제 다 쓰나 싶다..
로깅이나 재사용을 고려한다면, 아래와 같이 쉘 스크립트를 만들어 두는 것도 좋다.
2) 쉘 스크립트 실행 (Optional)
위 명령어를 기반으로 쉘 스크립트(migration_all.sh)를 만들 수 있다.
2-1) 쉘 스크립트 작성(nano 또는 vi)
여기서는 nano로 작성
nano migration_all.sh
#!/bin/bash
# ===== 사용자 입력 =====
OLD_GITLAB_URL="https://old.gitlab.com/group"
NEW_GITLAB_URL="https://new.gitlab.com/group"
BRANCH="[운영 브랜치명]"
BASE_DIR="$HOME/[이관용 디렉터리]"
LOG_FILE="$BASE_DIR/[이관용 디렉터리].log"
# ===== 이관할 프로젝트 리스트 =====
declare -a PROJECTS=(
"project-a"
"project-b"
"project-c"
)
mkdir -p "$BASE_DIR"
echo "=== $(date '+%F %T') 마이그레이션 시작 ===" >> "$LOG_FILE"
for PROJECT in "${PROJECTS[@]}"
do
SRC="$OLD_GITLAB_URL/$PROJECT.git"
DST="$NEW_GITLAB_URL/$PROJECT.git"
TARGET="$BASE_DIR/$PROJECT"
echo "[$PROJECT] 시작" | tee -a "$LOG_FILE"
# 1. 기존 디렉토리 존재하면 삭제 (클린하게)
if [ -d "$TARGET" ]; then
rm -rf "$TARGET"
fi
# 2. 운영 브랜치만 clone
git clone -b "$BRANCH" --single-branch "$SRC" "$TARGET" >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
echo "[$PROJECT] Clone 실패. 건너뜀." | tee -a "$LOG_FILE"
continue
fi
cd "$TARGET" || { echo "[$PROJECT] 디렉토리 이동 실패"; continue; }
# 3. 기존 remote 제거 및 신규 remote 등록
git remote remove origin 2>/dev/null
git remote add origin "$DST"
# 4. 신규 저장소로 운영 브랜치만 push
git push -u origin "$BRANCH":"$BRANCH" --force >> "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
echo "[$PROJECT] Push 완료" | tee -a "$LOG_FILE"
else
echo "[$PROJECT] Push 실패" | tee -a "$LOG_FILE"
fi
done
echo "=== $(date '+%F %T') 마이그레이션 종료 ===" >> "$LOG_FILE"
# 전부 작성한 후 Ctrl + O > 엔터 > Ctrl + X
2-2) 실행권한 부여 (Permission denied 오류 대응)
chmod +x migration_all.sh
2-3) 실행
./migration_all.sh
결론
뽀롱뽀롱 잘 돈다~
생각보다 간단하게 끝나서 다행이다 ㅎㅎ