Image
CI\CD/Git

[Git] reflog를 활용한 삭제된 브랜치 복구 방법

reflog란?

reflog란 git에서 가리키는 referenced commit이 변경된 내역이다. reflog를 기록하는 것은 대표적으로 HEAD와 branch 두가지이다.

 

HEAD의 reflog

HEAD의 reflog 경우 새로운 커밋이 생기거나, branch가 switch 될 때마다 해당 브랜치의 가장 최신 커밋으로 reference가 바뀌게 된다.

 

예를 들어 master 브랜치에 test, test2란 커밋을 만들고, feature-branch 브랜치를 새로 만든다음 feature-branch에서 new commit 커밋을 새로 만들면 다음과 같이 reflog가 쌓이게 된다.

$ git reflog show HEAD

d42e22f (HEAD -> feature-branch) HEAD@{0}: commit: new commit  # 4. feature-branch에서 new commit 커밋 생성
6e3a608 (master) HEAD@{1}: checkout: moving from master to feature-branch  # 3. 브랜치 변경
6e3a608 (master) HEAD@{2}: commit: test2  # 2. master branch에 test2 커밋 생성
b2f3c96 HEAD@{3}: commit (initial): test  # 1. master branch에 test 커밋 생성

 

branch의 reflog

branch의 reflog는 해당 브랜치의 commit이 변경되었을 때만 기록된다.

 

예를 들어 master 브랜치에 test, test2란 커밋을 만들고, feature-branch 브랜치를 새로 만든다음 feature-branch에서 new commit 커밋을 새로 만들면 master 브랜치의 커밋인 test, test2는 master 브랜치의 reflog에만 나타나고 feature-branch 브랜치의 reflog는 feature-branch 브랜치에서만 나타난다.

$ git reflog show master        

6e3a608 (master) master@{0}: commit: test2
b2f3c96 master@{1}: commit (initial): test


$ git reflog show feature-branch 

d42e22f (HEAD -> feature-branch) feature-branch@{0}: commit: new commit
6e3a608 (master) feature-branch@{1}: branch: Created from HEAD

 

 

reflog를 이용해 삭제된 브랜치 복구하기

위의 상황에서 만약 feature-branch가 삭제되었다고 해보자.

$ git switch master
'master' 브랜치로 전환합니다

$ git branch -D feature-branch
feature-branch 브랜치 삭제 (과거 d42e22f).

 

삭제된 브랜치의 reflog는 더이상 볼 수 없다.

$ git reflog show feature-branch 
fatal: 애매한 인자 'feature-branch': 알 수 없는 리비전 또는 작업 폴더에 없는 경로.
경로와 리비전을 구분하려면 다음과 같이 '--'를 사용하십시오:
'git <명령> [<리비전>...] -- [<파일>...]'

 

하지만 HEAD의 reflog는 그대로 남아있다. 우리는 이 로그에서 feature-branch의 마지막 커밋인 d42e22f 을 확인할 수 있다.

$ git reflog show HEAD          

6e3a608 (HEAD -> master) HEAD@{0}: checkout: moving from feature-branch to master
d42e22f HEAD@{1}: commit: new commit
6e3a608 (HEAD -> master) HEAD@{2}: checkout: moving from master to feature-branch
6e3a608 (HEAD -> master) HEAD@{3}: commit: test2
b2f3c96 HEAD@{4}: commit (initial): test

 

이 커밋은 .git/objects 폴더에 저장되어 있기 때문에 언제든지 커밋을 체크아웃 함으로써 복구가 가능하다.

$ git checkout d42e22f
Note: switching to 'd42e22f'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD의 현재 위치는 d42e22f new commit

 

따라서 위와 같이 checkout 하면 feature-branch의 마지막 커밋이 복구되며 이 checkout된 커밋을 다시 branch로 만드는 switch -c 명령어를 통해 브랜치를 복구할 수 있게된다.

$ git switch -c feature-branch
새로 만든 'feature-branch' 브랜치로 전환합니다

 

 

git reflog를 통해 삭제된 브랜치의 복구가 가능한 이유

git은 commit, tree, blob를 .git/objects 폴더에 저장한다. 브랜치가 삭제되더라도 이곳에 저장된 commit, tree, blob는 삭제되지 않는다. 따라서 commit hash 값만 있다면 브랜치가 삭제되더라도 언제든지 commit을 복구할 수 있다.

 

만약 이것에 대해 궁금하다면 아래 두 글을 추가로 읽도록 하자.

  • commit의 동작원리
 

[Git] Git의 저장 단위인 commit의 동작 원리에 대해 알아보자

Git의 기본 저장 단위 Commit Commit은 Git의 기본 저장 단위이다. 우리는 Commit을 파일들에 대한 스냅샷이라고도 부르며, Commit은 Commit을 찍은 시간의 파일들의 상태에 대해 저장한다. Commit은은 tree, pa

kotlinworld.com

  • git이 파일을 저장하고 복구하는 원리
 

[Git] Git은 어떻게 파일을 저장하고 복구하는가? git의 기본 파일 단위인 blob와 Hashing의 관계에 대

변경사항을 압축해 저장하는 objects 폴더 objects 폴더 내부를 보면 두 글자 이름을 가진 폴더들이 있다. objects 폴더는 git의 모든 변경사항을 압축해서 파일들을 각 폴더 내부에 저장한다. 이 내부

kotlinworld.com

 

 

git reflog의 한계점

git은 항상 로컬 브랜치의 reflog만을 저장한다. 따라서 만약 GitHub나 GitLab 등의 remote 브랜치를 삭제했다면 복구가 불가능하다. 물론 해당 브랜치를 체크아웃 한 적이 있다면 복구가 가능하다.

 

또한 git은 항상 모든 파일을 쌓아두지 않는다. 따라서 브랜치가 삭제된 후 일정 이상의 시간이 지났을 경우 복구가 불가능하다.

 

 

반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com