Git 헷갈리는 명령어 완벽 정리(reset, revert, rebase)
개요
제목은 “완벽 정리"라며 거창하게 썼지만, 개인적인 헷갈림을 정리하기 위함이다.
예를 들어 커밋을 되돌리고 싶을 때, Reset, Revert, Rebase 전부 다 활용할 수가 있다.
그동안 헷갈렸지만 귀찮음에 속아서 정리하지 못했던 것들을 이번 기회를 통해 정리해본다.
롤백
아 나 커밋 되돌리고 싶어요!
개발자로 살다보면 이전 작업 내역(커밋)으로 돌아가고 싶은 적이 분명 많이 있었을 것이다.
반면, 어떤 명령어를 사용하는게 적절한지에 대해서는 항상 정답을 못 찾았다.
결론적으로는 어떤 것을 사용해도 크게 문제가 없다.
하지만 각 명령어의 차이점을 알고 쓰는 것이 모르고 쓰는 것보다는 나을 것이다.
롤백을 하기 위해서는 크게 3가지 명령어가 존재한다.
- git reset
- git revert
- git rebase
1) git reset
git reset 명령어는 변경 사항을 취소하는데 사용된다.
쉽게 말해 이전 커밋으로 이동할 수 있다는 것이다.
git reset --(모드) (돌아갈 커밋)
보통 위와 같은 형태로 사용한다.
해당 명령어의 모드 인자로는 세가지가 존재한다.
- soft
- mixed
- hard
디폴트로 git reset 명령어는 mixed를 사용한다.
기본적으로 해당 인자를 이해하기에 적절한 그림을 가져왔다.
git으로 관리되는 어떤 프로젝트가 있다고 가정해보자.
내 로컬에서 해당 프로젝트의 특정 파일을 수정하면 변경 사항이 바로 스테이징 되지 않는다.
이를 먼저 스테이징하기 위해서는 git add
명령가 필요하다.
이후 git commit
명령어를 통해 커밋하면 스테이징에 존재하던 변경사항이 커밋되고 역사로 기록된다.
세 인자 전부 커밋을 취소하고, 이전 상태로 돌아간다는 관점에서는 동일하다.
돌아가는 기준을 어떻게 할 것인가에 설정이라고 생각하면 된다.
- --soft: 커밋 취소, 하지만 스테이징 상태로 유지.
- --mixed: 커밋 취소 및 스테이징 취소, 내 로컬 변경 상태로 유지.
- —hard: 커밋 취소 및 스테이징 취소 및 로컬 변경 상태 취소
2) git revert
git revert 명령어 역시 되돌리는 작업을 수행하는데 사용된다.
reset 명령어와 비슷해 보이지만, 특정 커밋으로 돌아가기 위해 새 커밋을 수행한다는 점이 다르다.
다시 말하자면, git revert 명령어 자체가 하나의 커밋이라고 생각하면 된다.
git revert (돌아갈 커밋)
보통 위와 같은 형태로 사용한다.
위 그림과 같이 revert를 한 커밋 역시 역사에 길이길이 남게 된다.
즉 만약 아예 커밋을 지우고 싶은 것이라면, revert는 적절하지 않다.
기존 커밋을 유지할 것인가, 말 것인가에 대해서 적절한 트레이드오프를 고려해서 활용하면 된다.
3) git rebase
git rebase는 꽤나 많은 기능을 가지고 있다.
rebase라는 것 자체는 보통 한 브랜치의 커밋들을 다른 브랜치로 합칠 때 때 많이 쓰는 방식이다.
(관련해서는 추후 다른 포스팅으로 다룰 예정이다.)
하지만 해당 명령어 역시 되돌리는 작업을 수행할 수 있다.
git rebase -i (돌아가고자 하는 커밋의 직전 커밋)
보통 위와 같은 형태로 사용한다.
예를 들어서
위와 같이 3개의 커밋이 있다고 가정해보자.
여기서 나는 맨 마지막 커밋을 지우고 싶다. 그러면 어떻게 해야할까?
git rebase -i 17271518eddfc6869169fc777f538e50869c4309
형식으로, 그 이전 커밋의 id를 입력해주면 된다.
이렇게 하면 해당 17271518eddfc6869169fc777f538e50869c4309
위의 커밋들이 모두 뜨게 된다.
해당 커밋의 작업 타입을 pick에서 d 또는 drop으로 바꿔준다.
친절하게도 아래에 다양한 커맨드를 설명해주고 있다.
이후에 저장 후 종료를 해준다.(:wq)
위와 같이 git log를 했을 때 커밋이 제거된 것을 확인 가능하다.
유추해보았을 때는 git reset의 —hard 모드와 동일하게 동작한다.
커밋은 물론, 내 스테이징이나 로컬에서도 변경 사항은 사라져있다.
결론
커밋을 지우는데에는 위 모든 명령어를 활용할 수 있다.
각 상황에 맞춰서 적절한 것을 골라쓰면 된다.
개인적으로는 rebase는 중간 커밋을 삭제할 때 용이하다고 생각이 든다.
그리고 되돌리기는 항상 신중해야 하므로, reset에서도 —hard 인자는 최대한 자제하는 것이 좋지 않을까 생각한다.
오랜만에 글로 정리하다보니 더 이해도가 높아진 것 같다.
참고: