git 다 써보기, (1) stash
커밋하지 않고 변경사항을 저장하는 방법, stash 에 대해 알아본다.
0. why STASH?
git stash는 변경사항을 임시로 저장할 수 있도록 도와주는 기능이다.
git 저장소에서 코드 작업을 하고 있는 상황에서 코드를 수정하던중 커밋을 하지 않은 상태에서 핫픽스 요청이 들어오는 경우,
지식이 없다면 변경사항 전체를 하드 리셋하거나, 저장소를 하나 더 클론해서 받아오고 또는 작업내용을 보조하기 위해 코드 전체를 급하게 커밋하였다.
$ git add .
$ git commit -m'Hotfix 작업을 위한 임시 커밋(작업중)'
hotfix란?
Hotfix는 배포된 버전에 문제가 생기면 문제를 해결하기 위한 전략이다. 별도로 브랜티를 생성하고 버그를 수정한다. Hotfix는 짧은 호흡의 브랜치로 한 가지 작업만을 위해서 생성되고 삭제된다.
혼자서 쓰는 브랜치에 임시 커밋을 해도 큰 문제는 없지만, 나중에 rebase를 하고 정리를 하려면 꽤나 귀찮다고 한다. 또한 공용 브랜치에서 이런식의 커밋을 하는건 더욱이 좋지 않은 방법이다. 이런 상황에서 git stash 명령어로 변경사항을 임시 저장하고, 나중에 다시 꺼내는 것이 가능하다.
1. git stash : 임시로 변경사항 저장하고 되돌리기
git stash에서 꼭 알아야 하는건 변경사항을 임시로 저장하는 git stash 명령어 이렇게 저장한 임시 변경 사항을 꺼내오는 git stash pop 명령어이다. pop 이라는 명령어를 보듯, stash 는 기본적으로 가장 최근에 저장한 변경을 꺼내온다.
간단한 예제를 알아보자,
$ tree
.
├── README.md
└── index.html
이 git 저장소의 파일들을 편집중에 다른 내용을 처리해야하는 상황이라면, 형재 git 저장소의 상태는 git add 로 스테이지 단계에 들어가 있을것이다.
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
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: index.html
스테이지 단게란?
워킹트리란?
git stash 명령어는 git 저장소에 관리 하고 있는 파일들을 대상으로 실행되며, 스테이지에 있는 내용과 아직 스테이지에 들어가 있지 않은 변경사항 모두 저장해 준다. 그럼 이상태에서 git stash 를 실행하고 git status를 확인해 보면 어떻게 될까?
$ git stash
Saved working directory and index state WIP on master: 451c825 Add index.html
$ git status
On branch master
nothing to commit, working tree clean
워킹트리가 비어졌다. 즉, 최종 커밋으로 부터 변경된 내용이 없다는 의미이다. 이제 작업을 진행하면 된다. 만약 app.js라는 파일을 급하게 하나 추가하고 커밋했다고 가정하자,
이제 프로젝트는 ㅇ래와 같아진다.
$ tree
.
├── README.md
├── app.js
└── index.html
이번에는 git stash pop 으로 앞서 임시 저장한 내용을 가져온다.
$ git stash pop
On branch master
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: README.md
modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (1248c07e9784f15a5dfa8df78e50239fe083041f)
앞서 편집하고 있던 readme.md 파일과 index.html파일의 변경 사항이 워킹 트리에 다시 반영된걸 확인할 수 있다. git status 로 저장소의 상태를 확인한다.
$ git status
On branch master
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: README.md
modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
여기서 중요한점은 스테이지 상태까지 그대로 복원하지는 않는 다는 점이다.
stash는 커밋되지 않은 변경사항을 스택에 쌓아두고, 이걸 다시 꺼내오는 기능이다. 다른 커밋이 추가되어 있는 상태나 심지어 다른 브렌치에서 꺼내는것또한 가능하다. 하지만 다른 변경사항과 충돌나는 경우 merge 충돌과 마찬가지로 충돌을 풀어주어야 한다.
git stash 명령어 심화
git stash 를 어떻게 다루는지 살펴보았고 이번에는 stash의 명령어를 더욱 자세히 알아보는 시간을 가지려 한다.
git stash -m : commit 과 마찬가지로 변경사항에 메세지를 붙여둘 수 있다. git stash list : 서브 커맨드로 현재 저장소에 임시 저장된 전체 목록을 확인할 수 있다.
$ git stash list
stash@{0}: On master: app.js 작업을 위한 임시 저장
여기서 stash@{0}이 이 임시 변경사항의 임시 이름이 된다.
다시함번 git stash save = git stash 를 해준다
$ git stash save
Saved working directory and index state WIP on master: e1bbd0c Add app.js
결과
$ git stash list
stash@{0}: WIP on master: e1bbd0c Add app.js
stash@{1}: On master: app.js 작업을 위한 임시 저장
git stash apply : stash@{0}을 꺼내온다. (apply) apply 를 명시하여 실행하면 stash@{0}의 내용을 꺼내오지만, 삭제하지는 않는다. git stash drop : stash@{0}을 삭제한다. (drop)
git stash apply stash@{1} git stash drop stash@{1}
git stash pop 의 index옵션
앞선 예제에서 git stash pop을 하는 경우 git add한 스테이지 상태는 복원이 되지 않았습니다. git stash pop이나 git stas apply 명령어를 사용할 때 –index 옵션을 붙이git stash clear: 모든 임시 변경사항(stash)을 삭제
clear 서브 커맨드를 사용하면 stash 스택에 저장된 모든 임시 변경 사항을 한 번에 삭제해버릴 수 있습니다.면 스테이지 상태까지 같이 복원 `됩니다.
git stash clear
clear 서브 커맨드를 사용하면 stash 스택에 저장된 모든 임시 변경 사항을 한번에 삭제하는것이 가능하해진다.
$ git stash clear
$ git stash list
git stash apply 로 꺼낸 임시 변경사항의 내용 되돌리기 다른 작업을 진행하다 git stash aaply 로 인해 저장해온 변경사항을 꺼내오는것이 가느앟다. 하지만 인덱스를 잘못 지정하거나, 불필요한 내용이 포함되있어 정확히 꺼내온 내용만 다시 되돌리고 싶을때가 있다. 이때는 명령어로 aaply 한 stash 변경 사항만 되될ㄹ수 있다.