Git 실전 · 내 컴퓨터에선 되는데요 · 실습
내 컴퓨터에선 되는데요 — 서브모듈이 옛 커밋에 꽂혀 있었다
목표
라이브러리 저장소를 부모 저장소에 서브모듈로 꽂고, 갱신을 부모에 커밋하지 않았을 때
동료가 옛 코드를 받는 사고를 직접 만들어 봅니다.
왜 중요한가
서브모듈에서 나는 사고는 거의 전부 한 가지 오해에서 나옵니다 — 부모가 브랜치를
가리킨다는 오해입니다. 부모의 트리에 들어가는 것은 모드 160000 인 항목 하나이고
값은 커밋 해시입니다. 브랜치가 아니라 커밋이므로, 서브모듈은 항상 detached HEAD 로
체크아웃되고, 라이브러리에 새 커밋이 쌓여도 부모는 저절로 따라가지 않습니다. 이
실습은 그 사실을 설명으로 듣는 대신 이력에서 직접 꺼내 보게 합니다. 그리고 git clone
이 기본으로 서브모듈을 받지 않는다는 것까지 확인하면, "CI 에서만 빌드가 깨진다" 는
흔한 증상이 왜 생기는지가 한 번에 정리됩니다.
단계
1. /root/gitx5/lib 에 커밋 2개짜리 라이브러리 저장소를 만듭니다(version.txt 가1.0.0 에서 1.1.0 으로).
2. /root/gitx5/app 을 만들고 lib 를 vendor/lib 자리에 서브모듈로 꽂습니다.
첫 시도가 막히는 것을 notes/protocol.txt 에 남깁니다.
3. 부모가 기억하는 것이 무엇인지 notes/pointer.txt 에 남깁니다.
4. lib 에 1.2.0 커밋을 쌓고 서브모듈을 그 커밋으로 옮긴 뒤, detached HEAD 와submodule status 의 앞 글자를 notes/detached.txt 에 남깁니다.
5. 그 갱신을 부모에 커밋합니다.
6. lib 에 1.3.0 을 쌓고 서브모듈만 옮긴 채 부모는 커밋하지 않은 상태에서/root/gitx5/clone 을 떠, 받은 쪽이 몇 번을 보는지 notes/accident.txt 에 적습니다.
7. --recurse-submodules 없이 /root/gitx5/clone2 를 떠서 앞 글자 - 를 만들고,
네 가지 앞 글자를 notes/status.txt 에 정리합니다.
8. notes/report.md 에 서브모듈을 쓸 때의 규칙을 정리합니다.
참고
- 이 이미지에는 git 신원이 전역으로 없습니다. 저장소를 만들 때마다
- 커밋 시각은
GIT_AUTHOR_DATE와GIT_COMMITTER_DATE로 고정합니다. - 흔한 실수: 2단계에서 첫 시도가 막히면 실습이 잘못된 줄 알고 넘어가는 것입니다.
- 흔한 실수: 6단계에서 부모를 커밋해 버리는 것입니다. 커밋하지 않은 상태 그대로
git config user.email 과 user.name 을 지정하세요.
막히는 것이 정상이고, 그 이유를 아는 것이 이 단계의 과제입니다.
clone 을 떠야 사고가 재현됩니다.
단계 8개
- 공통 라이브러리 저장소 만들기
- 로컬 경로 서브모듈이 기본으로 막힌다
- 부모의 트리에 들어간 한 줄
- 서브모듈은 언제나 detached HEAD 다
- 갱신을 부모에 커밋한다
- 커밋하지 않은 갱신은 나만의 것이다
- 앞 글자 한 칸이 말하는 네 가지
- 서브모듈을 쓸 때의 규칙