LabHub
学习 学习路径 课程

Git 实战

活儿开了一半,紧急修复来了

在 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 을 언제 쓰는지 정리합니다.

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