Skip to content
isdnetworks
Go back

옛 클론과 잃어버린 저장소

(수정됨)

여러 머신에 흩어진 저장소 클론을 정리하다가 한 머신에만 남은 클론이 나왔다. 지워도 되는지를 판정해야 했다.

Table of contents

Open Table of contents

증상 — 내용이 전혀 다른 클론

그 클론과 원격의 현재 상태를 git ls-files | wc -l 로 비교하니 추적 파일 수부터 자릿수가 달랐고 공통 파일이 거의 없었다. 그 클론에만 있는 메모 파일이 여럿이라 자산이 남아 있는 것으로 보였다.

git log -1 을 보니 그 클론의 HEAD 가 붙잡고 있는 커밋이 한참 전이었다. 그 사이에 메모가 다른 위치로 이관되고 코드 저장소가 합쳐지고 문서가 새로 들어와 있었다.

원인 — 파일명 대조가 성립하지 않는 이유

같은 원격이 시점에 따라 성격이 달랐던 것이지 자산이 사라진 것이 아니었다. 파일 목록을 대조하는 방법은 서로 다른 시점을 비교하는 것이라 애초에 성립하지 않는다.

없어 보이는 파일은 사라진 것이 아니라 이력 안에 있다. 그러면 물음도 무엇이 없느냐가 아니라 그 시점을 복원할 수 있느냐가 된다.

해결 — 복원 가능성으로 바꾼 판정

두 가지 방법이 있었는데 옛 클론의 HEAD 를 원격에 새 브랜치로 올려 두는 것과 그 커밋이 다른 클론에서 이미 복원 가능한지 확인하고 지우는 것이다. 뒤쪽을 골랐다. 이유는 이미 이력 안에 든 커밋을 브랜치로 올리면 같은 것을 두 번 보존하는 셈이라서다. 대신 판정에 명령 둘을 다른 머신에서 돌려야 하는 수고를 감수했다. 그 커밋 객체가 다른 클론에 있는지 git cat-file -e <sha>^{commit} 으로 확인했다. 있었고 그 커밋이 현재 기본 브랜치의 조상인지도 git merge-base --is-ancestor <sha> master 로 확인했는데 조상이었다.

두 조건이 만족되면 그 시점의 파일 하나는 git show <sha>:<path> 로 트리 전체는 git checkout <sha> -- . 로 다른 클론에서 꺼낼 수 있다. 그러면 이 클론은 지워도 되는 것이 된다.

주의 — 두 확인이 각각 막는 것

cat-file -e 만 확인하면 어느 브랜치에도 이어지지 않은 고아 커밋일 수 있고 그것은 git gc 에서 사라진다. --is-ancestor 만 확인하면 어느 클론에서 확인했는지가 문제가 된다. git 공식 문서는 cat-file -e 를 객체가 존재하고 유효하면 0 으로 끝나는 검사로 merge-base --is-ancestor 를 첫 커밋이 둘째 커밋의 조상이면 0 으로 끝나는 검사로 설명하므로 둘은 서로 다른 것을 잰다.

지우려는 클론 자신에서 확인하면 순환이 되므로 남는 다른 클론에서 둘 다 확인해야 한다. 두 확인이 막는 것이 서로 달라서 하나만으로는 판정이 안 됐다.

이름과 전수 탐색

저장소 이름에 작업 공간을 뜻하는 말이 붙어 있어서 그 성격으로 분류하고 있었는데 그 원격은 시점에 따라 코드 저장소이기도 했다. 이름은 만들 때의 의도이지 지금의 성격이 아니다.

이 비대칭이 드러난 것은 머신들의 개발 트리를 전수로 훑어 관련 디렉터리를 나열했기 때문이다. 한 머신만 봤으면 원래 그런 것으로 넘어갔을 것이고 전수 탐색이 비교 대상을 만들었다.

정리


Share this post on:

Previous Post
환경 이름은 코드에 있는 걸 쓴다
Next Post
파일 안의 지문