Git에서 변경 사항 되돌리기: Reset, Restore, Revert 총정리

`git reset`, `git restore`, `git revert` 때문에 헷갈리시나요? 이 가이드는 이 명령어들의 차이점을 명확히 설명하고 실용적인 예시를 제공합니다. Git 히스토리에서 변경 사항을 안전하게 버리고, 파일을 스테이지에서 내리고, 커밋을 재작성하거나 안전하게 되돌리는 방법을 배우세요. 효과적인 버전 관리와 깔끔한 프로젝트 타임라인을 위해 이 필수 명령어들을 마스터해 보세요.

46 조회수

Git에서 변경 사항 되돌리기: Reset, Restore, Revert 설명

Git은 코드베이스 변경 사항을 추적할 수 있게 해주는 강력한 버전 관리 시스템입니다. 하지만 실수는 발생할 수 있으며, 변경 사항을 되돌려야 할 수도 있습니다. Git은 이를 돕기 위해 여러 명령어를 제공하지만, 이들은 기능이 매우 다르고 저장소에 각기 다른 방식으로 영향을 미칩니다. git reset, git restore, git revert 간의 미묘한 차이를 이해하는 것은 프로젝트 히스토리를 효과적으로 관리하고 의도치 않은 결과를 초래하지 않으면서 오류를 수정하는 데 매우 중요합니다.

이 글에서는 이 세 가지 명령어의 목적, 작동 방식, 그리고 각각 언제 사용해야 하는지를 설명하여 명확하게 알려드리겠습니다. 명확한 설명과 실용적인 예제를 제공하기 위해 공식 Git 문 서와 일반적인 사용 패턴을 활용할 것입니다. 이 가이드가 끝나면 변경 사항을 자신 있게 되돌리고, 스테이징된 파일을 관리하며, 깔끔하고 일관된 커밋 히스토리를 유지할 수 있는 역량을 갖추게 될 것입니다.

핵심 개념 이해하기

명령어로 들어가기 전에 몇 가지 Git 개념을 파악하는 것이 중요합니다.

  • 작업 디렉토리(Working Directory): 현재 편집 중인 파일입니다.
  • 스테이징 영역(Staging Area/Index): 커밋하기 전에 변경 사항을 준비하는 임시 영역입니다. git add는 작업 디렉토리의 변경 사항을 스테이징 영역으로 이동시킵니다.
  • 커밋 히스토리(Commit History): 커밋으로 표현되는, 시간의 흐름에 따른 프로젝트 스냅샷의 연속입니다.
  • HEAD: 현재 브랜치의 가장 최근 커밋을 가리키는 포인터입니다.

이 세 가지 명령어는 주로 이러한 영역들과 상호 작용하여 변경 사항을 수정하거나 폐기합니다.

git restore: 작업 디렉토리 및 스테이징 영역의 변경 사항 폐기

Git에 비교적 최근에 추가된 git restore 명령어는 작업 디렉토리의 변경 사항을 되돌리거나 파일을 스테이징 해제하는 간단한 작업을 위해 설계되었습니다. 이러한 특정 작업에 대해서는 일반적으로 git reset보다 안전하고 직관적인 것으로 간주됩니다.

파일 스테이징 해제

실수로 git add를 사용하여 파일을 스테이징했다가 이를 해제하고 싶다면 git restore가 사용할 명령어입니다. 이 명령어는 스테이징 영역에서 작업 디렉토리로 변경 사항을 되돌리지만, 수정 자체를 폐기하지는 않습니다.

  • 특정 파일 스테이징 해제:
    bash git restore <file>
    이 명령어는 인덱스(스테이징 영역)에서 파일 버전을 가져와 인덱스로 다시 넣습니다. 본질적으로 다음 커밋을 위해 파일이 스테이징되는 것을 방지하지만, 작업 디렉토리에는 변경 사항이 그대로 남아 있습니다.

  • 모든 파일 스테이징 해제:
    git reset이 할 수 있는 방식으로 모든 스테이징을 해제하는 직접적인 git restore . 명령은 없지만, 일반적으로 개별 파일에 git restore를 적용하거나 필요한 경우 다른 명령어와 함께 사용합니다. 그러나 가장 일반적인 사용 사례는 특정 파일의 스테이징을 해제하는 것입니다.

작업 디렉토리의 변경 사항 폐기

