Git&Github

12. [Git] reset과 revert

drizzle0925 2021. 8. 24. 21:52
728x90

reset : 시간을 아예 과거의 특정 사건(commit)으로 되돌린다.
revert : 현재에 있으면서 과거의 특정 사건(commit)들만 없던 일로 만듭니다.

 

둘의 공통점은 '과거로 되돌린다.'는 것이지만, 가장 큰 차이점은 '과거로 되돌리겠다는 내용도 기록되는가?(== commit 이력에 남는가?)'입니다.

reset은 아예 현재가 없었던 것처럼 원하는 과거로 돌아갈 수 있습니다. reset은 이력을 남기지 않습니다. 따라서 현재까지의 commit 이력을 남기지 않고 원하는 시점으로 완전히 되돌아가고 싶을 때 사용합니다.

revert는 과거로 돌아가겠다는 이력을 남겨두고 원하는 시점으로 돌아갑니다. 즉, 이전의 commit 내역을 남겨두고 새로운 commit을 생성하면서 과거로 돌아가게 됩니다.


RESET

아래와 같은 commit 이력이 있다고 가정해보겠습니다.

위의 그림에서 git reset --hard a0fvf8 을 입력합니다. 'a0fvf8' commit으로 돌아간다는 뜻입니다.

 

 

commmit 히스토리에 C, D 커밋이 아예 사라집니다.

 

실제로 reset 명령어를 입력해보겠습니다.

$ git log

 

 

reset 명령어를 이용해서 memo2.txt를 수정했던 때로 되돌아가 보겠습니다.

commit 값을 복사합니다.

 

 

아래 명령어를 입력합니다.

$ git reset --hard 44db8222c3ea01f8c0b36c82f8b550aadfb8aad4

 

 

log 명령어를 입력해서 확인하면 memo.txt 수정이라는 git 내용이 없어진 것을 확인할 수 있습니다.

$ git log

 

 

이대로 원격 저장소(리포지터리)에 push 하려고 하면 에러가 발생합니다.

 

 

이럴 때는 + 명령어를 사용해서 강제로 push 하는 방법을 사용하면 됩니다.

$ git push origin +master

 

 

에러가 발생하지 않고 push 된 것을 확인할 수 있습니다.

github로 이동해서 잘 업로드되었는지 확인해보겠습니다.

제대로 되돌아간 모습을 확인할 수 있습니다.

 

 

그럼 혹시 reset 한 내용을 다시 취소하고 싶을 때는 어떻게 해야 되는지 알아보겠습니다.

아래 명령어를 입력합니다.

$ git reflog

 

 

HEAD@{0}을 보면 방금 제가 reset을 이용해서 44db822로 이동했다는 내용이 적혀있습니다.

HEAD@{1}로 이동하면 reset 이전으로 되돌릴 수 있습니다. 

아래 명령어를 입력합니다.

$ git reset HEAD@{1}

 

 

그러고 나서 log를 다시 확인해보면 commit이 되돌아온 것을 확인할 수 있습니다.

 

 

HEAD@{1} 대신에 commit키인 44db8222를 활용해도 됩니다.

이전과 같은 상태로 되돌리기 위해 원격 저장소(리포지터리)에 push 하겠습니다.

이전과 다르게 +명령어를 사용하지 않아도 잘 업로드되는 것을 확인할 수 있습니다.

 

원격 저장소에 가보니 정상적으로 업로드된 것을 확인할 수 있습니다.


REVERT

revert를 이용해 B 커밋으로 돌아가려면 commit이력을 따라가면서 순차적으로 revert 명령어를 입력해야 합니다.
git revert 5lk4er // D 커밋 revert
git revert 76sdeb // C 커밋 revert
위와 같이 뒤 commit부터 순차적으로 revert 해줍니다.

그럼 이렇게 revert 한 내용의 커밋 이력을 남기면서 B로 돌아갈 수 있음을 확인할 수 있습니다.

 

 

