[Git] Stash로 안전하게 브랜치 바꾸기 (Context Switching 꿀팁)
“잠깐 다른 브랜치 좀 봐줘… 하던 작업은 어떡하지?”
“멀티태스킹이 필수인 풀스택 개발자에게 Stash는 제2의 RAM이다.”
개발에 몰입하고 있는 평화로운 오후 3시.
복잡한 로그인 기능을 개발하느라 feature/login 브랜치의 코드는 엉망이고, 컴파일조차 되지 않는 상태입니다.
그런데 갑자기 매니저(또는 팀장님)가 다급하게 달려옵니다.
“Kyuchani님! 운영 서버 결제 쪽에 버그 터졌어요!
지금 당장 핫픽스(hotfix/urgent) 부탁해요!”
머릿속이 복잡해집니다.
- “지금 커밋하기엔 쓰레기 코드인데…”
- “그렇다고 다 지울 수도 없고…”
- “에라 모르겠다, 브랜치 이동!”
git switch hotfix/urgent
하지만 Git은 단호하게 거절합니다.
error: Your local changes to the following files would be overwritten by checkout:
src/auth/Login.js
Please commit your changes or stash them before you switch branches.
Aborting
이때 우리를 구원해 줄 도구가 바로 Git Stash입니다. 이번 글에서는 Stash를 “깊이 있게” 파헤쳐 봅니다.
1. Git Stash란? (Deep Dive)
stash의 사전적 의미는 “안전한 곳에 숨겨두다” 입니다.
Git에서는 작업 중이던 더러운(?) 코드들을 임시 저장소에 잠시 피신시키고, 작업 디렉토리를 마지막 커밋 상태로 깨끗하게 되돌려주는 기능입니다.
- 상황 정리
- 아직 커밋하고 싶지 않은 상태 (실험 중, 컴파일 에러, WIP 등)
- 그런데 브랜치를 바꿔서 급한 버그를 고쳐야 할 때
- 지금 코드를 어디 한군데 “숨겨 두고” 나중에 다시 꺼내 쓰는 기능이 필요
내부 구조: 스택(Stack)
Stash는 스택(Stack) 자료구조를 사용합니다.
LIFO (Last In, First Out), 즉 가장 나중에 넣은 것이 가장 먼저 나오는 구조입니다.
- 가장 최근에 저장한 Stash:
stash@{0} - 그 직전에 저장한 Stash:
stash@{1} - 가장 오래된 Stash:
stash@{n}
개념적으로는 이렇게 쌓인다고 보면 됩니다.
stash@{0} ← 가장 최근 (맨 위)
stash@{1}
stash@{2}
...
stash@{n} ← 가장 오래된 것 (맨 아래)
2. 작업 임시 저장하기 (stash save)
먼저, 하던 작업을 스택에 안전하게 저장합니다.
# 1. 하던 작업을 스택에 저장 (메시지 없이)
git stash
# 2. (권장) 나중에 알아보기 쉽게 메시지와 함께 저장
git stash save "로그인 기능 개발 중 - API 연동 전"
명령어를 실행하면 작업 디렉토리는 마지막 커밋 상태로 깨끗해집니다.
그리고 방금까지 하던 변경 사항은 stash 스택의 가장 위(stash@{0}) 에 안전하게 올라갑니다.
이제 마음 편하게 브랜치를 바꿔서 급한 Hotfix를 처리할 수 있습니다.
git switch hotfix/urgent
# 버그 수정
git commit -am "fix: 긴급 결제 버그 수정"
git push origin hotfix/urgent
3. 작업 다시 가져오기: pop vs apply
급한 불을 끄고 다시 원래 브랜치(feature/login)로 돌아왔습니다.
이제 아까 숨겨둔 코드를 다시 꺼내야 합니다.
여기서 많은 개발자가 pop과 apply를 헷갈립니다.
| 명령어 | 동작 방식 | Stash 목록 상태 | 비유 |
|---|---|---|---|
git stash pop |
작업 디렉토리에 적용 후, stash에서 삭제 | 해당 항목이 스택에서 사라짐 | 잘라내기 & 붙여넣기 (꺼내면 저장소엔 없음) |
git stash apply |
작업 디렉토리에 적용만 하고, stash는 유지 | 스택에 그대로 남아 있음 | 복사 & 붙여넣기 (혹시 몰라 원본 남겨둠) |
기본 사용 예시
# 가장 최근 작업(stash@{0})을 가져오고, 스택에서 제거
git stash pop
# 특정 시점의 작업을 가져오되, 스택에는 남겨둠
git stash apply stash@{1}
실무 추천
- 확신이 있다면:
git stash pop- “이제 이 작업은 이 브랜치에서만 쓸 거야” 라면 pop으로 깔끔하게 정리
- 충돌이 걱정되거나, 같은 코드를 여러 브랜치에서 테스트해보고 싶다면:
git stash apply- 원본을 스택에 계속 남겨두고, 필요할 때마다 다른 브랜치에서 재사용 가능
4. 묵은 Stash 정리하기: list, drop, clear
Stash를 너무 많이 쌓아두면 나중에 “이게 도대체 뭐였지?” 하는 상황이 옵니다.
목록 확인
# 쌓여있는 Stash 목록 확인
git stash list
예시:
stash@{0}: WIP on feature/login: 로그인 기능 개발 중 - API 연동 전
stash@{1}: WIP on feature/cart: 장바구니 UX 개선
stash@{2}: WIP on hotfix/payment: 결제 실패 버그 수정
특정 Stash 삭제
# 특정 Stash 삭제 (apply 또는 pop 후, 더 이상 필요 없을 때)
git stash drop stash@{1}
모든 Stash 한 번에 삭제 (⚠️ 주의)
# (주의) 모든 Stash를 한 방에 삭제
git stash clear
이 명령은 되돌릴 수 없으니 정말 필요할 때만 사용하세요.
5. 🚀 고급 기술: “내 파일이 왜 저장 안 되지?”
5-1. Untracked 파일까지 저장하기: -u 옵션
기본적으로 git stash는 Git이 추적 중인(Tracked) 파일만 저장합니다.
즉, 방금 새로 생성해서 아직 git add 한 번도 안 한 파일(Untracked)은 stash를 해도 작업 공간에 그대로 남습니다.
새로 만든 파일까지 몽땅 숨기고 싶다면 -u (또는 --include-untracked) 옵션을 써야 합니다.
# 새로 만든 파일(Untracked)까지 모두 포함해서 저장
git stash -u
# 메시지까지 함께 남기고 싶다면
git stash save -u "로그인 화면 리팩토링 중 - 신규 컴포넌트 포함"
5-2. 부분 스태싱(Partial Stashing): -p 옵션
작업 내용 중 일부만 숨기고 싶을 때가 있습니다.
- 예:
config파일 변경은 남겨두고 - 소스 코드 변경만 Stash에 숨기고 싶을 때 등
이럴 때는 대화형 모드로 변경 사항(Hunk)마다 저장 여부를 물어보는 -p 옵션을 사용합니다.
# 변경 사항(hunk)마다 저장할지 물어봄 (y/n)
git stash -p
실행하면 각 변경 블록마다 stash 할까요? (y/n) 식으로 물어보게 되고,
원하는 부분만 골라서 Stash에 넣을 수 있습니다.
6. 실무에서의 Stash 활용 흐름 정리
급한 요청이 들어왔을 때, 실무에서 자주 쓰는 안전한 패턴은 다음과 같습니다.
- 하던 작업 임시 저장
git stash save "로그인 기능 개발 중 - API 연동 전" # 새 파일까지 포함하고 싶다면 git stash save -u "로그인 기능 개발 중 - API 연동 전" - 브랜치 이동 후 버그 수정
git switch hotfix/urgent # 버그 수정 git commit -am "fix: 긴급 결제 버그 수정" git push origin hotfix/urgent - 원래 작업으로 복귀
git switch feature/login git stash pop # 또는 apply
이 흐름만 몸에 익으면, 어떤 긴급 상황에서도 당황하지 않고 멀티태스킹을 수행할 수 있습니다.
마무리 및 다음 공부할 내용 예고
Stash는 개발자의 Context Switching(문맥 전환) 비용을 획기적으로 줄여주는 도구입니다.
- 급한 요청이 오면? 👉
git stash save "작업명" - 브랜치 이동해서 버그 수정 👉
git commit&git push - 다시 돌아와서 👉
git stash pop또는git stash apply
다음 .gitignore에 파일을 추가했는데도 자꾸 Git이 추적하려고 할 때
git rm --cached와 캐시(Cache) 초기화로 해결하는 방법을 정리해보겠습니다.
댓글남기기