Git 재활 훈련 4일차 - git stash

0

Git

목록 보기
4/14

git stash

stash는 '안전한 곳에 넣어두다'라는 의미를 가진다. 즉, code를 안전한 곳에 넣어두겠다는 것이다.

우리가 A라는 branch에서 개발을 진행하고 있다고 하자. 그 와중에 B라는 branch에서 특정 부분을 수정해달라는 요청을 받았다고 하자. 이는 일반적으로 A branch의 변경 사항들을 commit한 후에 B branch로 가는데, 아직 A branch에서의 작업이 안 끝났다고 하자. 따라서, B branch로 가기위해서 commit을 만들기는 모호하고, 그렇다고 commit을 하지 않으면 branch간 이동이 안되므로 난감한 상황에 걸릴 수 있다.

이 때 사용하는 것이 바로 git stash이다. git stash를 사용하면 commit은 하지 않고 A branch의 code 내용들을 안전하게 저장한 다음, B branch로 갈 수 있다. 이는 필수적인 기능은 아니지만, 알고있으면 굉장히 큰 도움이 된다.

다음의 두 경우를 알아보도록 하자.

먼저 첫번째는 '충돌이 안나고 branch이동이 가능한 경우'이다. 이 경우를 test해보기 위해서 다음과 같이 환경을 설정해보도록 하자

mkdir ./gitstash
cd ./gitstash
git init

환경 설정이 끝났다면, file을 하나 만들어보도록 하자.

echo -n "html css javascript" >> ./html.txt 

cat ./html.txt
html css javascript

이제 commit을 해보도록 하자.

git add ./html.txt
git commit -m "add html.txt"

다음으로 ts branch를 만들고, html.txt 파일을 수정하도록 하자.

git switch -c ts
echo -n " typescript" >> ./html.txt 

cat ./html.txt 
html css javascript typescript

성공한 것을 볼 수 있다. 이제 git add, git commit을 하지 않고, master branch로 다시 넘어간다고 하자. 그럼 ts branch에 있던 working directory file들이 어떻게 되는 지 보도록 하자.

git switch master

cat ./html.txt 
html css javascript typescript

놀랍게도 master branch로 이동했는데 typescript가 남아있다. 이는 다른 branch에 있는 working directory가 이동하는 branch와 충돌하지 않으면 그대로 있다는 것을 알려준다.

master branch에 html.txt를 다음과 같이 수정하도록 하자.

  • html.txt
html css javascript php

commit을 해주도록 하자.

git add ./html.txt
git commit -m "update html.txt"

다시 ts brach로 돌아와서 html.txt를 다음과 같이 바꿔보도록 하자.

git switch ts
  • html.txt
html css typescript

javascripttypescript로 변경하였다. 이 상태로 commit없이 master branch로 이동해보도록 하자.

git switch master 
error: Your local changes to the following files would be overwritten by checkout:
        html.txt
Please commit your changes or stash them before you switch branches.
Aborting

다음과 같이 실패한다. 이것은 ts branch에 있는 working directory가 master의 commit 내용과 충돌하기 때문에 발생하는 문제이다.

log를 잘보면 Please commit your changes or stash라는 말이 있다. commit을 하던지 stash를 하라는 말이다.

일반적으로 대부분 commit을 하지만, 완성도 안된 code를 가지고 commit을 하기에는 무리가 있으므로, 이 경우 잠시 data를 보관하는 stash를 사용하는 것이다. 이것이 git stash를 사용하는 가장 큰 이유이다.

stashing이란

git stash는 commit하지 않은 변경사항들을 임시 저장하도록 해주고 불필요한 commit으로 이력이 더러워지지 않도록 해준다. 즉, 아직 완성되지 않았거나 commit할 준비가 되지 않은 것에 대해서 git stash를 하는 것이다.

git stash

git stash를 사용하면 commit하지 않은 모든 변경사항, stage area에 있는 변경 사항을 모두 stash한다. 즉, 변경사항을 기억했다가 working directory의 변경 사항을 되돌리는 것이다.

그리고 다시 되돌리때는 git stash pop을 사용하면 된다.

git stash pop

git stash를 사용하면 다음과 같이 동작한다고 생각하면 된다.

branch: bugfix

---Working Directory---   ---Staging Area---   ---Repository---
|   temp.html         |   |   index.html   |   | 0026...      |
|   temp.css          |   |   index.css    |   | bb43...      |
-----------------------   ------------------   ----------------

bugfix라는 branch에서 master branch로 가기 위해, 변경 사항들을 임시 저장하는 git stash를 사용하면 다음과 같이 된다.

branch: bugfix

---Working Directory---   ---Staging Area---   ---Repository---
|                     |   |                |   | 0026...      |
|                     |   |                |   | bb43...      |
-----------------------   ------------------   ----------------

-----------The Stash----------
|   temp.html , index.html   |
|   temp.css , index.css     |
------------------------------

working directory, staging area에 있는 data들이 모두 stash로 임시 보관되는 것이다.

이 다음 master branch로 가서 작업을 한다음, 끝나면 bugfix branch로 가서 git stash pop을 해주면 된다.

branch: bugfix

---Working Directory---   ---Staging Area---   ---Repository---
|   temp.html         |   |   index.html   |   | 0026...      |
|   temp.css          |   |   index.css    |   | bb43...      |
-----------------------   ------------------   ----------------

-----------The Stash----------
|                            |
|                            |
------------------------------

다시 원래의 영역으로 file들이 돌아간다.

