Reset

Violet_Evgadn·2023년 9월 7일
0

Git

목록 보기
24/33

Reset

Reset이란?

Git을 사용하다 보면 여러 개의 커밋을 생성한다.
이렇게 여러 개의 커밋을 생성하는 도중 특정 커밋 이전 상황으로 돌아가고 싶을 수도 있을 것이다.

예를 들어 A라는 기능을 만들었는데 법적 규제 때문에 A 기능을 사용할 수 없게 되었다. 이때 개발자는 A라는 기능을 개발하기 전 상황으로 돌아가야 할 것이다.

이때 활용하는 Git의 기능이 Reset이다.
(참고로 Git Reset 활용 시 Untracked 파일은 건드리지 않는다)

Git Reset 모드

Soft, Mixed

Soft와 Mixed 모드는 지정한 커밋 상태로 커밋 이력을 되돌리지만 워킹 디렉터리에 작업했던 내용은 그대로 유지시킨다.

그렇다면 동일한 동작 과정인 것 같은데 왜 Soft와 Mixed로 나누어놨을까?

Soft와 Mixed의 차이는 아래와 같다.

  • Soft : Reset 시킨 커밋과 비교했을 때 새로 생성된 파일을 Staging 상태로 둠
  • Mixed : Reset 시킨 커밋과 비교했을 때 새로 생성된 파일은 Unstaging 시킴

Hard

Hard Reset은 특정 커밋과 현재 상황을 완전히 일치시킴으로써 깔끔하게 모든 중간 작업물들을 리셋 시키는 것을 의미한다.

다른 git reset 옵션은 명령어를 수행하더라도 워킹 디렉터리에는 작업했던 내용이 남아 있다.
하지만, 유일하게 Hard 옵션은 커밋과 더불어 작업했던 내용까지 워킹 디렉터리에서 초기화시킨다.

이러한 점에서 git reset의 --hard 옵션은 reset 명령을 위험하게 만드는 유일한 옵션이다.

예시를 통해 본 Hard, Mixed, Soft

만약 내가 A 파일을 커밋 했었는데 git reset을 통해 A 파일의 작업물을 커밋에서 제외하고 싶다 가정하자.

각각의 옵션으로 git reset을 시키면 아래와 같은 결과가 나온다.

  • --mixed : A 파일이 삭제되지는 않지만 Unstaging 상태로 변경됨

    • 만약 추후 A 파일을 다시 커밋 하고 싶다면 git add를 통해 Staging 할 필요가 있음
    • git reset의 Default Option
  • --soft : A 파일이 삭제되지 않고 Staging된 상태로 변경됨

    • 단순히git commit만 수행하더라도 A 파일은 Staging된 상태이므로 커밋에 반영된다.
    • 단, git reset을 수행했으므로 현재 HEAD가 가리키는 커밋에는 A 파일이 존재하지 않을 것이다.
  • --hard : A 파일이 현재 커밋에 존재하지 않고 워킹 디렉터리에서도 삭제되어 있음

표로 보는 Hard, Mixed, Soft

구분SoftMixed(기본)Hard
HEAD초기화초기화초기화
스테이지유지초기화초기화
Working Tree 변경사항유지유지초기화

IntelliJ에서 git reset 수행

0. 새로운 파일을 생성한 뒤 커밋

Reset 수행

Git Log > Reset 후 상태로 만들고 싶은 커밋 선택 > 마우스 오른쪽 클릭 > Reset Current Branch to Here...을 클릭하면 git reset을 수행할 수 있다.

그럼 아래와 같은 창이 나올 것이다.

이제 하나씩 클릭해서 어떻게 동작하는지 알아보자.

Soft 선택(--soft 옵션)

일단 현재 main 브랜치의 HEAD가 가리키는 커밋은 Cherrypick으로 가져올 커밋이라는 메시지를 가진 커밋으로 성공적으로 Reset 되었음을 확인할 수 있다.
(Git Reset 테스트를 위한 파일 커밋 메시지를 가진 커밋이 삭제됨)

이제 reset_test_file.md 파일을 보자.
이미지에서 볼 수 있듯 초록색 글씨로 되어 있는 것을 볼 수 있는데 이는 IntelliJ에서 "Staging된 파일이다"라는 것을 나타낸다.

그렇다면 바로 Commit 할 수 있을까?
한 번 commit 해보자.

딱히 git add를 통해 Staging 하지도 않았는데 커밋이 가능함을 볼 수 있다.

커밋 시킨 뒤 Mixed reset을 수행해 보자.

Mixed 선택(--mixed 옵션)

마찬가지로 정상적으로 git reset 되었음을 확인할 수 있다.

하지만 큰 차이점이 있는데 바로 reset_test_file.md 파일명이 빨간색 글씨로 되어 있다는 것이다.

IntelliJ에서 빨간색 글씨는 해당 파일이 Staging 되지 않은 Untracked 파일임을 의미한다.
그렇다면 Commit 시 어떤 동작이 수행될까? 커밋 해보자.

