커밋 취소하기
git reset
git reset 명령어는 현재 커밋한 내역을 특정 시점으로 되돌리고 싶을 때 사용하는 명령어이다. 옵션에 따라 취소, 삭제되는 대상이 달라지기 때문에 상황에 따라 적절한 옵션을 선택하여 사용해야 한다. 자주 사용되는 옵션으로 hard, mixed, soft가 있다.
git reset --soft
reset --soft 옵션을 사용하면 현재 브랜치가 가리키는 커밋을 바꾼다.
git commit --soft "커밋 아이디"
- Index나 워킹 디렉토리는 그대로 놔두고 브랜치가 가리키는 커밋만 이전으로 되돌린다.
- HEAD는 계속 현재 브랜치를 가리키고 있기 때문에 HEAD 브랜치를 이동시키는 것과 같다. (저장소만 삭제(HEAD))
- reset 명령에 커밋을 넘기고 실행하면 언제나 이런 작업을 수행한다.
- checkout 명령처럼 HEAD가 가리키는 브랜치를 바꾸지는 않는다.
git reset --mixed
reset 명령은 여기서 한 발짝 더 나아가 브랜치가 가리키는 커밋을 바꾼뒤 Index( Staging Area )를 커밋이 가리키는 스냅샷으로 업데이트한다.
git commit --mixed "커밋 아이디"
- git reset 명령을 실행할 때 아무 옵션도 주지 않으면 기본적으로 --mixed 옵션으로 동작한다.
git reset --hard
reset 명령은 --mixed옵션에서 더 나아가 워킹 디렉토리까지 업데이트한다.
git commit --hard "커밋 아이디"
- git reset --hard와 같이 커밋을 지정하지 않는다면 가장 최신 커밋으로 초기화한다.
- 이 옵션을 사용하면 워킹 디렉토리의 파일까지 강제로 덮어쓰기 때문에 Git이 커밋으로 보관하고 있다면 reflog 를 이용해서 다시 복원할 수 있다. 만약 커밋한 적 없다면 Git이 덮어쓴 데이터는 복원할 수 없다.
commit 704f019b5f970ef6006097e1d6dfa811348f4bcf (HEAD -> master)
4
commit 7de82a68168a7ad32815cd01411fe777ff1b4f5d
3
...
- 커밋 내용을 취소하고 3번째 커밋으로 돌아 가고자 한다면 git reset 명령어를 사용하면 된다.
$ git reset --hard 7de82a68168a7ad32815cd01411fe777ff1b4f5d
commit 7de82a68168a7ad32815cd01411fe777ff1b4f5d (HEAD -> master)
3
commit 05961aea8c40619c2f26a51635b7eadab5ea63e5
2
...
현재 작업중인 브랜치인 master가 어떤 커밋을 최신 커밋으로 가지고 있는지 가리키는 파일인 refs/heads/master의 변경을 확인할 수 있다.
- git reset을 한다는 것은 작업중인 브랜치가 가르키는 가장 최신 커밋을 바꾸는 것, 4번 커밋 객체가 삭제 된것은 아니다.
가급적 reset은 공유하기 전 로컬 저장소에 있는 버전에만 실행이 되어야 한다. 버전 공유 후 리셋을 하게 되면 리셋한 내용을 팀원들이 모르고 되돌렸던 커밋들이 다시 원격 저장소에 추가되는 상황이 발생할 수 있기 때문이다.
- 미리 공지를 하거나, 가급적이면 git revert를 사용하는 것이 안전하다.
- git revert : 커밋을 취소하며 새로운 버전을 생성하는 명령어
checkout과 reset?
checkout 명령과 reset 명령은 모두 브랜치와 커밋에 대해 다루지만 크게 두가지의 차이가 있다. 첫 번째 중요한 차이점은 reset 명령은 브랜치가 가리키는 커밋을 변경하고 checkout 명령은 HEAD 자체를 다른 브랜치로 옮긴다는 것이고, 두 번째 차이점은 reset --hard 명령과는 달리 checkout 명령은 워킹 디렉토리를 안전하게 다룬다는 것이다.
- 워킹 디렉토리에서 Merge 작업을 한번 시도해보고 변경하지 않은 파일만 업데이트하고 반면 reset --hard 명령은 확인하지 않고 단순히 모든 것을 바꿔버린다.
- checkout 명령어를 기존에는 브랜치를 변경하기 위해서만 사용해 왔지만 커밋 아이디를 활용한다면 커밋으로 이동할 수 있다.
git checkout "커밋 아이디" // git reset --hard [branch] file 와 같은 동작을 한다.
- 기존 HEAD는 ref:refs/heads/master와 같은 파일(브랜치)를 가리키고있다. 하지만 해당 명령어를 실행하면 브랜치가 아닌 직접적으로 커밋을 가리키게 된다.
- 이렇게 되면 어떤 특정 브랜치에 속하는 게 아니라 현재 HEAD가 어떠한 특정 커밋을 직접 가리키는 detached되어 있는 상태가 된다.
master -> 7de82a68168a7ad32815cd01411fe777ff1b4f5d
// OK@DESKTOP-SJ9C79T MINGW64 ~/study/gitfth (master)
// OK@DESKTOP-SJ9C79T MINGW64 ~/study/gitfth ((7de82a6...))
- checkout을 통해 다시 브랜치로 이동하게 된다면 HEAD값이 다시 ref:refs/heads/master와 같은 형식으로 바뀌게 된다.
git reflog
- logs/refs/heads/master과 같은 파일은 해당 브랜치에 일어나는 중요한 작업을 기록하는 파일이다.
$ git reflog
- 해당 명령어를 사용하면 파일의 내용을 확인할 수 있으며 이 정보를 활용해 위험한 명령을 하기 전으로 돌아갈 수 있다.
7de82a6 HEAD@{1}: reset: moving to 7de82a68168a7ad32815cd01411fe777ff1b4f5d
704f019 (HEAD -> master) HEAD@{2}: commit: 4
7de82a6 HEAD@{3}: commit: 3
05961ae HEAD@{4}: commit: 2
7cac14e HEAD@{5}: commit (initial): 1
ORIG_HEAD
위험한 명령(정보를 잃어버릴수 있는 가능성이 있는)을 하기전에 깃은 ORIG_HEAD파일에 현재 브랜치의 head가 가르키는 최신 커밋을 기록한 뒤 명령을 실행한다.
- ORIG_HEAD를 통해서 위험한 명령을 취소 할 수 있다.
$ git reset --hard ORIG_HEAD
commit 704f019b5f970ef6006097e1d6dfa811348f4bcf (HEAD -> master)
4
commit 7de82a68168a7ad32815cd01411fe777ff1b4f5d
3
.....
'Git' 카테고리의 다른 글
[Git] 깃(Git)의 원리(4, 충돌과 충돌 해결)와 Git flow (1) | 2024.06.11 |
---|---|
[Git] 깃(Git)의 원리(3, Branch 정리)와 브랜치 병합(Merge / rebase) (0) | 2024.06.10 |
[Git] 태그(tag)의 기초와 사용법 (0) | 2024.06.02 |
[Git] 깃(Git)의 원리(2, commit)와 깃 객체(Git Object) (0) | 2024.06.02 |
[Git] 깃(Git)의 원리(2, commit)와 깃 객체(Git Object) (0) | 2024.05.28 |