git stash 써보기

이제 ts branch에서 git stash를 사용해보도록 하자.

git stash
Saved working directory and index state WIP on ts: 5757ff1 add html.txt

성공적으로 stashing되었다. 다음으로 master branch로 넘어가보도록 하자.

git switch master 
Switched to branch 'master'

문제없이 master branch로 이동되었고, html 파일도 다음과 같이 원래의 master branch 값이다.

  • html.txt
html css javascript php

다시 ts branch로 돌아가서 html.txt를 살펴보도록 하자.

git switch ts

cat ./html.txt 
html css javascript

재밌게도, 이전에 html.txt를 수정했던 내용들이 없다. 이는 git stash로 인해서 workding directory, staging area에 있던 data들이 안전하게 보관되어있기 때문이다. 따라서, local에는 data가 남아있지 않아, 이전 commit의 data로 돌아가게 된 것이다.

따라서, 다시 stash된 data를 local로 가져오도록 하자.

git stash pop

On branch ts
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   html.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (54a2e40a53f202ca99b27d61973f38afb5b2a551)```

html.txt 파일이 복구되었는 지 확인해보도록 하자.

cat ./html.txt
html css typescript

복구된 것을 볼 수 있다. 참고로 git stash pop은 stash에서 data를 가져오고, stash안에 있는 data들을 모두 삭제한다.

재밌는 것은 stash 영역은 git stash를 호출한 branch에만 종속적이게 동작하지 않는다. 따라서, ts branch에서 stash한 정보를 master branch에 가서 적용이 가능하다.

stash apply

git stash applygit stash pop과 비슷한데, 단 변동사항들을 stash에서 가져오지만 삭제하진 않는다. 이는 다른 branch에 있던 내용을 stash하여 현재 branch에 적용할 때 좋은 방식이다.

현재 ts branch이므로 ts branch의 변동사항을 stash로 담아두기로 하자.

git stash
Saved working directory and index state WIP on ts: 5757ff1 add html.txt

다음으로 master branch로 가서 html.txt 파일의 내용을 확인해보도록 하자.

git switch master 

cat ./html.txt 
html css javascript php

이제 git stash apply를 사용하여 ts에서의 변동사항을 master에도 적용해보도록 하자.

git stash apply
Auto-merging html.txt
CONFLICT (content): Merge conflict in html.txt

CONFLICT가 발생하는 것을 볼 수 있다. html.txt 파일을 확인해보도록 하자.

cat ./html.txt 
<<<<<<< Updated upstream
html css javascript php
=======
html css typescript
>>>>>>> Stashed changes

어떤 것을 해야할 지, 결정해야한다. 우리의 경우는 stash에 있는 내용을 적용하도록 하자.

  • html.txt
html css typescript

다음으로 commit을 해주도록 하자.

git add ./html.txt
git commit -m "merge ts"

다음으로 ts branch로 넘어가서 html.txt 파일을 보도록 하자.

git switch ts
cat ./html.txt 
html css javascriptg

이전의 내용이 적용된 것을 알 수 있다. stash에 있는 내용을 적용하기 위해서 git stash pop을 사용해보도록 하자. 이전에 사용했던 git stash apply는 stash 영역을 비워두지 않기 때문에, 남아있을 것이다.

git stash pop

On branch ts
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   html.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (dc58f920be02b1fadbaa460d6675665693dc76d5)

성공하였다. 다음으로 html.txt의 내용을 보도록 하자.

cat ./html.txt 
html css typescript

이전 stash 내용이 적용되어있다.

git stash stack

참고로, 여러 번 stashing하여 stack처럼 사용할 수 있다. 즉, 변경 사항을 적용한 순서대로 stack에 적재되어, pop을 할 수 있는 것이다. 단, 이 정도로 git stash를 어렵게 쓰는 사람은 많이 없긴하다.

먼저 현재 ts branch에 있는 html.txt을 확인해보도록 하자.

  • html.txt
html css javascript ruby

현재 ts branch에 있는 html.txtstash에 넣어보도록 하자.

git stash
Saved working directory and index state WIP on ts: 5757ff1 add html.txt

다음으로 html.txt code를 바꿔보도록 하자.

  • html.txt
html css javascript ruby

ruby를 추가한 것을 볼 수 있다. 이 내용을 stash에 넣도록 하자.

git stash

이제 stash에 stack처럼 변동사항들이 쌓였을 것이다.

git stash list
stash@{0}: WIP on ts: 5757ff1 add html.txt
stash@{1}: WIP on ts: 5757ff1 add html.txt

한 번 pop을 하고 html.txt 파일을 열어봐.

git stash pop

at ./html.txt 
html css javascript ruby

가장 최근에 넣은 stash data에 복구된 것을 볼 수 있다.

git stash list
stash@{0}: WIP on ts: 5757ff1 add html.txt

마지막으로 남은 stash를 복구해보도록 하자.

git stash pop
error: Your local changes to the following files would be overwritten by merge:
        html.txt
Please commit your changes or stash them before you merge.
Aborting
The stash entry is kept in case you need it again.

충돌이 발생해서 실패한 것을 알 수 있다.

왜냐하면 현재의 html.txt 정보가 사라질 수 있기 때문이다. 이번 경우는 merge하지 않고, 이전 stash를 drop시켜버리도록 하자.

drop시키는 명령어는 git stash drop을 사용하면 된다.

git stash drop
Dropped refs/stash@{0} (3a3d2189e34021cf7bc326d6ed380af69de41569)

0개의 댓글