#git reflog - HEAD 변경 이력을 볼 수 있다. 커밋은 어디 안 간다

1 minute read

LA in the Rearview Mirror

되돌릴 방법이 없으면 종종 걸음밖에 못 걷는다. 쫄아서. 하지만 복구 방법을 안다면 크게 걸을 수 있다. 과감해지는 거지. 과거를 볼 수 있다면 큰 걸음을 걸을 수 있다.

git reflog

저장된 HEAD 변경 이력을 보는 명령어. git을 쓰다보면 한 번은 찾아보게 된다. 언제? 뭔가 망했을 때. 커밋이 날아가진 않았을까 불안해하며.

HEAD 변경 이력만 가지고 있는데, 도움이 될까? 이것만 가지고 가능해? 가능하다. git은 persistent 자료구조를 구현했기 때문이다.

nil

master로 rebase 해보자.

nil

없어지는 것은 하나도 없다. C4, C5 잘 살아 있다. 다만 HEAD가 C5’를 가리키고 있어서 로그에 안 보일 뿐이다.

처음 rebase 설명 그림을 봤을 때, C4, C5가 C4’, C5’ 위치로 옮겨가는 건 줄 알았다. 아니다. 잘못 알았다. git 객체를 변경할 수 없다.

rebase를 잘못했다. 어떻게 돌릴 수 있을까? C5만 가리킬 수 있으면 된다. 커밋 id를 외우고 있으면 간단한데, 그럴리는 없겠지. rebase를 하면서 topic 브랜치도 C5’를 가리키게 됐다. 그래서 topic 브랜치도 도움이 안 된다.

reflog를 사용하면 된다. rebase를 하기 전 HEAD가 C5를 가리켰다. 이 정보를 사용하면 된다.

$ git reflog
8d029ef HEAD@{0}: rebase finished: returning to refs/heads/topic
8d029ef HEAD@{1}: rebase: c5
1256deb HEAD@{2}: rebase: c4
fc498f4 HEAD@{3}: checkout: moving from topic to fc498f4f7eeb9d345549bb2bd0441e7
9c16c89 HEAD@{4}: checkout: moving from master to topic

$ git reset --hard head@{4}

첫번째 열에 출력되는 커밋 id를 사용해도 되고 head@{4}와 같은 tree-ish를 사용해도 된다. rebase는 head@{3}부터 시작하므로 head@{4}로 reset하면 된다.

$ git log -g
commit 8d029eff92d307849ec2a9054afac7a7e54e56b3
Reflog: HEAD@{2} ...
Reflog message: rebase finished: returning to refs/heads/topic
...

    c5

commit 8d029eff92d307849ec2a9054afac7a7e54e56b3
Reflog: HEAD@{3} ...
Reflog message: rebase: c5
...

    c5

...

git log -g 명령어로 reflog와 커밋을 같이 볼 수 있다.

참고