Computer >> 컴퓨터 >  >> 프로그래밍 >> 프로그래밍

Git reset 완벽 가이드: 커밋 되돌리기부터 브랜치 복구까지

혼자 또는 팀으로 프로젝트를 진행하다 보면 커밋을 되돌리고 싶은 순간이 반드시 찾아옵니다. 그럴 때 git reset 명령어는 정말 든든한 구원자가 되어 줍니다.

Git의 추적 메커니즘

git reset을 본격적으로 다루기 전에, 먼저 Git의 내부 구조를 이해할 필요가 있습니다. Git은 노드와 포인터로 이루어진 트리(tree) 구조를 통해 파일을 관리하고 추적합니다.

로컬 Git 저장소에는 기본적으로 세 가지 "트리"가 존재합니다:

  1. 작업 디렉터리(Working Directory): 작업 트리(working tree)라고도 하며, 로컬 디렉터리를 의미합니다. git status 명령어로 현재 작업 디렉터리의 상태를 확인할 수 있습니다.
  2. HEAD: 현재 브랜치의 마지막 커밋 스냅샷을 가리키는 포인터입니다. git checkout으로 브랜치를 전환하면 HEAD도 해당 브랜치의 마지막 커밋으로 변경됩니다.
  3. 인덱스(Index): 스테이징(staging) 영역이라고도 합니다. git add로 파일을 추가하면 커밋 대상 파일들이 이 인덱스에 등록됩니다.

Git 워크플로우

다음 예시는 파일을 수정한 후 git add로 스테이징 영역(인덱스)에 추가하고, git status로 커밋 대상 변경 사항을 확인하는 과정을 보여줍니다.

Git reset 완벽 가이드: 커밋 되돌리기부터 브랜치 복구까지

이후 git commit을 실행하면 변경 사항이 더 영구적인 스냅샷으로 저장되고, master와 HEAD가 해당 커밋을 가리키도록 업데이트됩니다. 따라서 커밋 후 git status를 실행하면 세 가지 트리가 모두 동일한 상태임을 확인할 수 있습니다 (커밋할 내용이 없다고 표시됩니다).

Git reset 완벽 가이드: 커밋 되돌리기부터 브랜치 복구까지

그렇다면 git reset은 왜 필요할까?

이런 긴 설명이 왜 필요한지 궁금할 수 있습니다. git reset은 바로 이 세 가지 트리를 다양한 방식으로 조작하는 명령어이기 때문입니다. 원하는 작업에 따라 여러 가지 옵션을 조합해 사용할 수 있습니다.

Git Reset 모드

변경 사항과 파일을 커밋했는데, 잘못된 브랜치에 커밋했다는 사실을 깨달았거나 커밋에 버그가 있어 되돌리고 싶다고 가정해 봅시다. 이럴 때 git reset의 모드(mode)를 알고 있으면 큰 도움이 됩니다.

모드를 지정한 git reset은 항상 HEAD 포인터를 업데이트합니다. 기본 문법은 다음과 같습니다.

git reset <mode> <commit-optional>

주요 모드 살펴보기

  • --soft: HEAD 포인터만 초기화하고 인덱스와 작업 디렉터리는 그대로 유지합니다. HEAD만 리셋되고 나머지 트리는 최신 변경 사항을 그대로 보여줍니다.
  • --mixed: 기본값. HEAD와 인덱스를 함께 초기화합니다. 즉, 모든 변경 사항을 언스테이징(un-stage)하여 git add를 실행하기 전 상태로 되돌립니다. 참고: 옵션 없이 git reset만 입력하면 자동으로 git reset --mixed로 해석됩니다.
  • --hard: 이 옵션은 각별히 주의하세요. HEAD와 인덱스뿐 아니라 작업 디렉터리까지 초기화합니다. 현재 HEAD 포인터(마지막 커밋) 이후의 모든 변경 사항이 폐기되므로 작성한 코드를 잃어버릴 수 있습니다!

--merge, --keep 같은 그 외의 모드는 공식 문서에서 확인할 수 있습니다.

유용한 git reset 활용 팁

커밋 되돌리기

모드를 생략하면(git reset을 옵션 없이 실행하면) --mixed로 해석된다는 점을 기억하세요.

단순히 git reset HEAD를 입력하면 아무 일도 일어나지 않지만, git reset HEAD~1을 입력하면 HEAD가 이전 커밋을 가리키게 됩니다.

다음 예시는 앞선 과정에서 이어집니다. 샘플 파일에 새 텍스트를 추가한 후 git add와 commit을 실행했다고 가정해 봅시다. 이후 git reset HEAD~1을 실행하면 모든 변경 사항이 언스테이징되고 HEAD는 이전 커밋을 가리키게 됩니다.

Git reset 완벽 가이드: 커밋 되돌리기부터 브랜치 복구까지

커밋을 되돌리고 싶을 때 활용할 수 있는 빠르고 편리한 방법입니다!

특정 파일 언스테이징하기

git add로 파일을 인덱스에 추가한 상태라고 가정해 봅시다. 다음 명령어 하나만으로 해당 파일을 제외할 수 있습니다:

git reset HEAD <file-name>

시나리오: 코드를 완전히 망쳤어요! 정상적으로 작동하던 시점으로 돌아갈 수 있을까요?

모든 로컬 변경 사항을 버리고 이전 커밋으로 돌아가고 싶다면, 최후의 수단인 git reset --hard를 사용하세요.

코드가 깨졌을 때 이것이 유일한 선택지인 경우가 많습니다. 커밋 해시를 알고 있다면 git reset --hard <commit>으로 특정 시점으로 되돌릴 수 있습니다. 단, 이 경우 해당 커밋 이후의 다른 커밋들(있다면)까지 모두 영향을 받는다는 점에 주의하세요!

시나리오: 이 커밋은 새 브랜치에 올라갔어야 했는데!

특히 프로덕션 환경에서 작업을 시작하는 초반에 자주 발생하는 실수입니다. 이런 상황이 닥쳐도 당황하지 마세요!

해결 방법은 간단합니다. 되돌리고 싶은 브랜치의 상태를 담을 새 브랜치를 생성한 다음, 문제가 된 브랜치를 리셋하고 새 브랜치로 체크아웃하여 거기서 커밋하면 됩니다:

git branch new-branch

git reset HEAD~1 --hard

git checkout new-branch

정말 구원자 같지 않나요?

마무리하며

git reset --hard를 실행할 때, 그리고 특정 커밋으로 되돌릴 때는 특히 신중해야 합니다. 프로덕션 코드나 여러 개발자와 협업하는 환경에서는 더욱 그렇습니다. 이런 변경 사항을 적용할 때는 대체로 git revert가 더 안전한 방법입니다. 하지만 그 이야기는 다음 기회에 다루겠습니다. 그때까지 행복한 코딩 되세요! 👋🏻