07. 스태시(Stash) — 작업을 잠시 치워두기

🎯 이 장의 목표
  • 스태시가 어떤 상황에서 필요한지 이해한다
  • 작업을 임시 저장(stash)하고 다시 꺼내는(pop/apply) 법을 익힌다
  • 스태시 목록 관리·삭제, 복원 시 충돌 해결을 배운다
  • 워킹 디렉터리를 깨끗이 청소하는 git clean을 안다

7.1 스태시가 필요한 순간

이런 상황을 상상해보세요.

feature 브랜치에서 한창 코드를 작성 중인데, 아직 절반밖에 안 끝나 커밋하기엔 애매합니다. 그런데 갑자기 팀장이 "지금 당장 main의 치명적 버그를 고쳐줘!"라고 합니다.

문제는 6장에서 배운 대로, 커밋하지 않은 변경이 있으면 브랜치를 바꿀 때 막힐 수 있다는 것입니다. 그렇다고 어중간한 코드를 커밋하긴 싫습니다.

이때 스태시(Stash)가 구원투수입니다. 작업 중인 변경을 "임시 서랍"에 잠시 넣어두고, 워킹 디렉터리를 깨끗한 상태로 되돌려주는 기능입니다.

🧺 빨래 바구니 비유
손님이 갑자기 와서 거실을 치워야 할 때, 어질러진 물건을 바구니(스태시)에 잠깐 담아 안 보이게 치워둡니다. 손님이 가면 다시 바구니에서 꺼내 원래대로 둡니다. 버리는 게 아니라 잠시 치우는 것입니다.

7.2 스태시의 동작 원리

스태시는 워킹 디렉터리의 변경 + 스테이지의 변경을 한 묶음으로 떠서, 별도의 "스택(stack)" 공간에 쌓아둡니다.

flowchart LR
    W["✏️ 작업 중인 변경"]
    subgraph STACK["🧺 스태시 스택"]
        direction TB
        S0["stash@{0} — 가장 최근"]
        S1["stash@{1}"]
        S2["stash@{2} — 가장 오래된"]
    end
    Clean["🖥️ 워킹 디렉터리<br/>깨끗한 상태로 복원"]
    W -- "git stash" --> S0
    W -.-> Clean
    classDef work fill:#fef3c7,stroke:#d97706,color:#92400e
    classDef stash fill:#dbeafe,stroke:#2563eb,color:#1e40af
    classDef clean fill:#dcfce7,stroke:#16a34a,color:#166534
    class W work
    class S0,S1,S2 stash
    class Clean clean

스택이므로 나중에 넣은 것이 맨 위(stash@{0})에 옵니다.

7.3 작업 임시 저장하기 — git stash

BASH
# 현재 변경 사항을 스태시에 저장
git stash

# 설명(메시지)을 붙여 저장 (권장 - 나중에 알아보기 쉬움)
git stash push -m "로그인 폼 작업 중"
CODE
Saved working directory and index state WIP on feature: a1b2c3d Add feature.txt

이제 git status를 보면 워킹 디렉터리가 깨끗해져, 다른 브랜치로 자유롭게 이동할 수 있습니다.

BASH
git status
CODE
On branch feature
nothing to commit, working tree clean    ← 깨끗해짐!
💡 팁
기본 git stash추적 중인 파일의 변경만 저장합니다. 새 파일(Untracked)도 함께 치우려면 -u 옵션을 씁니다.
```bash
git stash -u # untracked 파일도 포함
git stash -a # ignored 파일까지 전부 포함
```

7.4 스태시 목록 보기 — git stash list

BASH
git stash list
CODE
stash@{0}: On feature: 로그인 폼 작업 중
stash@{1}: WIP on main: 9f8e7d6 Fix typo
  • stash@{0}이 가장 최근 저장본입니다.
  • 메시지를 붙여뒀다면 무엇을 저장했는지 한눈에 보입니다.

스태시 내용을 미리 보려면:

BASH
git stash show stash@{0}          # 요약
git stash show -p stash@{0}       # 변경 내용 전체(diff)

7.5 스태시 꺼내기 — pop vs apply

치워뒀던 작업을 다시 꺼낼 때 두 가지 방법이 있습니다.

git stash pop — 꺼내고 스택에서 제거

BASH
git stash pop                # 가장 최근(stash@{0}) 꺼내고 목록에서 삭제
git stash pop stash@{1}      # 특정 스태시 지정
  • 꺼내면서 스택에서 그 스태시를 제거합니다.
  • "한 번 쓰고 버릴" 일반적인 경우에 사용합니다.

git stash apply — 꺼내되 스택에 남겨두기

BASH
git stash apply              # 적용하되 스택에 그대로 둠
git stash apply stash@{1}
  • 적용 후에도 스태시가 목록에 남습니다.
  • 같은 변경을 여러 브랜치에 적용하고 싶을 때 유용합니다.
💡 팁
언제 무엇을?
  • 보통은 pop (꺼내 쓰고 정리)
  • 여러 곳에 재사용하거나 안전하게 보관하며 적용하고 싶으면 apply 후 나중에 drop

7.6 스태시 복원 시 충돌

스태시를 저장한 뒤 그 파일을 다른 곳에서 또 수정했다면, 꺼낼 때 충돌(conflict)이 날 수 있습니다.

