육감적 코딩

[Git 교과서]9장. 복귀 본문

정리/Git

[Git 교과서]9장. 복귀

감감감감감감 2021. 12. 12. 16:05

9.1 되돌리기

9.1.1 다시 시작

깃에서 코드 작업을 되돌리는 방법은 크게 reset 과 revert 두 가지입니다.

9.2 리셋

리셋(reset)은 커밋을 기준으로 이전 코드로 되돌리는 방법으로, 기록한 커밋을 취소합니다.

9.2.1 복귀 시점

커밋 메시지는 여러줄로 작성할 수 있습니다. 로그 기록은 그중 첫 번째 줄 메시지만 출력합니다.

그러므로, 첫 번째 줄에 요약정보를 입력하고, 한줄을 띄우고 좀 더 상세한 내용을 작성하면 좋습니다.

9.2.2 reset 명령어

reset 명령어를 사용하면 지정된 커밋 코드로 되돌아갑니다.

$ git reset <옵션> <커밋ID>

reset 명령어의 옵션

  • soft : 스테이지 영역을 포함한 상태로 복원합니다.
  • mixed : 기본 옵션 값은 mixed 입니다.
  • hard : 실제 파일이 삭제된 이전 상태로 복원합니다.

9.2.3 soft 옵션

$ git reset --soft <커밋ID>

9-1

soft 옵션은 지정한 커밋 위치로 복귀합니다. 복귀하면서 스테이지 영역의 상태도 같이 복귀합니다.

soft 옵션은 파일을 수정하고, add 명령어로 스테이지 영역에 올려 커밋을 실행하기 직전의 단계로 되돌립니다.

9-2

status 명령어를 실행한 출력 결과에서 메시지가 초록색으로 표기되는것을 보면, add 명령어를 사용하지 않고도 바로 커밋할 수 있는 직전의 상황입니다.

주의할 점은 커밋할 때마다 커밋의 해시 값이 변경된다는 점입니다.

reset --soft 명령어의 원리를 이용하면 마지막 커밋을 수정할 수 있습니다. 마치 --amend 명령어와 유사합니다.

9.2.4 mixed 옵션

$ git reset --mixed <커밋ID>  ---- --mixed는 기본옵션이므로, 생략할 수 있음.

mixed 옵션은 soft 옵션과 달리 리셋한 후 스테이지 상태까지 복원하지 않습니다.

mixed 옵션은 스테이지 영역을 같이 복사하지 않기 때문에 수정된 파일은 스테이지 영역이 아닌 워킹 디렉터리 안에 남아 있습니다.

따라서 커밋하려면 add 명령어를 먼저 실행해야 합니다.

9.2.5 hard 옵션

$ git reset --hard <커밋ID>

soft 옵션과 mixed 옵션은 이전 커밋으로 되돌리는 과정에서 실제로 삭제되는 내용은 없습니다.

모든 작업 내용이 워킹 디렉터리에 그래도 유지됩니다.

hard 옵션은 리셋되는 복귀 시점의 커밋 상태와 해당 커밋의 워킹 디렉터리까지 모두 되돌립니다.

9.2.7 커밋 합치기

리베이스 병합의 -i 옵션을 사용하면 여러 커밋을 하나로 합치는 동작을 수행할 수 있습니다.

또 단일 커밋은 커밋 명령어의 --amend 옵셩으로 커밋을 수정할 수 있습니다.

리셋의 동작 원리를 이해하고 있다면, 커밋도 수정할 수 있습니다.

리셋의 soft 옵션을 사용하여 커밋을 합쳐보도록 하겠습니다.

$ git reset --soft HEAD~2       -- 2단계 전의 커밋으로 리셋
$ git diff HEAD~                -- 커밋 비교

9-3

$ git commit -m "menu3/4"      -- 커밋

9-4

커밋 2개를 합쳐 커밋 하나를 만든 것과 같습니다.

9.2.8 스테이지 리셋

스테이지 영역의 파일을 다시 unstage 상태가 되도록 스테이징을 취소할 수 있습니다.

스테이지 영역에서 등록된 파일을 다시 unstage 상태로 만들 때는 reset 명령어를 사용합니다.

$ git reset <파일이름>

이 명령어는 사실 몇 가지 옵셕이 축약되어 있습니다.

내부적으로 다음과 같이 여러 단계로 처리하여 파일을 unstage 상태로 변경합니다.

$ git reset --mixed HEAD <파일이름>

최신 커밋에서 파일을 리셋하고 mixed 옵션으로 스테이지 영역도 같이 제거합니다.