git restore는 특정 파일에 대한 작업 디렉토리의 모든 스테이징되지 않은 변경 사항을 폐기하고, 이를 스테이징 영역(인덱스) 또는 마지막 커밋 상태로 되돌리는 데도 사용될 수 있습니다.

  • 파일의 스테이징되지 않은 변경 사항 폐기:
    bash git restore <file>
    (참고: 이 명령어는 컨텍스트에 따라 두 가지 의미를 가질 수 있습니다. --staged 없이 사용될 경우 주로 작업 트리(working tree)를 대상으로 합니다. 파일이 스테이징된 경우 스테이징을 해제합니다. 파일이 작업 트리에서 수정되었지만 스테이징되지 않은 경우, 작업 트리의 파일을 인덱스와 일치하도록 되돌립니다.)

  • 파일의 스테이징 및 스테이징되지 않은 모든 변경 사항 폐기 (HEAD로 복원):
    파일에 대한 모든 변경 사항(스테이징 및 스테이징되지 않은 변경 사항 모두)을 완전히 폐기하고 HEAD 커밋 시점의 상태로 되돌리려면 다음을 사용합니다.
    bash git restore --staged --worktree <file>
    이것은 파일을 마지막 커밋 상태로 효과적으로 재설정하는 강력한 명령어입니다.

특정 커밋에서 파일 복원

git restore는 브랜치 히스토리를 변경하지 않고 과거 커밋에서 특정 파일 버전을 검색하는 데도 사용할 수 있습니다.

git restore <file> --source <commit>

<commit>을 커밋 해시 또는 HEAD~1과 같은 심볼릭 참조로 바꾸십시오.

git reset: 히스토리 다시 쓰기

git reset은 현재 브랜치의 HEAD 포인터를 이동시켜 커밋 히스토리를 수정할 수 있는 더 강력한 명령어입니다. 사용되는 모드에 따라 스테이징 영역과 작업 디렉토리에도 영향을 줄 수 있습니다.

모드 이해하기 (--soft, --mixed, --hard)

git reset에는 세 가지 주요 모드가 있습니다.

  1. --soft: 지정된 커밋으로 HEAD를 이동하지만, 스테이징 영역과 작업 디렉토리는 그대로 둡니다. 되돌려진 커밋의 변경 사항은 스테이징된 변경 사항으로 나타납니다.
    bash git reset --soft HEAD^ # HEAD를 한 커밋 뒤로 이동시키고, 되돌려진 커밋의 변경 사항은 스테이징됨

  2. --mixed (기본값): HEAD를 이동하고 스테이징 영역을 지정된 커밋과 일치하도록 재설정합니다. 되돌려진 커밋의 변경 사항은 작업 디렉토리에 존재하지만 스테이징되지 않습니다.
    bash git reset HEAD^ # git reset --mixed HEAD^ 와 동일 # HEAD를 한 커밋 뒤로 이동시키고, 되돌려진 커밋의 변경 사항은 스테이징되지 않음

  3. --hard: HEAD를 이동하고 스테이징 영역과 작업 디렉토리를 모두 지정된 커밋과 일치하도록 재설정합니다. 이것은 되돌려지는 커밋의 모든 변경 사항과 작업 디렉토리의 커밋되지 않은 모든 변경 사항을 폐기합니다. 매우 주의해서 사용하십시오.
    bash git reset --hard HEAD~ # 마지막 커밋과 그 이후의 모든 변경 사항(작업 디렉토리 및 스테이징 영역)을 폐기함

git reset 사용 사례:

  • 파일 스테이징 해제: git reset <file>git restore --staged <file>의 바로가기로, 작업 디렉토리에 영향을 주지 않고 파일의 스테이징을 해제합니다.
  • 모든 스테이징 해제: git reset (인수 없이 또는 HEAD 지정)은 현재 스테이징된 모든 변경 사항의 스테이징을 해제하고 작업 디렉토리로 되돌립니다 (git restore --staged .과 동일).
  • 마지막 커밋 되돌리기: git reset HEAD^ (또는 git reset --soft HEAD^)는 마지막 커밋을 수정하는 데 일반적으로 사용됩니다. 이전 커밋의 변경 사항이 이제 스테이징되어 수정 또는 새 메시지로 다시 커밋할 준비가 됩니다.
  • 모든 로컬 변경 사항 폐기: git reset --hard는 모든 로컬 수정 사항(스테이징 및 스테이징되지 않은 변경 사항)을 완전히 폐기하고 저장소를 특정 커밋으로 되돌리는 데 사용됩니다. 이것은 파괴적인 작업입니다.

오래된 커밋 재설정

가장 최근 커밋이 아닌 커밋의 변경 사항을 되돌려야 하는 경우 git reset을 사용할 수 있습니다. 예를 들어, 문제가 있는 커밋 이전의 커밋으로 재설정하려면 다음을 사용합니다.

# 예시: 마지막 2개의 커밋을 되돌리고 변경 사항은 스테이징되지 않은 상태로 유지
git reset --mixed HEAD~2

