git checkout 한 번에 브랜치가 바뀌고 파일이 되돌아간 이유
문제 발생
브랜치를 옮기려고 친 명령이었는데, 브랜치는 그대로고 파일 하나가 되돌아가 있었습니다.
git checkout configconfig라는 브랜치가 있을 거라 생각했지만 실제로는 config라는 파일이 있었고, 그 파일의 수정 내용이 조용히 사라졌습니다. 확인 문구도, 되돌릴 안내도 없었습니다.
원인 분석
git checkout은 서로 관련 없는 두 가지 일을 한 명령에 담고 있습니다. 공식 문서도 두 모드를 나란히 설명합니다.
- 브랜치 전환 —
git checkout <branch> - 파일 복원 —
git checkout <commit> <file>또는git checkout <file>
인자가 브랜치 이름인지 경로인지에 따라 하는 일이 완전히 달라지고, 이름이 겹치면 어느 쪽인지 사람이 예측하기 어렵습니다.
그리고 두 번째 모드는 되돌릴 수 없습니다. 공식 문서의 설명대로, git checkout <file>은 인덱스(스테이징 영역)의 버전으로 작업 트리 파일을 교체하며, 스테이징하지 않은 수정은 그대로 버려집니다. 커밋이 아니었던 내용이므로 git reflog로도 찾을 수 없습니다 — reflog는 커밋된 것의 이동 기록이지 작업 트리의 백업이 아닙니다.
이 혼란 때문에 Git은 역할을 나눈 두 명령을 따로 제공합니다. git checkout 문서의 SEE ALSO도 git-switch와 git-restore를 가리킵니다.
해결 방안
- 브랜치를 다룰 때는
git switch를 씁니다. 브랜치 이외의 인자는 받지 않으므로 파일이 지워질 일이 없습니다.
git switch main
git switch -c feature/search # 새 브랜치 만들고 이동
git switch - # 직전 브랜치로
git switch --detach v1.4.0 # 의도적으로 detached HEAD- 파일을 되돌릴 때는
git restore를 씁니다. 무엇을 어디에서 어디로 되돌리는지가 옵션에 드러납니다.
git restore src/app.ts # 작업 트리를 인덱스 상태로
git restore --staged src/app.ts # 스테이징만 해제 (내용은 유지)
git restore --source=HEAD~2 src/app.ts # 특정 커밋의 내용으로
git restore --staged --worktree src/app.ts # 둘 다- 버릴지 확신이 없으면 먼저 남깁니다. 1초짜리 습관이 되돌릴 수 없는 삭제를 막습니다.
git stash push -m "확인용" src/app.ts--로 경로임을 명시합니다. 옛 명령을 계속 쓰더라도 이름 충돌의 모호함은 없앨 수 있습니다.
git checkout -- config # 확실히 파일
git checkout config -- # 확실히 브랜치/커밋git checkout은 사라지지 않습니다. 공식 문서에 폐기 예정이라고 적혀 있지는 않고, 기존 스크립트와 문서가 모두 이 명령을 씁니다. 새로 손으로 치는 명령만 목적에 맞는 쪽으로 바꾸면 충분합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.