다음과 같이 HEAD 대신 다른 커밋 ID를 사용할 수도 있습니다.

$ git reset <커밋ID> <파일이름>

9.2.9 작업 취소

코드를 수정하는 도중 오류가 생겨 현재 작업을 모두 취소하고 싶을 수 있습니다.

수정 작업을 완전히 취소하려면 워킹 디렉터리와 스테이지 상태를 모두 제거하여 마지막 커밋 상태로 되돌려 놓아야 합니다.

리셋할 때의 시점을 현재 HEAD를 기준으로 하면 해당 시점의 수정 작업을 모두 삭제할 수 있습니다.

$ git reset --hard HEAD

9.2.10 병합 취소

$ git reset --merge HEAD~

9.2.11 주의할 점

리셋 기능을 이용하면 독립된 개인 프로젝트를 관리할 때 쉽게 이전 상태로 복귀할 수 있습니다.

하지만 저장소를 외부에 공개했거나 공유하고 있다면 주의해서 리셋을 사용해야 합니다.

작성된 커밋이 리셋으로 삭제되면 함께 작업하는 개발자에게 혼란을 줄 수 있습니다.

일반적으로 협업하거나 소스 코드를 공유한 후에는 리셋 작업을 하지 않습니다.

9.3 리버트

공개한 저장소에서는 이전 상태로 되돌리려면 어떻게 해야 할까요?

깃은 커밋의 버전을 되돌릴 수 있는 또 다른 방법인 리버트를 제공합니다.

리버트와 리셋 차이점은 커밋 정보 삭제 여부입니다.

9.3.1 취소 커밋

리버트는 기존 커밋을 남겨 두고 취소에 대한 새로운 커밋을 생성합니다.

취소 커밋은 지정한 커밋을 삭제하지 않습니다. 대신 삭제를 위한 새로운 커밋을 생성합니다.

$ git revert HEAD    -- 현재 커밋을 리버트

9-5

9.3.2 리버트 지정

한 번에 여러 커밋을 리버트해야 한다면 어떻게 해야 할까요?

리버트는 한 번에 커밋 하나만 취소할 수 있습니다. 따라서 여러 커밋을 리버트하려면 최신 커밋부터 순차적으로 취소해야 합니다.

그렇다면 직전의 커밋이 아닌 다른 커밋을 취소할 때는 어떻게 해야 할까요? 커밋 해시 값을 지정합니다.

$ git revert <커밋ID>

깃의 범위 지정 연산자를 사용하여 여러 커밋을 히버트 할 수도 있습니다.

$ git revert <커밋ID> .. <커밋ID>

9.3.4 병합 취소

리셋은 방금 전 실행한 병합만 삭제합니다. 하지만 리버트는 시간이 지난 후에도 과거의 병합을 선택하여 취소할 수 있습니다.

$ git revert --mainline <숫자> <병합커밋ID>

9-6

참고로 리베이스된 병합은 리버트하기 어렵습니다. 리베이스로 병합된 공통 조상 커밋을 찾기 어렵기 때문입니다.

$ git log --oneline --graph
옵션을 사용하면
로그를 위 그림처럼 그래프 형태로 볼 수 있습니다.

9.3.5 리버트 히스토리

리버트를 실행하면 새 커밋이 추가되기 때문에 커밋 이력이 복잡합니다. 어떻게 보면 리셋으로 간단하게 이전 상태로 되돌리는 것이 간편해 보일 수도 있습니다.

하지만 저장소를 공개했다면 리셋으로 커밋을 삭제하는 것은 협업 차원에서 위험합니다. 이때는 리버트가 유용합니다.

9.4 정리

리셋과 리버트는 동작을 취소하고 과거로 돌아간다는 면에서는 유사합니다.

하지만 이렇게 두 명령어로 분리하여 사용하는 것은 저장소를 원격 저장소로 공개했는지 여부와 관련이 있습니다.

자신의 저장소를 외부로 공개했다면 특정 커밋을 삭제하는 것은 위험합니다.

다수의 사용자와 공유하는 저장소의 커밋 기록이 깨질 수 있기 때문입니다.

외부로 공개한 저장소라면 리버트를 사용하는 것이 좋습니다.

'정리 > Git' 카테고리의 다른 글

[Git 교과서]11장. 서브모듈  (0) 2021.12.20
[Git교과서]10장. 배포 관리와 태그  (0) 2021.12.13
[Git 교과서]8장. 병합과 충돌  (0) 2021.12.12
[Git 교과서]7장. 임시 처리  (0) 2021.11.30
[Git 교과서]6장. 브랜치  (0) 2021.11.23
Comments