브랜치 전체가 아니라 파일 하나만 “방금 수정한 내용을 취소하고 싶다"는 요구는 실무에서 매우 자주 생긴다. 12장에서 이미 checkout -- <file>과 restore의 관계를 짧게 언급했는데, 이 장은 그 되돌리기 동작 자체를 정면으로 다룬다.
개요
Git 2.23 이상에서는 파일 내용 복원 전용 명령이 분리되어 있다.
| |
두 명령 모두 스테이징되지 않은(unstaged, 04장) 작업 트리 변경만 대상으로 한다. 스테이징까지 된 변경을 되돌리려면 05장에서 다룬 --staged 옵션이 필요하다.
기본 개념
git restore가 존재하는 이유는 12장에서 다룬 git checkout의 중의성 문제와 같다 — 예전에는 “파일을 되돌린다"와 “브랜치를 바꾼다"는 서로 다른 두 개념을 같은 명령이 인자 형태로만 구분해 처리했다. git restore는 오직 파일 복원만 담당하도록 의도가 명확한 이름으로 새로 만들어졌다.
git restore가 다루는 두 영역은 옵션으로 구분한다.
| 명령 | 대상 | 결과 |
|---|---|---|
git restore <file> | 작업 트리 | 파일 내용을 스테이징 영역(비어 있으면 HEAD) 상태로 되돌림 |
git restore --staged <file> | 스테이징 영역 | 스테이징만 취소(05장에서 이미 다룬 내용), 작업 트리는 그대로 |
git restore --staged --worktree <file> | 둘 다 | 스테이징도 취소하고 작업 트리도 마지막 커밋 상태로 되돌림 |
종류/세부
임의의 커밋에서 파일 복원하기(--source)
방금 커밋한 상태가 아니라, 훨씬 이전 커밋에 있던 특정 파일의 버전을 지금 작업 트리로 가져오고 싶을 때가 있다.
| |
이 명령은 a1b2c3d 커밋 시점의 README.md 내용으로 지금 작업 트리의 해당 파일만 덮어쓴다. 다른 파일이나 커밋 히스토리 자체에는 영향을 주지 않으므로, “이 파일만 예전 버전으로 되돌리고 싶다"는 상황에 정확히 맞는 도구다.
| |
전체 파일을 되돌리기(디렉터리 지정)
여러 파일을 한 번에 되돌리고 싶다면 경로에 디렉터리나 .을 지정한다.
| |
이 명령은 05장에서 다룬 git add .의 범위 규칙과 동일하게 동작한다 — 명령을 실행한 위치를 기준으로 한다.
주의사항·함정
되돌린 작업 트리 변경은 복구할 수 없다: git restore(스테이징되지 않은 변경 대상)는 04장에서 설명했듯 아직 Git 객체로 저장된 적이 없는 내용을 되돌린다. 즉 이 명령이 지우는 내용은 애초에 저장소 어디에도 백업되어 있지 않으므로, 23장의 reset --hard나 28장의 reflog로도 복구할 수 없다. 실행 전 정말로 이 변경을 버려도 되는지 반드시 확인해야 한다.
--staged 여부를 헷갈리면 의도와 다른 영역이 되돌아간다: “스테이징까지 했는데 취소하고 싶다"면서 --staged 없이 git restore <file>만 실행하면, 스테이징 영역이 아니라 작업 트리만 되돌아가고 스테이징된 내용은 그대로 남는다. 04장의 3단계 모델을 다시 떠올리며 어느 영역을 되돌리고 싶은지 먼저 명확히 하는 편이 실수를 줄인다.
오래된 자료의 checkout -- <file> 표기를 무조건 최신 방식으로 바꿔 쓸 필요는 없다: 두 표기는 동일하게 동작하므로, 기존 스크립트나 문서에 있는 checkout -- 표기를 굳이 찾아 바꿀 필요는 없다. 다만 새로 작성하는 스크립트나 문서라면 의도가 더 명확한 restore를 쓰는 편이 나중에 읽는 사람의 혼란을 줄인다.
![Featured image of post [Git] 25. git restore와 git checkout -- <file>](/post/git/git-restore-checkout-file-discard-changes/wordcloud_hu_643ce992e815536e.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] 26. git cherry-pick](/post/git/git-cherry-pick-command/wordcloud_hu_2a527478bbed902.webp)
![[Git] 27. git rebase -i — 인터랙티브 리베이스](/post/git/git-rebase-interactive-mode/wordcloud_hu_31933fe2155d80d4.webp)
![[Git] 30. git clean — 미추적 파일 정리](/post/git/git-clean-command-remove-untracked-files/wordcloud_hu_73da61b3df7aabd.webp)
![[Git] 36. Packfile과 git gc](/post/git/packfile-and-git-gc/wordcloud_hu_b3276dfd3f3cb2be.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] 12. git switch/checkout — 브랜치 전환](/post/git/git-switch-checkout-branch-transition/wordcloud_hu_cfa8ddb8839c8503.webp)