CODE
CONFLICT (content): Merge conflict in login.js

당황하지 마세요. 이것은 "스태시의 변경"과 "현재 코드의 변경"이 같은 부분을 건드려 Git이 자동 합치기를 못 한 것입니다. 파일을 열면 다음과 같은 표시가 있습니다.

CODE
<<<<<<< Updated upstream
현재 코드의 내용
=======
스태시에서 꺼낸 내용
>>>>>>> Stashed changes

해결 방법:

  1. 파일을 열어 <<<<<<<, =======, >>>>>>> 표시를 보고 원하는 코드만 남기고 나머지 표시는 삭제합니다.
  2. 정리한 파일을 git add로 표시합니다.
  3. pop이었다면 충돌 시 스태시가 자동 삭제되지 않으므로, 해결 후 git stash drop으로 정리합니다.
(충돌 해결의 자세한 원리는 [08_병합과충돌.md]에서 깊이 다룹니다. 스태시 충돌도 같은 방식입니다.)

7.7 스태시를 브랜치로 만들기

스태시 내용이 생각보다 커서 별도 브랜치에서 이어가고 싶다면:

BASH
git stash branch new-branch-name stash@{0}

이 명령은 새 브랜치를 만들고, 스태시를 저장했던 시점의 커밋으로 이동한 뒤, 스태시를 적용하고 성공 시 그 스태시를 삭제합니다. 충돌 가능성을 줄이며 깔끔하게 작업을 이어갈 수 있습니다.

7.8 스태시 삭제하기

BASH
# 특정 스태시 하나 삭제
git stash drop stash@{0}

# 모든 스태시 한꺼번에 삭제 (주의!)
git stash clear
⚠️ 흔한 실수
git stash clear는 모든 임시 저장본을 되돌릴 수 없게 삭제합니다. 실행 전 git stash list로 정말 버려도 되는지 확인하세요.

소스트리에서는 좌측 Stashes 항목에서 저장된 스태시 목록을 보고, 우클릭으로 Apply / Pop / Delete를 할 수 있습니다. CLI보다 어떤 스태시가 있는지 한눈에 보기 좋습니다.

7.9 워킹 디렉터리 청소 — git clean

스태시는 "치워서 보관"이지만, git clean추적되지 않는 파일을 아예 삭제합니다. 빌드 산출물이나 임시 파일이 잔뜩 생겼을 때 깨끗이 비웁니다.

BASH
# 무엇이 지워질지 미리보기 (반드시 먼저!)
git clean -n

# 추적 안 되는 파일 삭제
git clean -f

# 폴더까지 삭제
git clean -fd

# .gitignore에 등록된 파일까지 삭제
git clean -fx
옵션의미
-ndry-run, 실제 삭제 없이 목록만 표시
-fforce, 실제 삭제 (기본적으로 -f 없으면 거부)
-d디렉터리도 포함
-x.gitignore된 파일도 포함
⚠️ 흔한 실수
매우 위험: git clean -f는 파일을 휴지통 없이 즉시 영구 삭제합니다. Git이 추적하지 않는 파일이므로 복구도 불가능합니다. 반드시 -n으로 먼저 확인한 뒤 실행하세요. 스태시와 달리 되돌릴 방법이 없습니다.

7.10 실습: 스태시 전체 시나리오

BASH
# === 상황: feature 작업 중 급한 버그 수정 요청 ===

# 1. feature에서 작업 중 (아직 커밋 못 함)
git switch feature
echo "작업중인 코드" > work.js

# 2. 급한 요청 → 작업을 치워둠
git stash push -m "feature 진행중"
git status                       # 깨끗함

# 3. main으로 이동해 버그 수정
git switch main
echo "버그 수정" > fix.js
git add fix.js
git commit -m "Fix urgent bug"
git push

# 4. 다시 feature로 돌아와 작업 재개
git switch feature
git stash list                   # stash@{0} 확인
git stash pop                    # 치워뒀던 작업 복원
ls                               # work.js 다시 나타남!

# 5. 작업 마무리 후 커밋
git add work.js
git commit -m "Finish feature work"

7.11 이 장에서 배운 것 (요약)

  • 스태시 = 커밋하기 애매한 작업을 임시 서랍에 치워두기
  • git stash(저장), -u(새 파일 포함), push -m(메시지)
  • git stash list(목록), show -p(내용 보기)
  • pop(꺼내고 삭제) vs apply(꺼내고 남김)
  • 복원 시 충돌 가능 → 병합 충돌과 같은 방식으로 해결
  • git stash drop/clear로 삭제
  • git clean은 추적 안 된 파일을 영구 삭제(반드시 -n 먼저)

✍️ 확인 문제

  1. 커밋하기 애매한 작업이 있는데 다른 브랜치로 급히 가야 합니다. 어떻게 하나요?
  2. git stash popgit stash apply의 차이는?
  3. git clean을 실행하기 전 반드시 해야 하는 것은?
여기까지가 2부(브랜치와 작업 흐름)입니다. 다음 단계에서는 갈라진 브랜치를 다시 하나로 합치는 병합(Merge)과 충돌 해결, 그리고 리베이스를 배웁니다.