HyunJun 기술 블로그

Git Reset, Revert 본문

Git

Git Reset, Revert

공부 좋아 2024. 7. 11. 12:25
728x90

Git reset, revert

git에서 commit history의 commit 내역을 제거하고 싶거나 되돌리고 싶을 때가 있다. 단순 checkout의 경우 commit 내역을 삭제하는 것이 아닌 단순히 보는 시점을 다르게 하는 것이다.

git reset과 git revert의 차이

git reset과 rever는 git을 삭제하는 데에 있어서 목표, 개념적인 차이가 있다.

  • git reset: 특정 commit을 선택한다. 해당 commit 이후의 내역들은 모두 삭제된다. 삭제했다는 이력은 남기지 않는다.
  • git revert: 특정 commit을 선택해 삭제한다. 하지만 최신 commit에 특정 commit을 삭제했다는 내역을 추가한다.
    • 특정 하나의 commit만을 삭제하므로, A - B - C - D - E라는 commit history에서 C, D, E를 삭제해 B의 시점으로 돌아가고 싶은 경우, revert E, revert D, revert C를 해야 한다.

 

git reset

git reset --옵션 [커밋 해시값]

option

  • —hard
    • reset target commit의 이후의 commit 내역들을 완전히 삭제한다.
  • —mixed
    • reset target commit의 이후의 commit 내역들을 Working Directory로 이동한다.
  • —soft
    • reset target commit의 이후의 commit 내역들을 Staging Area로 이동한다.

 

💡 commit history는 시간 순서에 따라 commit들을 연결한 기록이다. 해서 어느 한 지점의 commit을 삭제하게 되면 그 이후의 commit들에 문제가 생길 여지가 있다. 해서 reset의 컨셉은 사용 시 애초에 선택한 commit 이후의 commit들을 모두 지우는 것이다.

 

—soft

—soft를 사용하여 reset을 사용해 보자, 예를 들어 아래의 commit history에서 add file c를 삭제하고자 한다.

 

  1. add file b 즉, 4f16df... 을 타깃 커밋 해시값으로 잡아야 한다.
  2. add file b 이후 커밋 히스토리의 모든 내역은 삭제된다. 즉, add file d인 commit까지 삭제된다.
git reset --soft 4f16df
git log

 

soft를 사용했으므로 해당 내역들은 staging area로 이동하게 된다.

 

고로 —soft를 사용하면 Staging Area로 이동하고, 삭제한 내용들을 다시 commit 하여 쉽게 복구할 수 있다.

 

위와 같은 특징으로 git commit history는 삭제됐지만 로컬 내에서 파일은 삭제되지 않았다.

 

 

 

staging area 조차에서도 삭제하고 싶다면, 아래의 예시처럼, restore를 사용하면 된다.

git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   c
	new file:   d

git restore --staged c
git restore --staged d

 

Untracked 조차도 보지 않으려면, c, d 파일을 물리적으로 삭제하거나, .gitignore에 등록해 주면 된다.

 

즉, git reset --soft 명령어는 다음과 같은 특징을 가진다.

  1. Repository의 내역 변경: 지정한 커밋으로 HEAD를 이동시키며, 해당 커밋 이후의 커밋 내역은 삭제된다.
  2. 스테이징 영역 유지: 스테이징 영역(Staging Area)에 삭제된 변경 사항은 그대로 유지된다. 즉, 이전에 스테이징된 변경 사항들이 그대로 남아 있다.
  3. 작업 디렉터리 변경 없음: 작업 디렉터리(Working Directory)의 실제 파일들은 영향을 받지 않는다. 변경 사항이 그대로 유지된다. 따라서, git reset --soft를 사용하면 Git repository의 커밋 내역만을 수정하면서, 로컬의 실제 파일 변경 사항이나 스테이징된 변경 사항은 그대로 보존하게 된다.

—hard

그렇다면 git reset --hard를 써보자 현재 남은 2개의 commit history 중, add file b를 삭제해 보도록 하겠다. 즉, add file b 바로 전 커밋인, add file a, d3472d 커밋에 —hard를 써보자.

 

 

git reset --hard d3472d

로그가 잘 삭제된 것을 확인할 수 있으며 이번에는 실제 파일까지 삭제되었다.

 

 

 

 

git reflog

git reflog는 우리가 한 행동(행위)에 대해서 로그(해시값)를 가지고 있다. 해서 해당 로그를 지우게 되면 우리가 커밋 하거나 reset 한 내용을 되돌릴 수 있다. 심지어 —hard로 삭제한 commit까지도 살릴 수 있다.

reflog를 사용하여 로그를 확인해 보자.

git reflog

 

 

reset —hard와, reset —soft를 사용했던 행동들을 모두 취소해 보자. 이때 주의해야 할 점은 reflog를 reset 하면 reset의 특징과 마찬가지로 삭제할 바로 전 로그를 선택해야 한다.

git reset --hard HEAD@{2}

왼쪽은 reset을 하기 전 기록이고, 오른쪽은 행동을 reset 한 후의 결과이다. 여기서 특이점은 c, d 파일을 —soft로 reset 했을 때 restore를 사용하여 staging area에서 뺀 후, 물리적으로 c, d 파일을 삭제했는데도 해당 파일들이 생성되었다.

 

 

 

방금 행동을 삭제한 행동까지 기록이 되어있다.

 

 

git revert

revert는 reset보다 조금 안전한 방식이다. 또한 commit history를 삭제하지 않고 오히려 삭제했다는 것을 명시할 새로운 커밋으로 생성한다.

git revert [커밋 해시값]

revert는 삭제할 해당 타깃 commit id를 바로 선택하면 된다. 일단 log를 확인해 보자.

 

 

add file c를 삭제해 보도록 하자.

git revert bc567d

revert는 삭제한 기록을 남기는 새로운 commit을 생성한다고 말했다. 즉 revert를 사용하면 새로운 커밋 메시지를 입력해 주어야 한다.

 

 

ls로 확인 시 정확히 c 파일이 사라졌다.

 

하지만, log 확인 시 add file c라는 커밋은 남아있고, Revert “add file c”라는 커밋이 생겼다. 바로 이 커밋이 add file c 커밋을 삭제했다고 명시한 커밋이다.

 

💡 reset은 각각의 삭제되는 의존된 커밋을 다 삭제하기에 컨플릭트(충돌)을 잘 내지 않지만 커밋 히스토리가 망가지게 된다.

revert는 컨플릭트(충돌)를 낼 가능성이 많지만 잘만 사용한다면 기존의 커밋 히스토리를 망가뜨리지 않는다.

 

Git Graph 확인하기

commit history를 잘 확인하기 위해서는 git graph를 확인하는 것이 중요하다. VS Code Extension git graph 설치하면 깃 커밋 히스토리를 편리하게 확인할 수 있다.

728x90
Comments