본문 바로가기
뒷북 정리 (국비 교육)/git, github

Git command : reset

by 규글 2022. 3. 30.

reset : 과거로 돌아가고 싶다면?

 파일에 대한 작업이 아직 마무리되지 않은 상황이 commit 하기 전이라면 어떨까? 미처 마무리되지 않은 파일이 있다면 마무리하면 되고, 이미 stage에 올라간 상황이라면 다시 unstage 하여 작업한 후 다시 stage에 올리면 된다. 하지만 이미 commit을 해버렸는데 그것이 실수였다든지, 이미 merge했는데 그것이 치명적인 문제를 일으켜서 다시 과거로 돌아가야할 필요성이 있다면 어떨까? 그럴 때 사용하는 것이 reset이다.

 

git reset --hard HEAD~2

git reset --hard hash-code

 바로 위 이미지의 상태에서 두 단계 전의 상태로 돌아가고 싶다고 가정해보자. 그럼 예시 상으로는 branch3를 merge한 상황으로 돌아가게 될 것이다. 이때 쓰는 HEAD~2는 현재 HEAD가 위치하고 있는 곳 기준으로 두 단계 이전을 의미한다. 혹은 head pointer 대신에 원하는 시점의 hash code를 입력해도 된다.

 

 문제는 과거로 돌아갔음에도 이전 commit들이 남아있는 모습이었는데 이것들은 branch 정보가 남아있기 때문에 보이는 친구들로, branch 정보를 지우면 이전 commit들이 지워진 것을 확인할 수 있다.

 

 하지만 reset에도 단계가 있다. 방금 보였던 hard, 그리고 soft, 이들의 중간인 mixed이다.

 먼저 soft의 경우는 code는 남아있고, commit 이전까지의 상태로 돌아간다. commit만 취소하는 것이다.

 

 이렇게 기본 상태를 만들어두었다.

 

>>> git reset --soft hash-code

 soft 옵션을 주고 reset을 하면 그간의 commit했던 파일들이 staging area에 들어간 상태가 된다.

 

 hard 옵션을 주고 reset을 하면 untracked file을 제외한 모든 파일들이 사라진 상태가 된다.

 

>>> git reset --mixed hash-code

  mixed 옵션을 주고 reset을 하면 그간 commit 했던 파일들이 지워지지는 않지만 unstage 된 상태가 된다.

 

 

개인적인 reset 추가 실험

 사실 reset이 잘 와닿지 않아서 검색도 좀 해보고, 실험도 좀 해봤다. 먼저 검색하면서 발견했던 몇몇 글과 표를 가져와봤다.

[Git] reset 자세히 알아보기 — Antilog의 개발로 쓰다 (tistory.com)

 이 표를 보면서 가장 먼저 눈에 들어왔던 것은 hard 옵션의 내용이었다. hard 옵션을 사용했을 때 working directory고 staging area고 모두 아무것도 없는 상태가 되었는데, 어떤 의미인지 와닿지 않았다.2 왜 와닿지 않았는지를 알기 위해서 Git 공식 홈페이지의 내용을 다시 차근차근 읽어봐야할 필요가 있었다.3

 

 어떤 파일 test.txt를 만들었다고 생각해보자. 이 test.txt는 현재 working directory에 있을 것이다. 그리고 add 명령어로 staging area로 올리는데, 이것은 working directory의 내용을 staging area로 복사하는 것이다. 이어서 commit 명령어로 commit 하게 되면 index의 내용을 스냅샷으로 저장하고, 그 스냅샷을 가리키는 commit 객체를 만들고 master가 그 commit 객체를 가리키도록 한다. 이때 status 명령어로 상태를 확인하면 아무런 변경 사항이 없다는 메시지를 확인할 수 있는데, 현재 HEAD가 보고 있는 것과 staging area, working directory의 세 트리가 같기 때문이라고 한다.

 

 만약에 파일을 수정한다면? staging area에 있는 내용과 working directory에 있는 내용이 서로 다르기때문에 변경 사잉이 stage 되어야한다는 메시지를 얻게 된다. 동일하게 staging area로 옮기고 commit하면 세 트리의 파일이 같기 때문에 아무것도 출력하지 않게 된다.

 

 그렇다면 위와 같은 이미지의 상태라고 생각하고 reset을 생각해보자. reset 명령어가 수행하는 가장 첫 번째 일은 HEAD를 옮기는 것이다. 이때 branch를 바꾸지는 않는다. 현재 branch는 그대로고 가리키는 commit만 바꾼다.

 

 HEAD만 바꾼 상태가 바로 soft 옵션으로 reset 명령어를 수행했을 때이다. 나머지 staging area와 working directory의 내용은 그대로 유지한다.

 

  default인 mixed 옵션으로 reset 명령어를 수행하면 한 발짝 더 나간다. HEAD를 옮겨두고, 그 HEAD가 가리키는 스냅샷의 모습으로 staging area를 업데이트 한다. working directory의 내용은 그대로 유지한다.

 

 hard 옵션은 mixed 옵션에서 한 발짝을 더 나간다. staging area에 이어서 working directory까지 업데이트를 하게 한다. 때문에 hard 옵션으로 reset 명령어를 수행하면 아무런 변동사항이 없다고 나오는 것이다.

 

