git reflog 명령어로 레퍼런스의 기록을 봅시다.

GIT 2022. 11. 19. 01:52

 git reflog 명령어로 브랜치나, 다른 레퍼런스들이 업데이트 된 기록들을 봅시다. 이를 이용하면, 실수로 reset hard를 하고 push force를 한 커밋도 복구할 수 있습니다. 여기에서는 상황을 토대로, 이럴 때 reflog를 쓰겠구나. 정도만 알아보겠습니다.

 


 먼저, 제 로컬 레포에는 38분전에 커밋된 3e7d8172와 42분전에 commit된 것이 있습니다. 38분에 커밋된 것은 1.txt가 변경이 된 기록을 가지고 있겠네요.

 

 다음에, git reset --hard HEAD^를 입력했습니다. --hard가 들어갔기 때문에, 버전을 돌릴 때 파일까지도 같이 돌리게 됩니다. 예를 들어, 최신 커밋이 1.txt에 ABC가 추가된 것이라고 해 보겠습니다. git reset --hard HEAD^는 1.txt에 ABC가 추가된 것을 취소합니다. 즉, 제거해 버립니다. 위험하겠는데요.

 

 

 git reset HEAD^ 후에 로컬 main의 HEAD는 43분전에 커밋한 것을 가리키고 있습니다.

 


 git_test_ori는 reset HEAD^를 하기 전의 복사본, git_test는 reset HEAD^를 한 스냅샷입니다. git bash에서 diff 명령어를 사용해 봅시다. -r 옵션과 --color 옵션을 주었는데요. -r은 재귀적으로 비교하는 것입니다.

 

 git_test_ori와 비교해서 git_test에 무엇이 추가되었는지 알 수 있는데요. HEAD의 logs와 refs/heads/main의 log에 무언가 추가되었음ㅇ르 알 수 있어요. moving to HEAD^라는 로그가 찍혀있습니다.

 

 

 다음에, refs/heads/main가 가리키는 hash의 정보가 바뀌었음을 볼 수 있어요. 그 외에 1.txt에 BUSAN이라는 것이 빠졌음을 볼 수 있는데요. 이는, --hard 옵션을 주어서 reset을 했기 때문입니다. 그 외에 다른 meta 정보들은 변하지 않았습니다. 예를 들자면, 객체 정보들을 저장할 것만 같은 objects도 변한 것이 없습니다. diff에 뜨지도 않았기 때문입니다. log도 안 변했고요. 이를 토대로, 내가 실수로 로컬에서 삭제한 커밋을 복구하는 데 도움이 되는 정보가 있다는 추론을 할 수 있습니다.

 

 예를 들어, 3e라는 디렉토리를 보면 7d8172.. 라는 이상한 이름의 파일이 있습니다.

 

 

 이를 git show로 보면, commit에 대한 메타 데이터를 저장했음을 볼 수 있습니다.

 

 

 다른 파일에 대해서도 조회를 해 봅시다. aa 디렉토리 밑에는 337b.. 가 있는데요. git show aa33으로 조회해 보면, 파일을 저장했음을 알 수 있어요. 단지 HEAD가 가리키는 포인터와 1.txt만 변경이 있었기 때문에, reset을 하기 직전의 커밋을 알면 복구를 할 수 있습니다.

 


 git reflog를 봅시다. 레퍼런스 log도 reflog로 볼 수 있습니다. 그러니, HEAD를 이동한 기록도 남아 있을 겁니다. 보면 알 수 있듯, moving to HEAD^가 보입니다. 그 이전에 발생한 이벤트가 commit: .이였는데요. 3e7d817에서, 과거로 1 커밋만큼 이동한 것이 16ebf71임을 알 수 있어요. 

 

 

 다시 한 번 확인해 볼까요? reset 을 한 직후의 커밋이 16eb710입니다. reset을 한 게 가장 최근의 이벤트이고, 그 이전의 이벤트는 리셋하기 전이였으므로, 3e7d817을 가져오면 됩니다.

 

 

 git reset --hard 3e7d817을 입력하겠습니다.

 

 그러면, reset --hard HEAD^로 실수로 돌려놨던 커밋을 복구할 수 있습니다. 리셋을 하기 전 커밋 해시 기록과, 내가 한 행동이 남아 있었기 때문에, reflog로 볼 수 있었던 셈입니다. 즉, reflog는 쉽게 말해, 레퍼런스의 기록을 본다고 이해하시면 편하겠습니다.