실제로 revert를 명령어를 입력해보겠습니다.

log를 확인하여 돌아갈 지점을 선택합니다.

$ git log

 

 

be13529로 돌아가 보겠습니다.

위에서 설명한 대로 위에서부터 하나씩 뒤로 이동하겠습니다.

 

$ git revert b56f32a32c209f95aaf9c02ad7b553ce10af444c

 

엔터를 누르면 commit 메시지를 입력하는 창이 열립니다.

메시지는 지정 값에서 수정하지 않도록 하겠습니다.

 

다시 log를 확인합니다.

b56f32a위에 revert 한 log가 추가되어 있습니다.

 

 

시간이 걸리니 한 번만 더 revert를 해보겠습니다.

$ git revert e517223b06af9015bdf3540ad9a5d216b3123c30

 

 

별다른 수정 없이 닫겠습니다 

 

 

commit 이력을 원격 저장소(리포지터리)에 push 해보겠습니다.

reset과 다르게 + 없이 잘 업로드되었습니다.

 

 

revert 한 commit 이력이 추가되어 있고 소스코드도 이전으로 되돌아가 있습니다.

 

reset의 경우에는 reflog를 이용해서 되돌아갔지만, revert의 경우에는 commit 이력을 계속 생성하기 때문에 되돌아가고 싶은 commit id를 입력해서 되돌아가면 됩니다.


언제 reset을 사용하고 언제 revert를 사용할까?

코드를 작성하다가 과거로 되돌리고 싶어 져서 reset 명령어를 이용해서 되돌아갔다고 가정해보겠습니다.

reset명령어는 commit 이력을 삭제하는데 로컬에는 reset명령어로 인해 commit 이력이 삭제되어 있지만 원격 저장소에는 삭제되어 있지 않습니다. 이런 경우 충돌이 발생합니다. 혼자 작업하는 경우라는 위에 [+] 나 [-f]를 이용해서 강제 push를 할 수 있지만 다른 팀원들과 협업하는 중에 이렇게 작업을 하면 다른 팀원이 push 할 때 또 충돌이 발생하는 문제가 생깁니다. 

 

즉, 같은 branch를 공유하는 협업 프로젝트에서 마음대로 commit 이력을 삭제하면 다른 팀원이 push 할 때 충돌이 발생하게 됩니다.

 

따라서, 협업 프로젝트에서는 revert를 사용하여 이전 commit으로 되돌아가는 것이 좋습니다.


reset

git reset --soft [commit ID] 
git reset --mixed [commit ID]
git reset --hard [commit ID]
git reset HEAD~10 
git reset HEAD^
soft : commit된 파일들을 staging area로 돌려놓음. (commit 하기 전 상태로)
mixed(default) : commit된 파일들을 working directory로 돌려놓음. (add 하기 전 상태로)
hard : commit된 파일들 중 tracked 파일들을 working directory에서 삭제한다. (Untracked 파일은 여전히 Untracked로 남는다.) git reset --hard HEAD^ 를 혼자 할땐 제일 많이 쓰게되더라..
HEAD~취소할커밋수 : 현재로부터 원하는 만큼의 커밋이 취소된다.
HEAD^ : 가장 최근의 커밋이 취소된다. (기본옵션 mixed)

 

revert

git revert [commit ID]
돌아가고자 하는 commit ID를 적어준다.

 

 

revert를 사용하면 중간에 무슨 문제가 있었는지, 왜 돌아갔는지 등의 기록이 가능하다는 장점이 있습니다.

또한 다른 사람과 같은 브랜치에서 함께 작업할 때 코드 충돌을 최소화할 수 있습니다.


reset을 사용하면 commit 히스토리를 깔끔하게 유지할 수 있고, 혼자 작업할 때 편하게 되돌아갈 수 있다는 장점이 있습니다. 그러나 타인과 같은 브랜치에서 함께 작업할 때 commit이 뒤섞여버릴 수 있다는 위험한 단점이 있습니다.

728x90