[Git] reset 자세히 알아보기 — Antilog의 개발로 쓰다 (tistory.com)

 그렇다면 다시 한 번 처음 가져왔던 표를 읽어보겠다. soft 옵션은 HEAD가 가리키는 commit 만 바꾸기때문에 staging area와 working directory에는 변화가 없는 것이 맞고, mixed 옵션은 HEAD가 가리키는 commit의 내용으로 staging area가 업데이트 되는 것이기에 맞고, hard 옵션은 HEAD가 가리키는 commit의 내용으로 staging area와 working directory가 업데이트 되는 것이기에 맞는 내용이었다.

 

 유사한 다른 그림들이 있으니 참고하면서 읽어보면 도움이 될 것이다.4 5

 

그럼 이어서 실험한 내용을 살펴보자.

 간단히 설명하면 네 가지 파일이 등장한다. 1부터 4까지를 txt 파일로 만들었는데 1번 파일을 만들어서 commit 하고, 바로 이어서 2번 파일을 만들어서 commit 했다. 그리고 3번 파일을 만들어서 staging area에 올렸고, 4번 파일을 만들어 둔 상태이다.

 

 이때 default인 mixed 옵션을 사용해서 파일을 commit 하기 전의 상태로 되돌리면 그때까지 작업했던 네 파일이 모두 untracked 된 것을 확인할 수 있었다. 4번이야 애초에 untracked 파일이었다. 나머지를 생각해보자. 이미 commit이 됐던, 1번과 2번 파일은 사실 HEAD와 staging area, working directory의 세 트리에 모두 있던 친구들이다. 그런데 그 상태에서 HEAD가 파일들이 없던 상태의 commit을 가리키면서 mixed 옵션으로 인해 가리키는 HEAD와 staging area가 같아지면서 1번과 2번 파일은 working directory에만 남게 되었다. commit만 안했다 뿐이지 3번 파일도 같은 맥락이다.

 

때문에 강의에서 말했던 "version history에서는 commit을 삭제하지만, 작업하고 있던 내용들은 모두 working directory에 옮겨놓는 역할을 한다." 는 결론이 되는 것이다.

 

 soft 옵션은 어떨까? 1번과 2번 파일이 staging area로 옮겨졌다. HEAD를 옮기기만 하는 것이기 때문에 staging area와 working directory에서의 변동이 없다면 1번과 2번 파일이 staging area에 올라간 모습으로 보이는 것이 맞다.

 

 "reset의 soft 옵션을 사용하면 commit 했던 내용들을 staging area로 파일들을 초기화하게 된다." 는 결론과 일치하게 된다. 실험 끝!

댓글