--soft 옵션과 다르게 reset_test_file.md 파일이 커밋 후보 파일에 없음을 알 수 있다.
즉, --mixed 옵션을 사용하면 새로 생성된 파일은 Unstaging 됨을 확인할 수 있다.

마지막으로 --hard 옵션을 테스트하기 위해 git add를 통해 Staging 시킨 뒤 커밋 시키고 다시 git reset을 수행하자.

Hard 옵션(--hard 옵션)

git reset이 정상적으로 수행되었다.

하지만 큰 차이점이 있는데 분명 README.md 파일과 settings.gradle 파일 사이에 있던 reset_test_file.md 파일이 아예 워킹 디렉터리에서 삭제되었음을 볼 수 있다.

이런 상황이 된다면 (원격 저장소에 해당 파일을 Push 하지 않았다면) 삭제된 파일을 복구할 방법이 없다.
따라서 --hard 옵션을 사용할 경우 매우 큰 주의를 기울이며 사용하도록 하자.


CLI를 통한 git reset

# 방법 1 : 커밋 ID 활용
git reset [--hard | --mixed | --soft] <커밋 ID>

# 방법 2 : HEAD 예약어 활용
git reset [--hard | --mixed | --soft] HEAD~<숫자> # 방법 2-1
git reset [--hard | --mixed | --soft] HEAD^<숫자> # 방법 2-2

커밋 ID를 통한 reset

단순히 내가 Git Reset을 통해 돌아가고 싶은 커밋 ID를 뒤에 입력해 주면 된다.

필자는 이 방법을 선호하는데 아래에서 설명할 HEAD 활용 방법 같은 경우 몇 번째 커밋인지 숫자를 세야 하는 것도 있고 직접 수행하기 전까지 어떤 결과가 나올지 모호한데 커밋 ID를 활용하면 확실하고 안전하게 reset 시킬 수 있기 때문이다.

HEAD를 활용한 reset

Git에서는 HEAD에 ^ 기호나 ~ 기호 뒤에 숫자를 붙임으로써 현재 HEAD가 가리키는 커밋을 기준으로 특정 커밋을 가리킬 수 있다.(상대 참조)

^~의 의미는 아래와 같다.

  • HEAD~<숫자> : n 번째 부모 커밋

  • HEAD^ : 현재 커밋의 부모 브랜치

위 2가지 상황에서 부모 커밋은 모두 "현재 브랜치"를 기준으로 찾아야 한다.

벌써부터 어렵다. 이미지를 통해 알아보자.

현재 7번 커밋이 HEAD라고 가정하자.
과연 HEAD^은 어떤 커밋을 가리킬까?

이를 파악하기 위해선 현재 브랜치가 어디인지를 알아야 한다.
만약 보라색 브랜치가 현재 브랜치라면 4번 커밋을, 노란색 브랜치가 현재 브랜치라면 6번 커밋을 나타낼 것이다.

만약 3번이나 5번 커밋과 같이 부모가 아닌 N번째 조상 커밋을 나타내고 싶다면 ~를 사용하면 될 것이다.
HEAD~2를 활용하면 보라색 브랜치가 현재 브랜치일 경우 3번 커밋을, 노란색 브랜치가 현재 브랜치라면 5번 커밋을 나타낼 수 있다.

위 설명을 보면 알겠지만 HEAD를 활용해 특정 커밋을 나타내기엔 너무 어렵고 모호하며 현재 상황에 큰 의존성을 가진다.
그러니 특수한 상황이 아니라면 웬만하면 커밋 ID를 활용하는 것을 추천한다.

번외

위에서 --hard 옵션을 사용하면 파일이 삭제되고 복구할 수 없으니 위험하다는 말은 했지만, 사실 엄밀히 말하자면 복구 방법이 존재한다.

git reset --hard를 통해 reset시키더라도 로컬 저장소에서 커밋은 삭제되는 것이 아닌 사라진 것처럼 안 보일 뿐이다.

이해하기 쉽게 말하자면(엄밀히 따지자면 다르지만) 컴퓨터에서 특정 파일을 삭제할 경우 영구 삭제되었다고 생각하겠지만 사실 휴지통에는 존재하는 상황이라고 생각하면 편하다.
이런 상황에서 만약 내가 복구하고 싶은 파일명을 알고 있다면 파일을 다시 복구할 수도 있을 것이다

이처럼 만약 내가 복구하고 싶은 파일이 존재하는 커밋 ID를 알고 있다면 해당 커밋 ID를 통해 삭제된 파일을 복구할 수도 있다.
하지만 대부분의 경우 커밋 ID를 외워놓고 있지 않을 것이므로 복구 방법이 존재하지 않는 것과 유사하다고 판단하여 이렇게 설명하는 것이다.

profile
혹시 틀린 내용이 있다면 언제든 말씀해주세요!

0개의 댓글