개발을 진행하던 중 커밋을 잘못 등록하는 실수를 했고, 흔히 알려진 대로 터미널에 git reset HEAD^를 입력했다. 그런데 예상과 달리 실행은 되지 않고, 뜬금없이 more?라는 문구만 출력된 채 커서가 깜빡거리는 현상이 발생했다.
오늘은 이 more? 문구가 왜 뜨는지(나도 그랬다...)에 대한 원인과 해결 방법,
그리고 상황에 맞춰 안전하게 커밋을 취소하는 세 가지 리셋(Reset) 전략에 대해 정리해 보았다.
1. 상황별 리셋 전략: Soft vs Mixed vs Hard
단순히 HEAD^로 돌아가는 것 외에, 특정 시점(로그상의 eb2e173...)으로 돌아가고 싶을 때 작업 내용을 어떻게 처리할지에 따라 전략을 달리해야 함을 알게 되었다.
로그를 확인해보니 돌아가야 할 타겟 커밋은 eb2e17368bad6e1670f341955c83c694d7266035였다. 이 시점으로 리셋할 때 선택할 수 있는 세 가지 옵션을 정리해 보았다.
방법 A: 작업 내용은 살리고 커밋만 취소 (Soft Reset)
가장 권장되는 방식이다. 커밋 이력만 삭제되고, 작업했던 파일들은 'Staging(스테이징)' 상태로 안전하게 남는다.
- 용도: 방금 올린 커밋에서 오타를 수정하거나 파일을 조금 더 추가해서 다시 커밋하고 싶을 때 적합하다.
git reset --soft eb2e173(id)
방법 B: 작업 내용은 살리되 언스테이징 상태로 (Mixed Reset)
옵션을 안 붙였을 때의 기본값이다. 커밋은 취소되고 작업물은 남지만, git add를 다시 해줘야 하는 'Unstaged' 상태가 된다.
# 기본이 mixed다
1. git reset eb2e173(id)
2. git reset --mixed eb2e173(id)
방법 C: 작업 내용까지 완전히 삭제 (Hard Reset)
가장 주의해야 하는 방식이다. 타겟 시점 이후의 모든 작업 내용과 코드를 깔끔하게 날려버린다. 복구가 불가하다고 생각해라...
git reset --hard eb2e173(id)
2. 윈도우에서 git reset HEAD^ 실행 시 more?가 뜨는 이유
명령어를 입력했을 때 진행이 안 되고 more?가 떴던 이유는 내가 사용 중인 윈도우 CMD(명령 프롬프트) 환경의 특성 때문이었다.
Git이나 리눅스 환경과 달리, 윈도우 CMD에서 ^ (Caret, 캐럿) 기호는 탈출 문자(Escape Character)로 사용된다.
즉, 명령어 끝에 ^를 입력하고 엔터를 누르면 시스템은 이를 "명령어가 아직 끝나지 않았고 다음 줄에 입력할 내용이 더 있다"라고 인식한다. 그래서 사용자에게 추가 입력을 요구하며 more?라는 메시지를 띄우는 것이었다.
이 상태에서 빠져나오려면 당황하지 말고 Ctrl + C를 눌러 명령을 취소하면 된다.
3. more? 오류를 피해서 명령어를 입력하는 방법
이 문제를 해결하고 의도했던 대로 "가장 최신 커밋 하나를 취소"하기 위해서는 윈도우 터미널이 ^를 특수 문자로 인식하지 못하게 하거나, 다른 방식으로 표현해야 했다. 해결책은 다음 세 가지가 있었다.
방법 1: 따옴표 사용 (가장 권장)
^ 문자가 시스템 명령어(탈출 문자)로 해석되지 않도록 따옴표(" ")로 감싸주는 방법이다.
git reset "HEAD^"
방법 2: ~ (Tilde) 사용
^ 대신 ~ 기호를 사용하는 방법이다. 여기서 뒤의 숫자 1은 되돌릴 커밋의 개수를 의미한다.
git reset HEAD~1
방법 3: 꺽쇠 두 번 사용
CMD의 특성을 역이용하여 ^를 두 번 입력하면 문자 그대로 하나로 인식된다.
git reset HEAD^^
| 옵션 | 커밋 삭제 | 스테이징 유지 | 파일 수정 보존 | 설명 |
| --mixed | O | X | O | 커밋 취소, 파일은 Unstaged 상태로 보존 (기본값) |
| --soft | O | O | O | 커밋만 취소, 파일은 Staged 상태로 보존 |
| --hard | O | X | X | 모두 삭제하고 해당 시점으로 완전 초기화 |
4. git reset HEAD^의 정확한 의미와 동작 원리
명령어가 제대로 실행된다면 어떤 일이 일어나는지도 명확히 짚고 넘어갈 필요가 있었다.
- HEAD: 현재 내가 위치한 브랜치의 가장 최신 커밋을 가리킨다.
- ^ (Caret): '바로 이전'을 의미한다. 즉 HEAD^는 최신 커밋의 바로 전 단계 조상을 뜻한다.
- 기본 동작 (Mixed Reset): 별도의 옵션 없이 git reset을 사용하면 기본적으로 -mixed 모드로 작동한다. 이는 커밋 이력은 삭제되지만, 해당 커밋에서 수정했던 파일 내용들은 지워지지 않고 내 작업 디렉토리에 'Unstaged(변경 사항)' 상태로 남는다는 것을 의미한다.
5. 리셋 실행 후 확인 절차
리셋을 수행한 뒤에는 반드시 상태가 의도대로 변경되었는지 확인하는 습관을 들여야 했다.
- 명령어 실행: 위에서 결정한 방식(나의 경우 작업 보존을 위해 Soft Reset 선택)으로 명령어를 입력한다.
- 상태 확인 (git status):
- Soft Reset을 했다면 파일들이 초록색(Staged)으로 표시되어야 한다.
- Hard Reset을 했다면 working tree clean이라는 메시지가 뜬다.
- 로그 확인 (git log):
- git log --oneline -n 5를 입력하여 현재 HEAD가 의도했던 eb2e173 커밋을 가리키고 있는지 최종 점검한다.
마무리
결과적으로 나의 상황은 원격 저장소(origin/myBranch)와 로컬의 싱크를 맞추면서, 실수로 올린 파일(docker 및 cursor rule)은 유지해야 했기에 Soft Reset이 가장 안전한 선택이었다.
윈도우 터미널에서 more?가 떴을 때는 당황하지 말고 따옴표를 기억하면 된다.
또한 리셋을 할 때는 내가 작업한 코드를 날릴 것인지 살릴 것인지를 먼저 판단하고 --soft와 --hard 옵션을 신중하게 선택해야 한다는 점을 다시금 확인했다.