경고: git reset은 히스토리를 다시 씁니다. 이미 푸시한 커밋을 재설정하면 협업자에게 심각한 문제를 일으킬 수 있습니다. 로컬 저장소에만 있는 커밋은 일반적으로 안전하게 재설정할 수 있습니다.

git revert: 변경 사항을 되돌리기 위한 새 커밋 생성

git revert는 공유되거나 게시된 히스토리의 변경 사항을 되돌리는 가장 안전한 방법입니다. 히스토리를 다시 쓰는 대신, 이전 커밋의 반대 변경 사항을 도입하는 새로운 커밋을 생성합니다.

작동 방식

git revert <commit>을 실행하면 Git은 지정된 커밋을 분석하고, 반대 변경 사항을 계산하여 현재 작업 디렉토리와 스테이징 영역에 적용합니다. 그런 다음 되돌려지는 커밋을 나타내는 기본 메시지로 새 커밋을 생성하도록 안내합니다.

  • 특정 커밋 되돌리기:
    bash git revert <commit-hash>
    이것은 <commit-hash>에서 도입된 변경 사항을 취소하는 새 커밋을 생성합니다. 병합 충돌이 발생하면 Git이 일시 중지되고 커밋하기 전에 충돌을 해결해야 합니다.

  • 여러 커밋 되돌리기:
    커밋 범위를 되돌릴 수 있습니다.
    bash # HEAD~3부터 HEAD 직전까지의 커밋 되돌리기 git revert HEAD~3..HEAD
    Git은 지정된 각 커밋에 대해 되돌리기 커밋을 생성하려고 시도합니다. 프로세스 중에 충돌이 발생하면 각 되돌리기에 대해 충돌을 해결해야 합니다.

git revert의 장점:

  • 히스토리 보존: 기존 커밋을 변경하지 않아 공개 또는 공유 브랜치에 안전합니다.
  • 명확한 감사 추적: 되돌리기 커밋은 무엇이 되돌려졌는지, 왜 그랬는지를 명시적으로 나타냅니다.
  • 병합을 능숙하게 처리: Git은 종종 병합 커밋을 자동으로 되돌릴 수 있지만, 복잡한 시나리오에서는 수동 개입이 필요할 수 있습니다.

git revert 사용 시기:

  • 이미 원격 저장소에 푸시된 브랜치의 변경 사항을 되돌려야 할 때.
  • 수정 사항을 포함한 모든 변경 사항에 대한 명확하고 불변하는 기록을 유지하고 싶을 때.
  • 병합 커밋을 되돌릴 때.

올바른 명령어 선택하기

결정을 돕기 위한 간단한 가이드입니다.

  • 파일 스테이징을 해제하려면: git restore <file> 또는 git reset <file>을 사용하십시오.
  • 파일의 작업 디렉토리에서 스테이징되지 않은 변경 사항을 폐기하려면: git restore <file>을 사용하십시오.
  • 파일에 대한 모든 변경 사항(스테이징 및 스테이징되지 않은 변경 사항)을 폐기하려면: git restore --staged --worktree <file>을 사용하십시오.
  • 마지막 커밋을 되돌리고 변경 사항을 스테이징 상태로 유지하려면 (수정용): git reset --soft HEAD^를 사용하십시오.
  • 마지막 커밋을 되돌리고 변경 사항을 스테이징되지 않은 상태로 유지하려면: git reset HEAD^를 사용하십시오.
  • 마지막 커밋과 모든 후속 변경 사항을 완전히 폐기하려면 (파괴적): git reset --hard HEAD^를 사용하십시오.
  • 히스토리를 다시 쓰지 않고 공유 브랜치의 커밋을 되돌리려면: git revert <commit-hash>를 사용하십시오.
  • 저장소 전체의 모든 로컬 변경 사항을 폐기하려면 (파괴적): git reset --hard를 사용하십시오.

결론

git reset, git restore, git revert를 숙달하는 것은 효과적인 Git 사용의 기본입니다. git restore는 작업 디렉토리와 스테이징 영역의 변경 사항을 안전하게 폐기하는 데 가장 유용한 도구입니다. git reset은 강력한 히스토리 다시 쓰기 기능을 제공하며, 로컬에서 푸시되지 않은 커밋에 사용하는 것이 가장 좋습니다. git revert는 특히 협업 환경에서 중요한, 변경 사항을 되돌리기 위한 안전하고 히스토리를 보존하는 방법을 제공합니다. 각 명령어의 고유한 동작 방식을 이해하고 적절한 명령어를 선택함으로써 프로젝트의 발전을 자신 있게 관리하고 발생하는 모든 실수를 수정할 수 있습니다.