Git 실전 · 되돌리기(reset·revert·reflog) · 실습
reset·revert·reflog 실습
목표
reset 세 모드, amend, revert, reflog 를 각각 독립된 저장소에서 실행해 결과를 비교하고, 상황별로 무엇을 써야 하는지 치트시트로 정리합니다. 산출물은 /root/gitx2/ 아래에 둡니다.
왜 중요한가
되돌리기 사고의 대부분은 명령을 몰라서가 아니라, 그 명령이 무엇까지 덮어쓰는지 모르고 실행해서 생깁니다. --soft 는 잃는 것이 없고, 기본값 --mixed 는 스테이징 상태만 잃으며, --hard 는 커밋되지 않은 모든 변경을 잃습니다. 위험도는 명령 이름이 아니라 "이 명령이 커밋되지 않은 변경을 덮어쓰는가"로 매겨야 합니다. 그리고 두 번째 축이 있습니다. 커밋이 이미 다른 사람의 저장소에 있다면 그 커밋을 없애는 모든 방법은 남의 이력을 깨뜨립니다. 그때는 이력을 고치는 대신 덧붙이는 것이 답입니다. 이 실습은 그 차이를 말이 아니라 커밋 개수와 파일 존재 여부로 확인시켜 줍니다.
단계
전역 git 신원이 없습니다. 저장소를 만들 때마다 로컬 user.email / user.name 을 설정해야 커밋이 됩니다.
1. /root/gitx2/mkrepo.sh 를 만들고 chmod +x 합니다. 첫 인자($1)로 받은 경로에(없으면 만들고) 저장소를 초기화하고, 브랜치는 main, 커밋 5개를 만듭니다. n번째 커밋은 fn.txt(f1.txt … f5.txt)를 추가하고 제목은 c1 … c5 입니다. 채점기는 임시 디렉터리에 이 스크립트를 실행해 확인하므로, 경로를 하드코딩하지 말고 반드시 "$1" 을 쓰세요.
2. /root/gitx2/amend 에 스크립트로 저장소를 만들고, 마지막 커밋의 제목만 c5 fixed 로 바꿉니다. 커밋 수는 5개 그대로여야 하고, reflog 에 amend 기록이 남아야 하며, 바뀌기 전 해시와 현재 해시는 달라야 합니다.
3. /root/gitx2/soft 에 저장소를 만들고 커밋 하나를 되돌립니다. 결과: 커밋 4개, f5.txt 가 인덱스에 스테이징된 상태, 작업 트리에도 f5.txt 존재.
4. /root/gitx2/mixed 에 저장소를 만들고 커밋 하나를 되돌립니다. 결과: 커밋 4개, f5.txt 가 스테이징돼 있지 않고, 작업 트리에는 남아 있어야 합니다(git status --porcelain 에서 ?? 또는 M).
5. /root/gitx2/hard 에 저장소를 만들고 커밋 하나를 되돌립니다. 결과: 커밋 4개, f5.txt 가 사라지고, f4.txt 는 남아 있으며, 작업 트리가 완전히 깨끗해야 합니다.
6. /root/gitx2/revert 에 저장소를 만들고 c3 커밋의 변경만 상쇄합니다. 결과: 커밋 6개, 제목이 Revert 로 시작하는 커밋 존재, 원래의 c3 커밋도 이력에 그대로 남아 있을 것, f3.txt 는 사라지고 f1/f2/f4/f5.txt 는 남아 있을 것.
7. /root/gitx2/reflog 에 저장소를 만듭니다. 되돌리기 전에 현재 HEAD 해시를 /root/gitx2/before.txt 에 저장합니다(파일에는 해시 문자열만 있어야 합니다). 그다음 커밋 2개를 강제로 날렸다가, 참조 로그를 보고 원래 위치로 복구합니다. 결과: HEAD 가 기록해 둔 해시와 같고 커밋은 5개, reflog 에 reset 기록이 남아 있어야 합니다.
8. /root/gitx2/undo.md 에 치트시트를 씁니다. 본문에 --soft, --mixed, --hard, revert, reflog 가 모두 등장해야 하고, 아래 세 줄이 있어야 합니다.
pushed=— 이미 푸시해서 다른 사람이 받아 간 커밋을 되돌릴 때 쓸 명령 (한 단어)staging_only=— 스테이징만 풀고 파일은 남기는 reset 옵션worktree_wiped=— 커밋되지 않은 변경까지 날리는 reset 옵션
참고
- 스크립트 뼈대:
mkdir -p "$1"→git -C "$1" init -q -b main→git -C "$1" config user.email ...→ 반복문으로 파일 생성·git add·git commit -m "c$i". - 해시 저장:
git rev-parse HEAD > /root/gitx2/before.txt로 하면 해시만 들어갑니다.git log출력을 그대로 넣으면 형식 검사에서 걸립니다. - 잃어버린 커밋 찾기:
git reflog에서HEAD@{1}같은 표기를 쓰거나 왼쪽에 보이는 해시를 그대로 씁니다. - 흔한 실수 1: 3~5단계를 같은 저장소에서 이어서 하는 것. 각 단계는 별도 디렉터리에서 깨끗한 상태로 시작해야 합니다.
- 흔한 실수 2: 6단계에서
git reset을 쓰는 것. 커밋 수가 줄어들면 실패합니다. revert 는 과거를 지우지 않고 반대 커밋을 하나 더 쌓습니다. git revert는 편집기를 열 수 있습니다.--no-edit를 붙이면 그대로 진행됩니다.
단계 8개
- 저장소 생성 스크립트 만들기
- 마지막 커밋 메시지 고치기
- 커밋만 풀고 스테이징은 남기기
- 인덱스까지 되돌리기
- 작업 트리까지 되돌리기
- 이력을 남기며 되돌리기
- 잃어버린 커밋 되찾기
- 상황별 치트시트 정리