문제: 매번 .env 파일을 수동으로 복사하는 번거로움
Bun 모노레포에서 Git worktree를 자주 생성하면서 개발하다 보면, 새 worktree가 생길 때마다 .env 파일을 직접 복사해야 한다는 문제가 있다. 특히 GUI 앱(oh-my-worktree 같은)으로 worktree를 관리하는 경우, 매번 터미널을 열어서 파일을 복사하는 건 번거롭고 실수하기 쉽다.
내 경우에는:
apps/api-server/.envapps/wetrials-x-mobile/.env
두 개의 환경변수 파일이 필요했고, worktree를 생성할 때마다 이 파일들을 일일이 복사해야 했다.
검토한 방법들
1. Symlink 방식
중앙 위치에 .env 파일을 두고 worktree에서 symlink로 연결하는 방식이다.
- 장점: 환경변수 변경 시 모든 worktree에 반영
- 단점: GUI 앱이라 자동화가 어렵고, 새 worktree마다 symlink를 수동으로 생성해야 함
2. direnv
디렉토리별로 환경변수를 자동으로 로드해주는 도구다.
- 장점: 강력하고 유연함
- 단점: Bun이 이미
.env파일을 자동으로 로드해주므로 오버킬
3. .env.example + 자동 복사
버전 관리에 올리는 .env.example에서 실제 .env 파일로 복사하는 방식이다.
- 장점: 팀 친화적, 깃에 추적 가능
- 단점: 매번 민감한 정보를 다시 입력해야 함
4. 외부 .env-store 디렉토리
프로젝트 외부의 중앙 저장소에서 복사하는 방식이다.
- 장점: 명확한 구조
- 단점: 경로를 하드코딩해야 하므로 팀원 간에 공유 어려움
최종 해결책: Git post-checkout 훅
Git worktree를 만드는 과정에서는 자동으로 post-checkout 훅이 실행된다. 이 시점을 활용하면 자동으로 .env 파일을 복사할 수 있다.
핵심 아이디어:
- 메인 worktree(bare root)의
.env파일을 새 worktree로 자동 복사 - 상대 경로를 사용해 경로 하드코딩 제거
- 메인 worktree 자체에서는 아무것도 하지 않음
구현: post-checkout 훅 스크립트
.git/hooks/post-checkout 파일을 다음과 같이 작성한다:
#!/bin/bash
# Git worktree post-checkout hook
# worktree 생성 시 bare root의 .env 파일을 자동 복사
BARE_ROOT="$(cd "$(git rev-parse --git-common-dir)/.." && pwd)"
CURRENT="$(pwd)"
# bare root 자체면 아무것도 안 함
[ "$BARE_ROOT" = "$CURRENT" ] && exit 0
# .env 파일 복사 (없을 때만)
for env_file in apps/api-server/.env apps/wetrials-x-mobile/.env; do
if [ -f "$BARE_ROOT/$env_file" ] && [ ! -e "$env_file" ]; then
cp "$BARE_ROOT/$env_file" "$env_file"
fi
done스크립트 해석
git rev-parse --git-common-dir: 모든 worktree가 공유하는.git디렉토리의 경로를 반환한다.BARE_ROOT계산: 공통.git디렉토리의 부모 디렉토리가 메인 worktree(bare root)다.- 조건 체크: 현재 디렉토리가 bare root라면, 이미 원본
.env파일이 있으므로 훅을 종료한다. - 파일 복사: bare root에 있는
.env파일을 현재 worktree로 복사한다. 이미 있으면 덮어쓰지 않는다.
설치 방법
1. 훅 파일 생성
메인 저장소의 .git/hooks/ 디렉토리에 파일을 생성한다:
cat > .git/hooks/post-checkout << 'EOF'
#!/bin/bash
BARE_ROOT="$(cd "$(git rev-parse --git-common-dir)/.." && pwd)"
CURRENT="$(pwd)"
[ "$BARE_ROOT" = "$CURRENT" ] && exit 0
for env_file in apps/api-server/.env apps/wetrials-x-mobile/.env; do
if [ -f "$BARE_ROOT/$env_file" ] && [ ! -e "$env_file" ]; then
cp "$BARE_ROOT/$env_file" "$env_file"
fi
done
EOF2. 실행 권한 부여
chmod +x .git/hooks/post-checkout3. 테스트
새 worktree를 생성해서 .env 파일이 자동으로 복사되는지 확인한다:
git worktree add ../test-branch test-branch
cd ../test-branch
ls -la apps/api-server/.env apps/wetrials-x-mobile/.env # 파일이 있는지 확인주의사항
기존 worktree에는 적용되지 않음
훅 설치 전에 만든 worktree들은 post-checkout 훅이 실행되지 않았으므로 .env 파일을 수동으로 복사해야 한다:
cd /path/to/existing-worktree
cp /path/to/main-worktree/apps/api-server/.env apps/api-server/.env
cp /path/to/main-worktree/apps/wetrials-x-mobile/.env apps/wetrials-x-mobile/.env팀원과의 공유
.git/hooks/ 디렉토리는 기본적으로 Git에 추적되지 않는다. 팀원들도 같은 설정을 사용하게 하려면:
방법 1: 수동 설치 (간단) README에 설치 지침을 추가하고 각자 설치하도록 한다.
방법 2: Git hooks 공유 (추천)
프로젝트 루트에 .githooks/ 디렉토리를 만들고 훅을 커밋한다:
mkdir -p .githooks
mv .git/hooks/post-checkout .githooks/post-checkout
chmod +x .githooks/post-checkout
git add .githooks/post-checkout
git config core.hooksPath .githooks그러면 다른 개발자들도 git clone 후 자동으로 훅이 설정된다.
결론
Git post-checkout 훅을 활용하면, worktree 생성 시 자동으로 .env 파일을 복사할 수 있다. 이는:
- GUI 앱과 완벽하게 호환됨 (자동으로 실행됨)
- 경로 하드코딩이 없어서 어디서나 사용 가능함
- 추가 도구(direnv, symlink 등)가 필요 없음
단순하지만 효과적인 해결책으로, 매번 수동으로 파일을 복사하는 번거로움을 완전히 제거할 수 있다.
사실 이 문제를 겪으면서 결국 worktree 관리 자체를 더 편하게 할 수 있는 macOS 앱을 직접 만들었다. oh-my-worktree라는 프로젝트인데, worktree 생성 시 .env 파일 자동 복사를 기본 내장하고 있어서 훅 설정 없이도 바로 해결된다.

worktree를 자주 쓰는 macOS 사용자라면 한번 써보길 추천한다.