/
(4)-6.GIT reset+의+역할
(4)-6.GIT reset+의+역할
reset 의 역할
- Step 1: Moving HEAD killing me --soft ly
- Step 2: Updating the Index having --mixed feelings
- Step 3: Updating the Working Directory math is --hard, let's go shopping
- Summary
reset은 옵션에 따라 이해가 매우 힘듭니다. 유심히 잘 따져봐야 합니다.
게다가 git답지 않게 위험하기도 합니다.
- 애매하기 때문에 정확히 알아야 git의 가장 큰 장점인 맘대로 커밋하고, 맘대로 푸쉬하는 장점을 제대로 활용할 수 있습니다.
- reset은 복잡해 보이지만, 정해지고, 예측 가능한 방식으로 커밋 트리를 직접 조작합니다.
- reset은 --soft , --mixed, --hard 세 가지 옵션으로 작업을 수행합니다.
Step 1: Moving HEAD killing me --soft ly
- reset이 가장 먼저 하는 일은 HEAD가 가리키는 포인터를 이동하는 것 입니다. 참고) checkout은 HEAD가 가르키는 커밋에 대한 포인터를 이동하는 대신'Detached HEAD' state로 이동.
- reset은 직접적으로 HEAD가 가르키는 커밋을 변경하고, 이에 따라 SHA가 바뀌게 됩니다
즉, HEAD가 'master'브랜치를 가르키고 있다면(다른 브랜치에 있지 않다면) git reset 9e5e6a4 을 수행하면, master가 9e5e6a4를 가르키게 됩니다.
Diagram 1
설명
- 세번의 커밋이 있었음.
- 그 때마다 file.txt를 수정하여 커밋 세번에
- file.txt가 변경되어
- 각각을 v1,v2,v3 라 하자.
- 이때, git reset --soft HEAD~
- 를 수행하면,
- HEAD와 master는 9e5e6a4 (2번째 커밋)으로 이동
- HEAD는 v2의 file.txt를 가지고 있고
- 반면 스테이징된 파일은 아직 v3이다.
- 또한 Working Directory에 있는 내용도 v3임.
- 참고) git checkout HEAD~ 이면
checkout은 HEAD가 가르키는 커밋에 대한 포인터를 이동하는 대신'Detached HEAD' state로 이동.
이 상태는 별도의 브랜치를 만들어서 과거에 돌아간 것. git checkout -b <new-branch-name> 으로 분기하여 개발 진행 가능| - reset 뒤에 어떤 옵션이 붙던 reset 명령어가 수행될 때 처음하는 일은 HEAD를 옮기는 것입니다. 만약 --soft 옵션을 붙여 reset 을 수행하면 reset은 HEAD를 v2 커밋으로 옮기고, 거기서 멈출 것입니다.
- Diagram 1을 유심히 보세요. reset --soft는 최종 커밋을 취소합니다. 그러나 staging된 내용과 현재 작업하고 있는 내역은 최종커밋의 내용입니다.
- 결과적으로 당신은 스테이징 영역 또는 작업 디렉토리를 변경하지 않고 HEAD만 이전 커밋 지점을 이동하고있다는 것을 의미합니다 .
- reset HEAD~(HEAD의 부모)로 최종커밋을 취소했지만 스테이징 영역과 작업 디렉토리는 그대로 입니다.
- 이제는 할 일은 돌아간 커밋에서 수정하고 싶은 부분을 수정하고 git commit --amend 를 수행하면 최종 커밋 수정이 완료됩니다.
- file.txt를 수정하지 않고 git commit --amend 를 수행하면 v3내용이 커밋됩니다. (결론 : 커밋 히스토리는 v1과 v3만 남음, 내용은 v3)
Step 2: Updating the Index having --mixed feelings
- git reset --mixed HEAD~ 를 수행하면, HEAD를 v2 커밋으로 옮깁니다.
그리고, Staging안의 내용을 v2로 변경합니다. 이 상태에서 git status 실행 하면 현재 Staging된 내용을 볼 수 있습니다. INDEX와 새로운 HEAD의 차이점이 녹색으로 표시됩니다.
Diagram 2
설명
- 이때, git reset --mixed HEAD~
- 를 수행하면,
- HEAD와 master는 9e5e6a4 (2번째 커밋)으로 이동
- HEAD는 v2의 file.txt를 가르키고 있음
- --mixed는 스테이징된 파일을 v2로 롤백
- 그러나 Working Directory에 있는 내용도 v3임.|
- --mixed옵션 을 지정하면 reset이 HEAD를 옮기고(최종 커밋을 취소하고) , 이전 커밋내용을 INDEX에 이전 커밋 내용으로 롤백됩니다, 하지만 여기서 멈춥니다.
- --mixed가 reset의 default이기 때문에 옵션을 주지 않으면 reset의 결과는 이렇게 됩니다.
Step 3: Updating the Working Directory math is --hard, let's go shopping
- git reset --hard HEAD~ 를 수행하면, HEAD를 v2 커밋으로 옮깁니다.
- 그리고, Staging안의 내용을 v2로 변경합니다. 이 상태에서 git status 실행 하면 현재 Staging된 내용을 볼 수 있습니다.
여기서 그치지 않고 --hard를 수행하면, Working Directory의 내용도 롤백합니다. 결국 INDEX의 내용과 Working Directory의 내용이 같아집니다.
State
설명
- 이때, git reset --hard HEAD~
- 를 수행하면,
- HEAD와 master는 9e5e6a4 (2번째 커밋)으로 이동
- HEAD는 v2의 file.txt를 가르키고 있음
- --hard 는 스테이징된 파일을 v2로 롤백
- Working Directory에 있는 내용도 v2로 롤백.|
- 꼭 알아둘 점은 reset명령이 위험한 명령이 될 수 있다는 것입니다. 즉, 작업 디렉토리가 안전하지 않다는 것입니다.
- 다른 옵션으로 reset명령어를 수행하면 쉽게 돌아갈 수 있지만, --hard 옵션은 작업 디렉토리에있는 파일을 (점검하지 않고) 겹쳐 쓰므로 위헙할 뿐더러 reset을 쉽게 취소할 수도 없습니다.
- 이 경우 reflog 로 Git DB에 있는 것을 찾아서 롤백을 할 수는 있지만, 이 마저도 commit을 했다면 Git DB에 Overwrite가 일어나므로 복구가 불가합니다.
Summary
간단히 reset 명령어가 옵션에 따라 동작하는 것을 정리하면 다음과 같습니다.
- # 1) 어떤 커밋이든 HEAD가 가리키는 모든 브랜치로 이동 (여기서 멈춤 --soft)
- # 2) THEN, INDEX 를 HEAD가 가르키는 커밋 내용으로 롤백 ( --hard 를 쓰지 않으면 여기서 멈춤, Default, --mixed )
- # 3) THEN, Working Directory를 HEAD가 가르키는 커밋 내용으로 Overwrite