10. 되돌리기 — 리셋(Reset)과 리버트(Revert)
🎯 이 장의 목표
- 커밋을 되돌리는 두 방식, 리셋과 리버트의 차이를 이해한다
reset의 soft / mixed / hard 옵션을 명확히 구분한다revert로 안전하게 되돌리는 법을 익힌다- 실수했을 때
reflog로 복구하는 법을 안다
10.1 되돌리기의 두 철학: Reset vs Revert
실수한 커밋을 되돌리는 방법은 크게 두 가지이며, 철학이 완전히 다릅니다.
| Reset (리셋) | Revert (리버트) | |
|---|---|---|
| 방식 | 커밋을 없던 일로 되감기 | 되돌리는 새 커밋을 추가 |
| 이력 | 역사를 지움/변경 | 역사를 보존 (취소 기록 남김) |
| 안전성 | 위험 (공유 커밋엔 부적합) | 안전 (공유 커밋에도 OK) |
| 비유 | 타임머신으로 과거로 회귀 | "취소했음"을 일지에 적기 |
💡 팁
핵심 구분- 혼자만의 로컬 커밋을 정리 → Reset
- 이미 push해서 공유된 커밋을 되돌리기 → Revert (반드시!)
10.2 리셋(Reset)의 3가지 모드
git reset은 HEAD(현재 위치)를 과거 커밋으로 옮깁니다. 이때 워킹 디렉터리와 스테이지를 어떻게 처리하느냐에 따라 세 가지 모드가 있습니다. 이것이 reset 이해의 전부입니다.
CODE
--soft --mixed(기본) --hard 커밋 이력 되돌림 ✅ ✅ ✅ 스테이지 비움 ❌ ✅ ✅ 워킹 디렉터리 변경 ❌ ❌ ✅ (파일도 되돌림!)
세 영역(워킹 디렉터리 / 스테이지 / 저장소)을 떠올리며 보면 명확합니다.
① --soft — 커밋만 취소, 변경은 스테이지에 남김
BASH
git reset --soft HEAD~1
- 마지막 커밋을 취소하지만, 그 변경 내용은 스테이지에 그대로 남습니다.
- "커밋 메시지만 다시 쓰고 싶을 때", "마지막 커밋을 합치고 싶을 때" 유용합니다.
- 바로 다시
git commit하면 새 커밋이 됩니다.
CODE
커밋 취소 → 변경은 "git add된 상태(스테이지)"로 보존
② --mixed — 커밋·스테이지 취소, 변경은 워킹에 남김 (기본값)
BASH
git reset HEAD~1 # 옵션 생략하면 --mixed git reset --mixed HEAD~1
- 커밋을 취소하고 스테이지도 비웁니다.
- 변경 내용은 워킹 디렉터리에 수정된 상태로 남습니다.
- "커밋과 add를 모두 무르고, 파일은 다시 손보고 싶을 때" 사용합니다. 가장 흔히 쓰입니다.
CODE
커밋 취소 + add 취소 → 변경은 "수정됨(Modified)" 상태로 보존
③ --hard — 전부 되돌림 ⚠️ (파일 내용까지!)
BASH
git reset --hard HEAD~1
- 커밋, 스테이지, 그리고 워킹 디렉터리의 파일 내용까지 모두 과거로 되돌립니다.
- 마지막 커밋 이후의 모든 작업이 사라집니다.
🚨 매우 위험: --hard는 커밋 안 한 작업을 복구 불가능하게 삭제합니다. 정말 다 버려도 되는지 세 번 확인하세요. (단, "커밋했던" 내용은 reflog로 살릴 수 있습니다 — 10.6 참고.)
비유로 정리
📦 이사 비유 (마지막 커밋 = 방금 싼 택배 상자)
--soft: 상자만 풀기 (물건은 책상 위 그대로 = 스테이지)--mixed: 상자 풀고 물건도 여기저기 흩어놓기 (= 워킹 디렉터리)--hard: 상자째 버리기 (물건도 전부 사라짐 😱)
10.3 리셋 실전 활용
마지막 커밋 메시지를 다시 쓰고 싶을 때
BASH
git reset --soft HEAD~1 git commit -m "올바른 메시지"
(또는 더 간단히 git commit --amend)
여러 커밋을 하나로 합치고 싶을 때
BASH
git reset --soft HEAD~3 # 최근 3개 커밋 취소(변경은 스테이지에 모임) git commit -m "Combine three commits into one"
스테이지만 비우기 (커밋은 유지)
BASH
git reset # = git reset --mixed HEAD # 또는 특정 파일만 git restore --staged file.txt
특정 커밋으로 이동
BASH
git reset --hard a1b2c3d # 해당 커밋 상태로 완전히 되돌림(주의)
소스트리에서는 커밋을 우클릭 → "Reset current branch to this commit"을 선택하고 Soft/Mixed/Hard를 고를 수 있습니다. 시각적으로 어느 커밋으로 가는지 보여 실수를 줄여줍니다.
10.4 리버트(Revert) — 안전한 되돌리기
revert는 과거를 지우지 않습니다. 대신 "그 커밋의 변경을 정반대로 적용하는 새 커밋"을 추가합니다. 역사가 그대로 남으므로 협업에 안전합니다.
gitGraph
commit id: "A"
commit id: "B"
commit id: "C (되돌릴 대상)"
commit id: "C' (C의 반대)" type: REVERSE
revert는 C를 지우지 않습니다. C의 변경을 정반대로 적용한 새 커밋 C'를 추가할 뿐이라, C는 이력에 그대로 보존됩니다.
BASH
git revert HEAD # 마지막 커밋 되돌리기 git revert a1b2c3d # 특정 커밋 되돌리기
- 실행하면 되돌림 커밋의 메시지 편집기가 열립니다(기본값 OK).
- 결과적으로 코드는 그 커밋 이전 상태가 되지만, 이력에는 "되돌렸다"는 기록이 남습니다.
💡 팁
왜 push한 커밋엔 revert를 쓸까? reset은 역사를 지워서, 이미 그 커밋을 받아간 동료와 어긋납니다. 반면 revert는 정상적인 "새 커밋 추가"라서 누구와도 충돌 없이 공유됩니다. 공유된 코드를 되돌릴 땐 무조건 revert.병합 커밋 되돌리기
병합 커밋은 부모가 둘이라, 어느 쪽을 기준으로 되돌릴지 지정해야 합니다.
BASH
git revert -m 1 <병합커밋해시> # 보통 1번 부모(병합 받은 쪽) 기준
여러 커밋을 한 번에, 커밋은 만들지 않고 모아서 처리할 수도 있습니다.
BASH
git revert --no-commit HEAD~2..HEAD # 변경만 모으고 git commit -m "Revert recent changes" # 한 번에 커밋
소스트리에서는 커밋 우클릭 → "Reverse commit"으로 동일하게 실행됩니다.
10.5 작업·병합 취소 빠른 참조
| 하고 싶은 것 | 명령 |
|---|---|
| 워킹 디렉터리 수정 버리기 | git restore <file> |
| 스테이지에서 내리기 | git restore --staged <file> |
| 마지막 커밋 취소(변경 유지) | git reset --soft HEAD~1 |
| 마지막 커밋+add 취소(변경 유지) | git reset HEAD~1 |
| 마지막 커밋 완전 폐기 | git reset --hard HEAD~1 ⚠️ |
| 진행 중 병합 취소 | git merge --abort |
| 진행 중 리베이스 취소 | git rebase --abort |
| 공유된 커밋 안전하게 되돌리기 | git revert <commit> |
10.6 실수했을 때의 구원자 — git reflog
"reset --hard로 커밋을 날렸어요! 끝장인가요?" 대부분 아닙니다. Git은 HEAD가 움직인 모든 기록을 reflog에 남겨둡니다.
BASH
git reflog
CODE
a1b2c3d (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
e5f6g7h HEAD@{1}: commit: Important work I thought I lost
c3d4e5f HEAD@{2}: commit: Earlier work
날린 줄 알았던 커밋(e5f6g7h)이 보입니다. 그곳으로 돌아가면 복구됩니다.
BASH
git reset --hard e5f6g7h # 잃어버린 커밋으로 복귀 # 또는 안전하게 새 브랜치로 git switch -c recovered e5f6g7h
💡 팁
reflog는 Git의 블랙박스입니다. "커밋했던" 내용은 웬만하면 reflog로 살릴 수 있습니다(기본 90일 보관). 단, 한 번도 커밋한 적 없는 변경(워킹 디렉터리에만 있던 것)은 reflog로도 못 살리니, reset --hard나 git clean 전에는 항상 신중하세요.10.7 리셋 작업 시 주의사항 정리
--hard와git clean은 되돌릴 수 없는 작업을 포함한다. 실행 전git status로 무엇이 사라질지 확인.- 이미 push한 커밋은 reset 하지 말 것. 공유 이력엔 revert를 사용.
- 헷갈리면 일단 현재 상태를 새 브랜치로 백업:
git switch -c backup. - 막히면
git reflog를 떠올린다.
10.8 이 장에서 배운 것 (요약)
- Reset: 역사를 되감음(로컬 정리용). Revert: 되돌림 커밋 추가(공유 안전)
- reset 3모드: soft(커밋만)/mixed(커밋+add, 기본)/hard(전부, 위험)
- 공유된(push된) 커밋을 되돌릴 땐 반드시 revert
- 병합/리베이스 중단은
--abort git reflog로 잃어버린 커밋 복구 (단, 커밋한 적 있는 것만)
✍️ 확인 문제
reset --soft,--mixed,--hard는 각각 어디까지 되돌리나요?- 동료와 공유 중인 main의 잘못된 커밋을 되돌릴 때 reset과 revert 중 무엇을 써야 하나요?
reset --hard로 커밋을 날렸습니다. 가장 먼저 시도할 명령은?
여기까지가 3부(합치기와 되돌리기)입니다. 다음 단계(마지막)에서는 버전을 표시하고 배포하는 태그(Tag)를 다룹니다.