git --amend 가 내 커밋을 지웠다 — reflog
두 세션이 한 저장소를 물고 있었다. 옆 세션의 amend 한 번에 내 커밋이 로그에서 사라졌다.
커밋을 두 개 만들었는데 로그에 하나만 있다.
한 저장소를 두 개의 작업 세션이 동시에 물고 있었다. 각자 다른 기능을 만드는 중이었고, 만질 파일도 겹치지 않게 나눠 잡았다. 내 쪽 작업이 끝나서 두 덩어리로 나눠 커밋했다. 첫 번째는 화면 로고, 두 번째는 에러 수집 로직. 커밋하고 확인차 로그를 봤다.
ac01348 감시 기록 — 개발 중 에러와 redirect 를 걸러낸다
4b616b2 통계 — 「진입 경로」 블록 신설 + QR 이름 통일
39e3a62 통계 — 「진입 경로」 블록 신설
2a63512 통계 — 입구 QR 을 화면에 넣고…
두 번째 커밋은 있는데 첫 번째가 없다. 로고 커밋이 통째로 사라졌다. git log --all 로 찾아도 안 나왔다.
reflog 에 한 줄이 남아 있었다
ac01348 HEAD@{0}: commit: 감시 기록… ← 내 두 번째
4b616b2 HEAD@{1}: commit (amend): 통계 — … ← 여기
a9ece37 HEAD@{2}: commit: 갤러리·운영 콘솔 로고 ← 내 첫 번째
39e3a62 HEAD@{3}: commit: 통계 — …
commit (amend).
옆 세션이 자기 커밋을 고치려고 --amend 를 눌렀는데, 그 사이에 내 커밋이 끼어 있었다.
--amend 는 「직전 커밋을 지우고 다시 만드는 것」이다. 그 세션이 생각한 「직전」은 자기가 만든 39e3a62 였고, 실제 직전은 내 a9ece37 이었다. HEAD 가 새 커밋 4b616b2 로 갈리면서 내 커밋은 어느 가지에도 안 붙은 채 떨어져 나갔다.
잃은 건 코드가 아니었다
처음엔 작업이 날아갔다고 생각했다. 그런데 코드를 열어보니 로고 변경이 멀쩡히 있었다.
amend 는 「지금 스테이징된 것 + 기존 커밋」을 합쳐서 새 커밋을 만든다. 내 변경은 이미 워킹 트리에 반영돼 있었으니, 옆 세션이 amend 할 때 내 파일까지 그 커밋에 흡수됐다. 실제로 그 커밋의 변경 목록에 내 파일 4개가 그대로 들어 있었다.
그러니까 사라진 건 커밋 메시지였다. 「로고를 왜 이렇게 바꿨나」를 적은 열 줄이 없어지고, 그 변경이 「통계 — 진입 경로 블록 신설」이라는 엉뚱한 제목 아래 들어가 있었다.
여기서 두 갈래였다.
되살리자 — reflog 에 커밋이 30일 남아 있으니 떼어내서 다시 붙일 수 있다. 이력이 정확해진다.
그냥 두자 — 되살리려면 히스토리를 고쳐야 하고, 그러려면 옆 세션의 커밋 세 개까지 건드려야 한다. 그 세션이 아직 살아 있으면 그쪽 작업과 충돌한다.
얻는 건 커밋 메시지 하나고, 잃을 수 있는 건 남의 진행 중 작업이다. 후자를 골랐다. 코드는 맞고, 이력이 조금 섞였을 뿐이다.
그래서 뭘 바꿨나
이번엔 아무것도 안 고쳤다. 대신 협업 규칙에 빠진 구멍을 하나 찾았다.
여러 세션을 동시에 돌릴 때의 규칙은 이미 갖고 있었다. 「같은 파일을 두 세션이 만지지 않는다」, 「스테이징은 파일을 하나씩 지정한다」, 「git add . 을 쓰지 않는다」. 오늘 그 규칙들은 다 지켜졌다 — 파일도 안 겹쳤고, 나도 파일을 하나씩 지정해서 담았다.
그런데 커밋을 만든 다음의 규칙이 없었다. --amend 는 이미 만들어진 커밋을 건드리는 명령이라, 「무엇을 담을까」에 대한 규칙으로는 막히지 않는다.
그리고 이건 조용히 실패한다. amend 를 누른 쪽은 아무 경고도 못 받는다. 밀려난 쪽도 로그를 유심히 보지 않으면 모른다. 나도 커밋 두 개를 만들고 개수를 세다가 우연히 발견했다.
혼자 쓰는 저장소에서 안전한 명령이 여럿이 쓰면 안전하지 않다. --amend, rebase, reset 처럼 「이미 만든 것을 다시 만드는」 명령이 전부 여기 해당한다. 옆자리가 그 사이에 뭘 올렸는지 모르는 채로는 쓸 수 없다.