협업에서 각자 작업을 하다가 협업자의 작업을 머지해야하는 상황이 생길 수 있다. 그런데 작업 중인 내용이 아직 커밋을 하기에는 어정쩡한 상태라면 어떻게 해야할까? 이럴 때 유용하게 사용되는 것이 바로 git의 stash 명령어다.


1. git stash

: 작업 중 다른 요청으로 잠시 브랜치를 변경해야 할 경우, 커밋하지 않고 이동했다가 나중에 다시 돌아와서 작업을 하고 싶을 때 사용하는 명령어.

  • 사용하면 워킹 디렉토리에서 수정한 파일들만 저장한다.
  • 즉, 파일을 커밋하고 수정중인 파일이거나 커밋 전의 파일들을 잠시 보관해둘 장소가 필요할 때 stash에 쌓아 두는 것.


stash란?

  • Modified 상태이면서 Tracked 상태인 파일과 Staging area에 있는 파일들을 보관해두는 장소를 일컫는다.
  • Modified 상태의 파일은 커밋하지 않고 다른 브랜치로 이동하면 수정 내역이 사라진다.


2. 하던 일 stash하기

(1) 예제 준비

  1. [stash-practice] 파일을 생성하고 git init 해준다.
  2. 이어 git add ., git commit -m "Initial commit"으로 커밋을 생성한다.
  3. 해당 폴더 안에 stash1.txt 와 stash2.txt 파일을 각각 생성하고 내용입력 후
  4. 파일 생성한 것에 대해 커밋을 해주고 두 파일 모두를 수정한다.
  5. 수정 후 stash1.txt만 add하면 예제 준비 완료.
$ git status
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   index.html

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   lib/simplegit.rb


(2) 브랜치 변경

브랜치를 변경하기 전에 git stash 또는 git stash save를 치면 스택에 새로운 stash가 만들어지고, 수정중이었던 파일과 staging area에 있는 파일들이 이동한다.

iterm2
Saved working directory and index state WIP on master: 35a31d6 stash1.txt와 stash2.txt 파일 생성
HEAD is now at 35a31d6 stash1.txt와 stash2.txt 파일 생성

$ git status - 워킹 디렉토리가 깨끗해짐.
On branch master
nothing to commit, working tree clean

로그를 확인해보면 지금까지 작업중인 수정파일들이 stash에서 참조되고 있다는 것을 확인할 수 있다.

$ git log
*   5e4291c (refs/stash) WIP on master: 35a31d6 stash1.txt와 stash2.txt 파일 생성
|\
| * 818a10d index on master: 35a31d6 stash1.txt와 stash2.txt 파일 생성
|/
* 35a31d6 (HEAD -> master) stash1.txt와 stash2.txt 파일 생성


(3) stash 파일 확인 - git stash list

: stash된 파일(들)을 확인하는 명령어

[email protected]{0}: WIP on master: 35a31d6 stash1.txt와 stash2.txt 파일 생성


(4) stash 다시 적용 - git stash apply

: stash로 넣어놨던 파일들을 다시 워킹디렉토리에 불러오는 명령어

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   stash1.txt
	modified:   stash2.txt

no changes added to commit (use "git add" and/or "git commit -a")

해당 명령어 적용 후 stash를 참조하던 파일들이 다시 워킹디렉토리로 옮겨진 것을 확인할 수 있다.


+ git stash apply [email protected]{n}

: stash된 파일들의 목록에서 부여된 번호를 위 명령어의 n에 쓰면 그 번호의 stash만 워킹디렉토리로 불러오게 할 수 있다.

git stash apply [email protected]{0} -> 역시 위와 같은 결과를 보여준다.


+ git stash pop

: stash를 적용하고 나서 바로 스택에서 제거해준다.


3. stash는 까다롭지 않다. 단…

git stash apply --index

  • git stash를 적용할 때 staged였던 파일을 다시 staged 상태로 불러오지 않는다.
    • git stash apply --index 옵션을 줘서 staged 상태까지 적용한다. 그래야 원래 상태로 되돌아올 수 있다.
  • 물론! 다른 브랜치로 이동해서 stash를 복원할 수도 있다.
  • 다시 git stash apply할 디렉토리가 깨끗할 필요도 없다.
  • 수정하고 커밋하지 않은 파일이 있어도 stash가 적용가능하다.
  • 충돌이 있다면 알려준다.


stash 제거 1 - git stash drop

  • apply 는 단순히 stash를 적용해주는 명령어이므로 stash는 아직 스택에 남아있다.
  • git stash drop명령어로 해당 stash를 제거한다.
Dropped refs/[email protected]{0} (f1588c7b4eb171fe448da1fe0c0d9bb73156793a)


stash 제거 2 - git stash pop

  • stash를 적용하고 나서 바로 스택에서 제거해준다.
  • apply와 drop을 합친 것과 같다!


4. stash를 만드는 새로운 방법

stash를 만드는 방법은 여러가지가 있다.

(1) 이미 staging area에 들어있는 파일을 stash하지 않고 싶을 때

git stash save --keep-index

수정한 파일들 중 몇몇 파일만 커밋하고 나머지는 나중에 처리하고 싶을 때 사용하는 명령어

$ git stash save --keep-index
Saved working directory and index state WIP on master: 35a31d6 stash1.txt와 stash2.txt 파일 생성
HEAD is now at 35a31d6 stash1.txt와 stash2.txt 파일 생성
<git status -s>
M  stash1.txt
?? .gitignore


(2) 추적하지 않는 파일과 추적중인 파일을 같이 stash할 때

git stash --include-untracked or git stash -u

  • 기본적으로 stash는 추적 중인 파일(tracked files)만 저장한다.
  • 추적중이지 않은 파일은 stash명령어를 사용할 때 --include-untracked or -u를 붙여서 사용한다.


(3) 저장할 것과 저장하지 않을 것을 고르고 싶을 때

git stash --patch

  • --patch 옵션을 붙이면 모든 사항을 저장하지 않고 변경 데이터 중 저장할 것을 지정할 수 있게 해준다.
  • e : 내용을 edit할 수 있다.


5. stash를 이용한 브랜치 만들기

stash를 저장하고 그 브랜치에서 한동안 새로운 작업을 하다가 다시 stash를 불러오면 충돌이 일어날 수도 있다. 이럴 때 stash를 쉽게 다시 테스트하는 명령어 git stash branch를 사용한다.

  • stash할 당시의 커밋을 checkout한 후 새로운 브랜치를 만들고 여기에 적용. 그 이후에는 stash를 삭제해버린다.



Julia Hwang

디발자를 꿈꾸는 웹개발자의 블로그입니다.