git stash 사용법
Git으로 작업을 하다 보면 현재 브랜치에서 뭔가를 한창 수정하고 있는데 급하게 다른 브랜치로 전환해야 하는 상황이 생기곤 합니다. 아직 완성되지 않은 코드를 커밋하자니 찜찜하고 그렇다고 변경사항을 날리기엔 아까운데요.
바로 이럴 때 git stash가 유용합니다.
git stash는 현재 작업 중인 변경사항을 임시로 저장해두고 나중에 다시 꺼내 쓸 수 있게 해주는 명령어인데요.
이번 글에서는 기본 사용법부터 실전에서 유용한 고급 활용법까지 함께 알아보겠습니다.
기본 사용법
git stash의 가장 기본적인 사용법은 간단합니다.
$ git stash
이 명령어를 실행하면 작업 디렉토리(working directory)와 스테이징 영역(staging area)에 있는 변경사항이 별도의 공간에 임시 저장됩니다. 그리고 작업 디렉토리는 마지막 커밋 상태로 깨끗하게 돌아가죠.
실제로 사용해볼까요?
$ git status
On branch feature/user-auth
Changes not staged for commit:
modified: src/api/auth.js
modified: src/components/Login.jsx
$ git stash
Saved working directory and index state WIP on feature/user-auth: a1b2c3d 이전 커밋 메시지
$ git status
On branch feature/user-auth
nothing to commit, working tree clean
작업 디렉토리가 깨끗해졌으니 이제 마음 편히 다른 브랜치로 전환할 수 있겠죠?
$ git switch main
# 긴급한 작업 처리 후...
$ git switch feature/user-auth
다시 원래 브랜치로 돌아와서 저장해둔 변경사항을 꺼내려면 git stash pop을 사용합니다.
$ git stash pop
On branch feature/user-auth
Changes not staged for commit:
modified: src/api/auth.js
modified: src/components/Login.jsx
Dropped refs/stash@{0} (a1b2c3d...)
pop은 stash에서 변경사항을 꺼내면서 stash 항목을 삭제합니다.
변경사항은 꺼내되 stash 항목은 그대로 남겨두고 싶다면 git stash apply를 쓰면 됩니다.
$ git stash apply
apply는 pop과 달리 stash 항목을 삭제하지 않기 때문에 같은 변경사항을 여러 브랜치에 적용해보고 싶을 때 쓸 수 있습니다.
메시지 추가
git stash를 여러 번 사용하다 보면 각 stash가 어떤 작업이었는지 구분하기 어려워집니다.
이럴 때는 -m 옵션으로 설명 메시지를 남겨두면 나중에 훨씬 편합니다.
$ git stash -m "로그인 폼 유효성 검사 작업 중"
Saved working directory and index state On feature/user-auth: 로그인 폼 유효성 검사 작업 중
메시지를 남겨두면 stash 목록을 확인할 때 어떤 작업이었는지 한눈에 알 수 있습니다.
stash 목록 확인
저장된 stash 항목은 git stash list로 확인할 수 있습니다.
$ git stash list
stash@{0}: On feature/user-auth: 로그인 폼 유효성 검사 작업 중
stash@{1}: WIP on main: b2c3d4e API 리팩토링
stash@{2}: WIP on feature/dashboard: c3d4e5f 차트 컴포넌트 수정
stash는 스택(stack) 구조로 관리되는데요.
가장 최근에 저장한 것이 stash@{0}이고 오래된 것일수록 번호가 큽니다.
git stash pop이나 git stash apply를 인자 없이 실행하면 가장 최근 stash인 stash@{0}이 적용됩니다.
특정 stash를 골라서 적용하고 싶다면 인덱스를 지정하면 됩니다.
# 두 번째 stash 적용 후 삭제
$ git stash pop stash@{1}
# 세 번째 stash 적용 (삭제 안 함)
$ git stash apply stash@{2}
stash 내용 확인
stash를 적용하기 전에 어떤 변경사항이 들어있는지 미리 확인하고 싶을 때가 있죠?
git stash show 명령어로 stash 내용을 살펴볼 수 있습니다.
$ git stash show
src/api/auth.js | 12 ++++++------
src/components/Login.jsx | 8 ++++----
2 files changed, 10 insertions(+), 10 deletions(-)
변경된 파일 목록과 수정 분량이 간략하게 표시됩니다.
git diff의 --stat 출력과 같은 형식이죠.
구체적인 diff를 보고 싶다면 -p 옵션을 추가합니다.
$ git stash show -p
특정 stash의 내용을 확인하려면 마찬가지로 인덱스를 지정하면 됩니다.
$ git stash show -p stash@{1}
추적되지 않는 파일 포함
기본적으로 git stash는 Git이 이미 추적(tracking)하고 있는 파일의 변경사항만 저장합니다.
새로 만든 파일처럼 아직 git add를 한 번도 하지 않은 파일은 stash에 포함되지 않는데요.
$ git status
On branch main
Changes not staged for commit:
modified: src/app.js
Untracked files:
src/utils/helpers.js
$ git stash
Saved working directory and index state WIP on main: a1b2c3d ...
$ git status
On branch main
Untracked files:
src/utils/helpers.js
src/utils/helpers.js가 stash에 포함되지 않고 남아있는 것을 볼 수 있습니다.
이런 경우 -u 또는 --include-untracked 옵션을 사용하면 추적되지 않는 파일까지 함께 stash에 저장할 수 있습니다.
$ git stash -u
git add명령어의 자세한 사용법은 git add 사용법에서 다루고 있으니 참고 바랍니다.
특정 파일만 stash
변경된 파일이 여러 개인데 그중 일부만 stash하고 싶을 때도 있겠죠?
이럴 때는 -- 뒤에 파일 경로를 지정하면 됩니다.
$ git stash -- src/api/auth.js
여러 파일을 지정할 수도 있습니다.
$ git stash -- src/api/auth.js src/components/Login.jsx
좀 더 세밀하게 변경사항을 나눠서 stash하고 싶다면 -p 또는 --patch 옵션을 사용해볼 수 있습니다.
각 변경 사항(hunk)을 하나씩 보여주면서 stash에 포함할지 물어보거든요.
$ git stash -p
diff --git a/src/api/auth.js b/src/api/auth.js
--- a/src/api/auth.js
+++ b/src/api/auth.js
@@ -10,6 +10,8 @@
Stash this hunk [y,n,q,a,d,/,e,?]?
y를 누르면 해당 변경을 stash에 포함하고 n을 누르면 건너뜁니다.
stash 삭제
더 이상 필요 없는 stash 항목은 git stash drop으로 삭제할 수 있습니다.
# 가장 최근 stash 삭제
$ git stash drop
# 특정 stash 삭제
$ git stash drop stash@{2}
모든 stash를 한꺼번에 삭제하려면 git stash clear를 사용합니다.
$ git stash clear
clear는 되돌릴 수 없으니 신중하게 사용하시길 바랍니다.
stash에서 브랜치 생성
stash에 저장해둔 변경사항을 새로운 브랜치에서 작업하고 싶은 경우가 있습니다. stash를 적용하려는데 그 사이에 같은 파일이 수정되어서 충돌이 발생한다면 새 브랜치를 만드는 편이 깔끔하죠.
git stash branch 명령어는 stash를 저장했던 시점의 커밋에서 새 브랜치를 만들고 거기에 stash를 적용한 뒤 stash 항목을 삭제해줍니다.
$ git stash branch feature/login-validation
Switched to a new branch 'feature/login-validation'
On branch feature/login-validation
Changes not staged for commit:
modified: src/api/auth.js
modified: src/components/Login.jsx
Dropped refs/stash@{0} (a1b2c3d...)
stash를 저장한 시점의 커밋으로 브랜치가 만들어지기 때문에 충돌 없이 변경사항이 깔끔하게 적용됩니다.
실전 활용: 브랜치 전환 시 stash 활용
git stash가 가장 많이 쓰이는 상황은 역시 브랜치를 전환할 때입니다.
커밋하지 않은 변경사항이 있는 상태에서 다른 브랜치로 전환하려고 하면 Git이 경고를 표시하죠.
$ git switch main
error: Your local changes to the following files would be overwritten by switch:
src/app.js
Please commit your changes or stash them before you switch branches.
이때 git stash를 활용하면 작업 흐름이 자연스러워집니다.
# 1. 현재 작업 저장
$ git stash -m "로그인 페이지 레이아웃 작업"
# 2. 다른 브랜치로 전환해서 작업
$ git switch main
# ... 급한 작업 처리 ...
# 3. 원래 브랜치로 복귀
$ git switch feature/login
# 4. 저장한 작업 복원
$ git stash pop
브랜치 전환에 대해서는 git switch 사용법과 git checkout 사용법에서 자세히 다루고 있으니 참고 바랍니다.
실전 활용: 실험적인 코드 테스트
코드를 수정하다가 “이건 좀 다른 방식으로 해볼까?”라는 생각이 들 때도 git stash가 유용합니다.
현재 변경사항을 stash에 넣어두고 다른 접근 방식을 시도해본 뒤 마음에 안 들면 원래 코드를 복원하면 되거든요.
# 현재 작업 저장
$ git stash -m "접근 방식 A"
# 다른 접근 방식 시도
# ... 코드 수정 ...
# 새로운 접근 방식이 마음에 안 들면 되돌리기
$ git restore .
# 원래 작업 복원
$ git stash pop
stash 충돌 해결
git stash pop이나 git stash apply를 실행했을 때 충돌이 발생할 수 있습니다.
stash를 저장한 이후에 같은 파일의 같은 부분이 수정되었다면 Git이 자동 병합에 실패하기 때문인데요.
$ git stash pop
Auto-merging src/api/auth.js
CONFLICT (content): Merge conflict in src/api/auth.js
The stash entry is kept in case you need it again.
충돌이 발생하면 pop을 사용했더라도 stash 항목이 자동으로 삭제되지 않습니다.
충돌을 수동으로 해결한 후 직접 stash를 삭제해야 합니다.
# 1. 충돌 파일 열어서 수동으로 해결
$ vim src/api/auth.js
# 2. 해결된 파일 스테이징
$ git add src/api/auth.js
# 3. stash 항목 수동 삭제
$ git stash drop
충돌이 너무 복잡하다면 앞서 소개한 git stash branch로 새 브랜치를 만들어서 해결하는 것도 방법입니다.
git worktree와 비교
git stash는 브랜치 전환 시 변경사항을 임시 저장하는 데 유용하지만 브랜치를 자주 오갈수록 stash/pop을 반복하는 과정이 번거로워질 수 있습니다.
stash를 여러 개 쌓아두다 보면 관리가 복잡해지기도 하고요.
이런 상황에서는 git worktree가 좋은 대안이 될 수 있습니다.
git worktree는 하나의 저장소에 여러 작업 디렉토리를 만들어서 각각 다른 브랜치를 체크아웃할 수 있게 해주는데요.
브랜치마다 별도의 디렉토리가 있으니 stash 없이도 터미널 탭만 바꾸면 다른 브랜치 작업이 가능합니다.
간단히 비교하면 다음과 같습니다.
| 상황 | git stash | git worktree |
|---|---|---|
| 브랜치 전환 빈도가 낮을 때 | 적합 | 과할 수 있음 |
| 브랜치를 자주 오갈 때 | 번거로움 | 적합 |
| 동시에 여러 브랜치 작업 | 불가 | 가능 |
| 디스크 공간 | 추가 사용 없음 | 워크트리마다 공간 필요 |
| 설정 난이도 | 낮음 | 약간 높음 |
두 가지를 적절히 조합하면 더 유연한 워크플로우를 만들 수 있습니다.
잠깐 브랜치를 전환하는 것이라면 git stash로 빠르게 처리하고, 장시간 병렬 작업이 필요하다면 git worktree를 활용하는 식이죠.
마치며
git stash는 일상적인 개발 워크플로우에서 정말 자주 쓰이는 명령어입니다.
핵심 명령어를 정리하면 다음과 같습니다.
git stash: 변경사항 임시 저장git stash pop: 저장한 변경사항 꺼내기 (stash 삭제)git stash apply: 저장한 변경사항 적용 (stash 유지)git stash list: 저장된 stash 목록 확인git stash show -p: stash 내용 미리보기git stash drop: stash 삭제git stash branch: stash에서 새 브랜치 생성
처음에는 git stash와 git stash pop만 알아도 충분하지만 -m 옵션으로 메시지를 남기는 습관을 들이면 나중에 stash를 관리하기가 훨씬 수월해집니다.
더 자세한 내용은 Git 공식 문서를 참고하세요.
This work is licensed under
CC BY 4.0