LabHub
배우기 러닝패스 코스

Git in Practice

A Hotfix Lands While Your Work Is Half Open

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

저장소 하나에 작업 디렉터리를 셋까지 붙였다 정리합니다. 끝나면 stash 없이 브랜치를 갈아타는 손이 생기고, 작업 사본이 남긴 관리 파일을 어떻게 치우는지 알게 됩니다.

왜 중요한가

브랜치를 바꾸는 일이 왜 이렇게 번거로운지 생각해 보면, 작업 트리가 하나뿐이기 때문입니다. 저장소는 객체와 브랜치 참조를 들고 있고, 작업 트리는 그중 한 커밋을 펼쳐 놓은 사본입니다. 펼쳐 놓는 자리를 늘릴 수 있다면 갈아타기 자체가 필요 없어집니다. git worktree 가 정확히 그 일을 합니다. 다만 브랜치 참조는 저장소가 하나로 들고 있어서, 같은 브랜치를 두 자리에서 열려고 하면 git 이 막습니다. 이 제약을 이해하는 것이 이 실습의 절반입니다. 나머지 절반은 정리입니다 — 디렉터리만 지우면 관리 파일이 남고, 그 자리가 prunable 인 채로 계속 목록에 뜹니다.

단계

  1. /root/gitx4/repo 에 커밋 3개짜리 저장소를 만들고 release 브랜치를 땁니다.
  2. release/root/gitx4/rel 에 작업 사본으로 붙입니다.
  3. main/root/gitx4/dup 에 한 번 더 붙여 보고, 거절 메시지를 notes/dup.txt 에 남깁니다.
  4. repo 에 저장하지 않은 변경을 남겨 둔 채 /root/gitx4/hothotfix 브랜치를 새로 만들어 붙이고, 거기서 hotfix.txt 를 커밋합니다.
  5. git worktree list --porcelainnotes/list.txt 로 남깁니다.
  6. /root/gitx4/tmp 를 붙였다가 디렉터리만 rm -rf 하고, prunable 표시와 prune 결과를 notes/prune.txt 에 남깁니다.
  7. /root/gitx4/usb 를 붙여 lock 을 걸고, remove 가 거절하는 것을 notes/lock.txt 에 남긴 뒤 풀어서 지웁니다.
  8. notes/report.md 에 worktree · stash · clone 을 언제 쓰는지 정리합니다.

참고

저장소와 릴리스 브랜치 만들기

/root/gitx4/repo 에 커밋 3개짜리 저장소를 만들고 release 브랜치를 땁니다.

git init -b main 으로 시작합니다. 이 이미지에는 전역 신원이 없으니 저장소마다 git config user.emailuser.name 을 정해야 커밋이 됩니다. 커밋 시각은 GIT_AUTHOR_DATEGIT_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/hothotfix 브랜치를 새로 만들어 붙이고, 거기서 hotfix.txt 를 커밋합니다.

repodraft.txt 를 만들어 두세요 — 커밋도 stash 도 하지 않습니다. 그 상태에서 git worktree add -b <새브랜치> <경로> <기준> 으로 자리를 하나 더 만들고, 그 디렉터리 안에서 커밋합니다. 끝나고 repo 를 보면 draft.txt 가 그대로 있습니다.

지금 자리가 몇 개인지 기계가 읽는 형식으로

git worktree list --porcelainnotes/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 을 언제 쓰는지 정리합니다.

세 방법이 각각 무엇을 아끼고 무엇을 잃는지로 갈라 쓰세요. 이번에 직접 본 것 두 가지 — 같은 브랜치를 두 자리에서 열 수 없다는 것과, 디렉터리를 지워도 관리 파일이 남는다는 것 — 도 반드시 들어가야 합니다.