活儿开了一半,紧急修复来了
한국어 원문으로 표시합니다.
목표
저장소 하나에 작업 디렉터리를 셋까지 붙였다 정리합니다. 끝나면 stash 없이 브랜치를
갈아타는 손이 생기고, 작업 사본이 남긴 관리 파일을 어떻게 치우는지 알게 됩니다.
왜 중요한가
브랜치를 바꾸는 일이 왜 이렇게 번거로운지 생각해 보면, 작업 트리가 하나뿐이기
때문입니다. 저장소는 객체와 브랜치 참조를 들고 있고, 작업 트리는 그중 한 커밋을 펼쳐
놓은 사본입니다. 펼쳐 놓는 자리를 늘릴 수 있다면 갈아타기 자체가 필요 없어집니다.
git worktree 가 정확히 그 일을 합니다. 다만 브랜치 참조는 저장소가 하나로 들고
있어서, 같은 브랜치를 두 자리에서 열려고 하면 git 이 막습니다. 이 제약을 이해하는
것이 이 실습의 절반입니다. 나머지 절반은 정리입니다 — 디렉터리만 지우면 관리 파일이
남고, 그 자리가 prunable 인 채로 계속 목록에 뜹니다.
단계
/root/gitx4/repo에 커밋 3개짜리 저장소를 만들고release브랜치를 땁니다.release를/root/gitx4/rel에 작업 사본으로 붙입니다.main을/root/gitx4/dup에 한 번 더 붙여 보고, 거절 메시지를notes/dup.txt에 남깁니다.repo에 저장하지 않은 변경을 남겨 둔 채/root/gitx4/hot에hotfix브랜치를 새로 만들어 붙이고, 거기서hotfix.txt를 커밋합니다.git worktree list --porcelain을notes/list.txt로 남깁니다./root/gitx4/tmp를 붙였다가 디렉터리만rm -rf하고,prunable표시와prune결과를notes/prune.txt에 남깁니다./root/gitx4/usb를 붙여lock을 걸고,remove가 거절하는 것을notes/lock.txt에 남긴 뒤 풀어서 지웁니다.notes/report.md에 worktree · stash · clone 을 언제 쓰는지 정리합니다.
참고
- 이 이미지에는 git 신원이 전역으로 없습니다. 저장소를 만들면
git config user.email과git config user.name을 그 저장소에 지정해야 커밋이 됩니다. - 커밋 시각은
GIT_AUTHOR_DATE와GIT_COMMITTER_DATE로 고정합니다. 채점이 시각에 흔들리지 않게 하려는 것이고, 실무에서도 재현 가능한 이력을 만들 때 쓰는 손입니다. - 흔한 실수: 4단계에서
repo의 변경을git stash나 커밋으로 치워 버리는 것입니다. 이 실습의 요점은 치우지 않고도 된다 는 쪽이라, 그대로 두어야 합니다. - 흔한 실수: 6단계에서
git worktree remove를 쓰는 것입니다. 거기서는 디렉터리를rm -rf로 먼저 없애고, 남은 관리 파일을prune이 치우는 흐름을 봐야 합니다.
저장소와 릴리스 브랜치 만들기
/root/gitx4/repo 에 커밋 3개짜리 저장소를 만들고 release 브랜치를 땁니다.
git init -b main 으로 시작합니다. 이 이미지에는 전역 신원이 없으니 저장소마다 git config user.email 과 user.name 을 정해야 커밋이 됩니다. 커밋 시각은 GIT_AUTHOR_DATE 와 GIT_COMMITTER_DATE 두 환경 변수로 고정합니다.
릴리스 브랜치를 두 번째 자리에 붙이기
release 를 /root/gitx4/rel 에 작업 사본으로 붙입니다.
git worktree add <경로> <브랜치> 입니다. 붙인 뒤 새 디렉터리의 .git 이 디렉터리가 아니라 파일 이라는 것을 cat 으로 확인해 보세요. 그 한 줄이 원래 저장소의 관리 디렉터리를 가리킵니다.
같은 브랜치를 두 자리에서 열 수 없는 이유
main 을 /root/gitx4/dup 에 한 번 더 붙여 보고, 거절 메시지를 notes/dup.txt 에 남깁니다.
git worktree add /root/gitx4/dup main 을 그대로 해 보면 fatal: 로 시작하는 줄이 나옵니다. 그 줄을 요약하지 말고 그대로 파일에 넣고, 왜 막는지 한 줄 덧붙이세요 — 브랜치 참조는 저장소가 하나로 들고 있습니다.
저장하지 않은 변경을 그대로 두고 핫픽스
repo 에 저장하지 않은 변경을 남겨 둔 채 /root/gitx4/hot 에 hotfix 브랜치를 새로 만들어 붙이고, 거기서 hotfix.txt 를 커밋합니다.
repo 에 draft.txt 를 만들어 두세요 — 커밋도 stash 도 하지 않습니다. 그 상태에서 git worktree add -b <새브랜치> <경로> <기준> 으로 자리를 하나 더 만들고, 그 디렉터리 안에서 커밋합니다. 끝나고 repo 를 보면 draft.txt 가 그대로 있습니다.
지금 자리가 몇 개인지 기계가 읽는 형식으로
git worktree list --porcelain 을 notes/list.txt 로 남깁니다.
--porcelain 은 사람이 아니라 스크립트가 읽으라고 만든 출력입니다. 정렬을 맞춘 표 대신 worktree·HEAD·branch 가 한 줄씩 나옵니다. 리다이렉션으로 그대로 파일에 넣으세요.
디렉터리만 지우면 관리 파일이 남는다
/root/gitx4/tmp 를 붙였다가 디렉터리만 rm -rf 하고, prunable 표시와 prune 결과를 notes/prune.txt 에 남깁니다.
git worktree add -b tmpwork /root/gitx4/tmp 로 자리를 만든 뒤 그 디렉터리를 rm -rf 합니다. 그 상태에서 git worktree list 를 보면 한 줄에 prunable 이 붙습니다. git worktree prune -v 가 무엇을 지웠다고 말하는지, 그리고 브랜치는 남는지 까지 확인해서 적으세요. prune 의 설명은 표준 오류로 나가므로 파일에 담으려면 2>&1 이 필요합니다.
잠긴 자리는 remove 가 거절한다
/root/gitx4/usb 를 붙여 lock 을 걸고, remove 가 거절하는 것을 notes/lock.txt 에 남긴 뒤 풀어서 지웁니다.
git worktree lock --reason '<사유>' <경로> 로 잠급니다. 잠긴 자리에 git worktree remove 를 하면 거절 메시지가 나옵니다 — 그 줄을 그대로 남기세요. 그다음 unlock 하고 remove 해서 목록과 디렉터리가 함께 사라지는 것까지 확인합니다.
언제 자리를 늘리고 언제 밀어 넣는가
notes/report.md 에 worktree · stash · clone 을 언제 쓰는지 정리합니다.
세 방법이 각각 무엇을 아끼고 무엇을 잃는지로 갈라 쓰세요. 이번에 직접 본 것 두 가지 — 같은 브랜치를 두 자리에서 열 수 없다는 것과, 디렉터리를 지워도 관리 파일이 남는다는 것 — 도 반드시 들어가야 합니다.