Git Stash 개념
어떤 작업 내용을 개발자가 커밋했다.
이후 다른 업무로 인해 코드를 작성하다가 다른 브랜치로 이동하고 싶어졌다.
바로 git checkout과 switch를 쓰면 다른 브랜치로 이동할 수 있을까?
아쉽게도 그렇지 않다. 커밋하지 않은 코드가 남아있으므로 다른 브랜치로 이동이 불가능하다.
그럼 어떻게 코드를 작성하다가 다른 브랜치로 편하게 넘어갈 수 있을까?
이런 상황에서 스태시(stash)기능을 사용한다. stash를 번역기에 돌려보니 은닉처라고 나온다.
깃은 커밋되지 않은 변경 내용이 남아 있을 때, 현재 작업을 임시로 저장할 수 있는 스태시 기능을 제공한다.
스태시는 현재 워킹 디렉터리 내역을 별도의 스택 영역에 저장해 브랜치가 이동할 때 작업 중인 내용으로 워킹 디렉터리가 충돌하는 것을 방지한다.
스태시 명령을 실행하면 현재 작업중인 내용은 별도의 스택에 저장되고, 수정 전 마지막 커밋 상태로 돌아간다.
즉, 이전 커밋 후 작업하지 않은 상태의 워킹 디렉터리가 된다.
Git Stash 실습
스태시를 하려면 stash 명령어를 실행해야 한다.
한번 실습을 진행해보겠다.
먼저 git init으로 실습을 진행할 디렉토리를 만든다.
그리고 아래 명령어를 따라 커밋을 하나 해보자.
mkdir stash
cd stash
vi hello.txt
//a를 누르고 Hello, World!! 후 ESC를 누르고 :wq Enter를 누른다.
git add .
git commit -m "first commit"
여기서 git status를 입력하면 커밋할 사항이 없고, 작업 폴더는 깨끗하다고 나온다.
작업 도중 새로운 변경 요청
이제 새로운 작업을 진행하게 브랜치를 하나 만든다.
git branch feature
git switch feature
이제 작성한 hello.txt 내용을 바꾸고 커밋을 하자.
vi hello.txt
Hello, World!!!!!!!!!!!!!!
git add .
git commit -m "feature commit"
그럼 이제 2개의 커밋이 생긴다.
그럼 이제 마지막으로 hello.txt를 수정해보자
vi hello.txt
Hello, Awesome World!!!!!!!!!!!!!!
git status
git status 명령어를 치면 hello.txt가 수정되었다고 나온다.
새 코드 작성 중 기존 코드를 수정
기존에 작업한 코드에서 버그가 발생했다고 가정하자.
우리는 작업 중인 브랜치는 멈추고, 다른 브랜치를 수정해야 한다.
git switch main(or master) 이라는 명령어를 입력하면 아래와 같은 메시지가 출력된다.
현재 워킹 디렉토리의 작업이 다른 브랜치의 워킹 디렉터리에 영향을 줄 수 있으므로 아래와 같은 메시지가 나온다.
이런 상황에서 git stash가 적절하다.
스태시의 임시 스택 영역에 작업 중인 코드 저장
스태시 명령어는 수정 중인 내역을 커밋하지 않고도 브랜치를 이동할 수 있게 워킹 디렉터리를 깨끗하게 청소한다.
스태시는 영구적인 커밋 기록 대신 현재 작업들을 임시 스택 영역에 저장한다.
- git stash -> 제일 기본
- git stash save -> 스탯시 여러 개를 생성할 때 유용. 스태시는 스택 구조로 여러 번 실행하여 저장할 수 있다.
- git stash save "메시지 내용" -> 스태시를 구별할 수 있도록 메시지도 추가 가능
이제 git stash 명령어를 사용해보자.
git statsh
그럼 아래와 같은 화면을 확인할 수 있고, git status를 입력하면 클린하다고 메시지가 뜬다.
그럼 이제 git switch main(or master)가 정상적으로 성공한다.
임시 저장 영역의 스택 목록
스태시의 저장 영역은 스택(선입후출) 자료구조다.
스태시에 저장된 스택은 list 옵션을 사용해 확인할 수 있다.
git stash list
깃은 스태시된 객체들을 .git/refs/stash에 저장한다.
git stash show -p 명령어를 사용해 방금 전의 스태시와 현재 워킹 디렉터리 간 차이를 확인할 수도 있다.
임시 저장한 스태시 불러오기
이제 버그를 수정한다고 가정하고 hello.txt를 수정하고 커밋해보자.
vi hello.txt
//아무 내용이나 추가하고 수정
git add .
git commit -m "bug fix"
이제 원래의 feature 브랜치로 돌아가 stash를 불러오자.
git switch feature
git stash pop
git stash pop을 하면 워킹 디렉토리로 스태시한 작업들이 돌아온다.
또한 git stash list 명령어를 입력하면 아무것도 보이지 않는다. 즉 정상적으로 스태시가 복원되면 저장된 스택은 삭제되는 것이다.
스태시 복원으로 충돌
스태시를 복원할 때는 워킹 디렉터리의 상태가 깨끗해야 한다.
스택에 저장된 스태시 내용이 다시 워킹 디렉터리로 복구될 때, 수정된 작업 내용과 현재 워킹 디렉터리를 병합하기 때문이다.
복구되는 워킹 디렉터리가 깨끗하지 않다면 병합 과정에서 충돌이 발생할 수 있다.
스태시를 복원할 때 충돌이 생기면 직접 문제를 해결해야 한다.
복원하는 도중 충돌이 생기면 스테시는 스택에 저장된 내용을 자동으로 삭제하지 않는다.
직접 충돌을 해결한 후 스태시 목록을 수동으로 삭제해야 한다.
스태시 충돌이 예상되면 스태시용 브랜치 하나를 생성해서 작업하도록 하자.
아래 명령어는 스태시 스택에 저장된 내용으로 새로운 브랜치를 동시에 생성하는 명령어다.
git stash branch 브랜치이름
스태시로 이전 내용을 복원했으며, 아직 커밋을 수행하지 않았으므로 작업 중인 내용은 워킹 디렉터리에 남아있다.
이렇게 브랜치를 파고 병합을 통해 충돌을 해결하면 되는 듯..?
스태시 복사
스태시 스택에 저장된 항목들은 어느 브랜치에서나 복원이 가능하다.
apply 옵션은 스택에 저장된 항목을 불러와 현재 브랜치로 복원한다.
스태시 복원은 pop, apply 명령어 2개를 제공한다.
- pop -> 스택 내용을 복원한 후 스택 목록에서 자동으로 삭제한다.
- apply -> 스택 목록을 읽은후 자동으로 삭제하지 않기 때문에 반복적으로 스택에서 스태시 내용을 읽어올 수 있다.
참고로 스택에 임시 작업 내용이 여러개 저장되었을 때는 stash@{번호} 형태로 출력된다.
apply 명령어는 pop과 달리 마지막 작업 내용이 아니라, 스택 목록의 중간 작업을 지정하여 적용할 수 있다.
git stash apply stash@{2}
스태시 삭제
충돌이 발생하거나 apply 명령어로 워킹 디렉터리를 복구할 때는 스택에서 자동으로 삭제되지 않는다.
이때는 아래 명령을 실행해야만 스태시 목록에서 삭제된다.
git stash drop
스태시를 너무 많이 만들어 사용하는 것은 좋지 않다. 사용한 스태시는 바로바로 삭제하자.
이상으로 포스팅을 마칩니다. 감사합니다.
참고자료
GIT 교과서(이호진님)
https://product.kyobobook.co.kr/detail/S000001834368
댓글