Git 이력을 다시 쓴 뒤 스크린샷 검사가 깨졌습니다
작성자 정보를 고치며 커밋 154개의 해시가 바뀌었습니다. 검사가 읽던 reviewed-at과 커밋 메시지의 참조를 새 해시로 옮기고, 과거 일지의 해시는 그대로 남겼습니다.
들어가며
커밋 작성자에 옛 이메일 주소가 남아 있어 filter-branch로 이력을 다시 썼습니다. 물타기 계산기 122개와 루트 32개, 모두 154개의 커밋이 대상이었습니다.
그 뒤 스토어 스크린샷 검사인 fresh.sh가 fatal: bad object로 실패했습니다. 검사가 기준으로 삼는 docs/store/shots/reviewed-at에 재작성 전 커밋 해시가 남아 있었습니다.
사람이 확인한 화면을 해시로 기억하고 있었습니다
reviewed-at에는 스토어 스크린샷을 사람이 검토한 시점의 커밋을 적어둡니다. fresh.sh는 이 값을 읽어 그 뒤 화면 코드가 바뀌었는지 확인합니다. 화면에 영향을 주는 변경이 있다면 스크린샷을 다시 확인해야 하기 때문입니다.
저장한 해시를 읽는 명령은 git log -1 <해시>였습니다. 작성자 정보를 바꾸면서 커밋 해시는 달라졌지만 파일 안의 문자열은 그대로였습니다. 검사는 화면 변경을 비교하기도 전에 기준 커밋을 찾지 못하고 멈췄습니다.
스크린샷이 낡아서 실패한 게 아니라, 비교를 시작할 커밋을 잃은 상태였습니다.
파일과 커밋 메시지를 함께 옮겼습니다
백로그에는 이미 주의사항이 있었습니다.
이력을 다시 쓰면
reviewed-at도 어긋난다
그날 새벽에는 이 파일이 깨질까 봐 잘못 섞인 커밋을 되감지 않았습니다. 그렇게 피했던 문제를, 뒤이어 작성자 정보를 고칠 때는 놓쳤습니다.
두 번째 재작성에서는 filter-branch의 map으로 옛 해시와 새 해시를 연결했습니다. reviewed-at 파일뿐 아니라, 그 해시를 본문에 적어둔 커밋 메시지 둘도 함께 옮겼습니다.
반면 작업 일지에 적힌 옛 해시는 그대로 남겼습니다. 일지는 당시 어떤 커밋을 기록했는지 보존하는 문서였고, 자동 검사가 그 값을 현재 이력에서 조회하는 것은 아니었습니다.
다음 재작성에서 먼저 확인할 것
해시를 저장한 파일을 찾을 때는 다음 검색을 출발점으로 삼기로 했습니다.
git grep -E '[0-9a-f]{7,40}'
다른 용도의 문자열도 나오므로 각 값을 어떤 도구가 읽는지 살펴야 합니다. 커밋 메시지 안의 참조는 이 검색에 나오지 않아 따로 확인할 항목으로 적었습니다.
검사 쪽에서는 기준 커밋이 없는 경우를 구분해 알리는 방식이 필요했습니다. 예를 들면 화면 변경을 비교하기 전에 다음과 같이 확인할 수 있습니다.
git cat-file -e "$REVIEWED_AT^{commit}" 2>/dev/null || {
echo "reviewed-at 의 해시가 이 이력에 없다 — 이력이 다시 쓰였나?" >&2
exit 1
}
위 코드는 보완 예시로 남겼습니다.
마치며
이번에 적용한 수정은 reviewed-at과 커밋 메시지의 참조를 옮기는 데까지였고, 과거 일지는 그대로 뒀습니다. 현재 커밋을 조회하는 데 쓰는 해시와 당시 작업을 기록한 해시를 구분해 처리했습니다.