git reset --hard는 인터넷 검색으로 Git 문제를 해결하려는 사람들이 가장 쉽게 마주치는 명령 중 하나이면서, 동시에 가장 흔하게 데이터를 잃게 만드는 명령이기도 하다. 이 장은 5부의 첫 챕터로, reset의 세 모드가 04장의 3단계 모델(작업 트리·스테이징 영역·저장소) 중 정확히 어디까지 되돌리는지 구분한다.
개요
git reset은 현재 브랜치(HEAD)가 가리키는 커밋을 다른 커밋으로 옮기는 명령이며, 세 가지 모드가 옮기는 범위를 결정한다.
| |
HEAD~1은 현재 커밋의 바로 이전 커밋을 가리키는 표기로, 09장에서 다룬 커밋 그래프를 부모 방향으로 한 칸 거슬러 올라간 지점이다.
기본 개념
세 모드의 차이는 04장의 3단계 모델과 정확히 대응하며, 문단만으로는 “어디까지 영향을 주는가"를 헷갈리기 쉬우므로 그림으로 범위를 겹쳐 보는 편이 명확하다.
flowchart TB
subgraph soft["--soft"]
direction LR
s1["저장소(HEAD)"]:::changed --> s2["스테이징 영역"] --> s3["작업 트리"]
end
subgraph mixed["--mixed(기본값)"]
direction LR
m1["저장소(HEAD)"]:::changed --> m2["스테이징 영역"]:::changed --> m3["작업 트리"]
end
subgraph hard["--hard"]
direction LR
h1["저장소(HEAD)"]:::changed --> h2["스테이징 영역"]:::changed --> h3["작업 트리"]:::changed
end
classDef changed fill:#f96,stroke:#333
--soft는 HEAD만 옮기므로, 되돌려진 커밋의 변경 사항은 스테이징 영역에 그대로 남아 있다 — 커밋을 취소하고 다시 커밋 메시지만 고쳐 쓰고 싶을 때 유용하다. --mixed(옵션을 생략했을 때의 기본값)는 HEAD와 스테이징 영역까지 옮기므로, 변경 사항은 작업 트리에 스테이징 안 된 상태로 남는다 — 커밋 단위를 다시 나누고 싶을 때 유용하다. --hard는 셋 다 옮기므로, 작업 트리의 실제 파일 내용까지 되돌려진 커밋 상태로 강제로 맞춰지며, 그 사이의 모든 변경 사항이 사라진다.
종류/세부
특정 파일만 되돌리기
reset은 브랜치 전체가 아니라 특정 파일만 대상으로 지정할 수도 있다. 이 경우 05장에서 다룬 “스테이징만 취소"하는 동작이 된다.
| |
잘못된 커밋을 완전히 취소하기(soft reset + 재커밋)
방금 만든 커밋의 메시지를 고치고 싶다면 08장의 --amend가 더 직접적이지만, 여러 커밋을 하나로 합치면서 메시지도 새로 쓰고 싶다면 soft reset이 더 유연하다.
| |
이 패턴은 27장에서 다루는 rebase -i의 “squash"와 결과가 비슷하지만, 조작이 더 단순한 대신 세밀한 순서 조정은 할 수 없다.
주의사항·함정
--hard는 커밋되지 않은 작업을 되돌릴 수 없이 지운다: 이것이 이 명령에 대한 가장 중요한 경고다. 스테이징되지 않은 작업 트리의 변경, 스테이징됐지만 커밋되지 않은 변경 모두 --hard 앞에서는 흔적 없이 사라진다. 실행 전 git status(06장)로 지금 무엇이 사라질지 반드시 확인해야 한다.
되돌려진 커밋 자체는 즉시 사라지는 것이 아니다: reset으로 브랜치 포인터가 옮겨지면, 그 이전에 가리키던 커밋들은 어떤 브랜치에서도 참조되지 않는 상태(unreachable)가 된다. 완전히 삭제되는 것은 아니고 28장의 git reflog로 복구할 여지가 얼마간 남아 있지만, 이는 안전망이지 의도적으로 의존할 방법은 아니다.
이미 push된 커밋을 reset하면 15장·20장과 같은 문제가 생긴다: reset도 리베이스와 마찬가지로 브랜치 히스토리를 재작성하는 효과를 낸다. 이미 원격에 공유된 커밋을 reset한 뒤 push하려면 강제 push가 필요하며, 그로 인한 위험은 20장에서 다룬 것과 동일하다. 공유된 히스토리를 안전하게 취소하고 싶다면 24장에서 다루는 git revert가 더 나은 선택이다.
![Featured image of post [Git] 23. git reset — soft/mixed/hard](/post/git/git-reset-command-soft-mixed-hard/wordcloud_hu_fdc601237bbe4e50.webp)
![[Git] 21. Fork와 Pull Request 워크플로(GitHub Flow)](/post/git/fork-pull-request-workflow-github-flow/wordcloud_hu_681908459f6099a8.webp)
![[Git] 22. git tag — 릴리스 태깅](/post/git/git-tag-command-release-tagging/wordcloud_hu_f2c27c45177f6c2c.webp)
![[Git] 23. git reset — soft/mixed/hard](/post/git/git-reset-command-soft-mixed-hard/wordcloud_hu_4a537338fdc7a2ba.webp)
![[Git] 24. git revert — 안전한 되돌리기](/post/git/git-revert-command-safe-undo/wordcloud_hu_a9a3aa26ca794b13.webp)
![[Git] 25. git restore와 git checkout -- <file>](/post/git/git-restore-checkout-file-discard-changes/wordcloud_hu_cd1210130e27a947.webp)
![[Git] 06. git status — 상태 확인](/post/git/git-status-command-check-working-tree-state/wordcloud_hu_47937000002ad2ce.webp)
![[Git] 09. git log — 히스토리 조회](/post/git/git-log-command-view-history/wordcloud_hu_bc1a6a01030ca9b3.webp)
![[Git] 28. git reflog — 실수 복구](/post/git/git-reflog-command-recover-lost-commits/wordcloud_hu_67933a4c82ea14b7.webp)
![[Git] 44. 자주 발생하는 Git 에러와 해결법 총정리](/post/git/common-git-errors-and-solutions/wordcloud_hu_5251c239f8e16968.webp)
![[Git] 07. git diff — 변경 비교](/post/git/git-diff-command-compare-changes/wordcloud_hu_3b0ce1ca4361f1f6.webp)