지옥에서 온 Git

stash

수업소개

다른 브랜치로 checkout을 해야 하는데 아직 현재 브랜치에서 작업이 끝나지 않은 경우는 커밋을 하기가 애매합니다. 이런 경우 stash를 이용하면 작업중이던 파일을 임시로 저장해두고 현재 브랜치의 상태를 마지막 커밋의 상태로 초기화 할 수 있습니다. 그 후에 다른 브랜치로 이동하고 작업을 끝낸 후에 작업 중이던 브랜치로 복귀한 후에 이전에 작업하던 내용을 복원할 수 있습니다. 여기서는 이 기능에 대해서 알아봅니다. 

수업

댓글

댓글 본문
  1. CrashOverride
    stash 기능 자체가 git이 버전 관리를 하고있는 파일들 대상으로만 적용이 되다보니
    일단 add는 하셔야지 싶고요.
    나중에 apply든 pop이든 사용해 복원하고 불필요한 파일들은 다시 unstage 상태로 돌리면 될 것 같습니다.
    대화보기
    • CrashOverride
      1~8번 작업 자체는 저렇게 나오는 게 맞는 듯하고요.
      다만 pop은 apply와 drop이 한번에 순차적으로 실행되는 부분이니
      stash save 됐던 내용이 복원되고 stash list에서 가장 최근의 1건은 삭제가 되고요.

      그냥 drop은 잘못 사용했을 때 복구하는 방법이 있는지 모르겠습니다만,
      stash list에 올라간 기록과 함께 작업했던 내용들도 함께 삭제되니 주의해서 사용해야지 싶습니다.
      대화보기
      • 20210614
      • boksoon
        개꿀팁 감사합니다.
      • 주니어개발자
        git stash --help

        git stash
        git stash apply
        git stash list
        git stash drop


        git stash pop
        => git stash apply; git stash drop;

        stash는 버전관리되고 있는 파일만 적용된다
        가장 최근에 진행 중인 dirty working directory 내용부터 pop
      • 현수
        감사합니다
      • supernet
        완료!!!
      • 게케게케
        감사합니다!
      • seokhee
        stash 잘 배웠습니다.
        적어도 커밋대기상태에 올라온 파일들을 하이딩한다는 것은 알겠는데요.
        그럼 add하지 않고 vim으로 수정만 한 파일들은 어떻게 처리하면 되나요?
        다른 브랜치로 넘어가도 저게 계속 뜰텐데
        일단 add를 하고 작업을 해야하는건가요?
      • 초간단
        stash : branch작업중에 다른 branch로 이동못할때 stash(챙겨두다)로 옮겨갈수있음.

        master에서 f1.txt 만들고,
        exp브랜치 만들고 f1.txt 를 적당히 수정해주자.
        여기서 다시 master로 가보자. $git status하면 f1.txt가 exp브랜치에서 수정한 내역의 영향도 받는걸 볼수있음.
        exp브랜치에서 아직 완성하지 않아서 commit도 애매하고 이렇게 checkout도 애매할때 : stash

        $git stash --help

        $git stash 만 쓰거나,
        $git stash save 쓰면, 세이브된걸 볼수있음.
        WIP란건 working in process란걸로, 작업중이란 뜻임.

        $git status 해보면, 아무것도 commit할것 없다 나오고, f1.txt내용보면 내가 쓴 내용이 없어져있음.
        이 상태에서 $git checkout master 해서 master브랜치에서 마음편하게 작업할 수 있음.
        작업이 끝나면, exp로 돌아와서 $git stash apply 하면, 다시 원래 작업하던상태로 돌아옴.

        $git stash list 해보면, 뭔가나옴.

        현재 stash한 내용(modified뜬 내용)을 날려버리자.
        $git reset --hard HEAD 쓰면, 제일 최신커밋상태로 감.

        $git stash list 하면, 아직 남아있는게 보임.
        $git stash apply 하면 다시 남아있는게 보임.

        $git reset --hard 하면 리셋되니 날라가고
        $git stash apply하면 다시 돌아오는거임.

        즉, $git stash list 안에있는게 명시적으로 삭제하지 않는 이상 살아있는것임.

        $git reset --hard 한번 다시해서 초기화해보자.
        $vim f2.txt 에 내용넣고
        $ git add f2.txt
        $ git stash 해서 stash하자.
        $ git stash list 하면 2개의 stash가 저장된것을 볼수있음.

        방금 제가 처리한것은 {0} 위에껏임.
        아까 처리한것은 {1} 밑에껏임.
        git stash apply하면 제일 위의 stash {0}을 적용하는 것임.

        그 이전에 stash도 순차적으로 적용하고싶다면??
        $git stash drop
        하면 제일 최신의 stash가 사라진것을 볼 수 있음.
        $git stash apply; git stash drop; 이라하면, 적용하고 삭제하고를 한번에 하는거임.

        apply : 제일 최신의 stash를 사용한다. 하지만 그 stash는 사라지지않는다
        drop : 최신의 stash를 지운다.


        $git stash apply; git stash drop; 과 같은 명령어는
        $git stash pop 이다.(apply+drop의 기능)




        f1.txt의 내용을 수정하고, f2.txt을 새로만들어 보자.
        $git status하면,
        f1.txt는 modified되는 즉, tracked도 되는파일이고
        f2.txt는 untracked 되는파일임.
        여기서 $git stash 하면
        $git status했을때, f2.txt는 untracked이니 stash가 되지않음.
        즉, stash는 버전관리가 되고있는 파일에 대해서만 stash가 된다.
      • PassionOfStudy
        * stash 사전적 의미 '감추다'
        > commit하기전에 다른 branch로 checkout할 때 기존의 브랜치의 working process를 감춘다.
        - git stash 명령으로 stash를 실행할 수 있다.
        - git stash apply로 다시 돌아갈 수 있다.
        - git stash list로 stash의 목록을 볼 수 있다.
        - stash는 스텍처럼 쌓인다. git apply는 최신 stash로 돌려준다.
        - stash list의 스텍을 지우려면 drop하거나 apply 후 지우고 싶으면 pop을 이용한다.
      • software.lee
        감사합니다.
      • 택길이지
        git stash drop 나 git stash pop를 하면 add 나 commit 대기중(?)이던 내용도 삭제 되는게 맞는 건가요?

        1. vim f1.txt 로 피일 내용 수정
        2. git status 로 modified: f1.txt 내용 확인
        3. git stash save 명령
        4. git status 로 확인 시 "working tree clean" 출력
        5. git stash list 로 stash@{0}: WIP on master: 65c0e92 1 내용 확인
        6. git stash drop 로 list 내용 삭제
        7. git stash list 로 내용 삭제 된거 확인
        8. git status 로 확인 시 "working tree clean" 출력

        이게 맞는건가요? 몇번을 다시해도 계속 똑같은 결과가 나오는데 제가 맞게 이해한건지 잘 모르겠네요
      • 몽키덩키
        git stash save 하면

        Saved working directory and index state WIP on exp: e994670 1

        위와 같이 나오고
        HEAD 가 변경됬다는 아래의
        HEAD is now at e994670 1 이라는 메시지가 나오지 않습니다.
        영상이나 검색을 해보아도 모두 두가지 메시지가 나오는데 저만 Saved 관련 메시지만 나옵니다.
        $ git stash save

        warning: LF will be replaced by CRLF in f1.txt.
        The file will have its original line endings in your working directory.
        Saved working directory and index state WIP on exp: c116a05 1


        그래서 그런지 git stash save 후 git status 하면 아래와 같이 나옵니다.

        $ git status
        On branch exp
        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: f1.txt

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

        제가 예상 하기론 아래의 메시지가 나와여 하는데 말이죠

        On branch exp
        nothing to commit, working tree clean

        git stash save 를 두번 입력하면 그제서야 nothing to commit, working tree clean 이메시지가 출력됩니다.

        혹시 왜 이런 현상이 나오는지 알 수 있을까요? 몇일 고민해봐도 잘 모르겠네요
      • 어프리
        협업하는데 stash가 중요하더라구요! 감사합니다!!
      • 고스트프리
        다시 branch 처음으로 돌아갑니다.^^
      • haMsa
        잘 보고 있습니다. 감사합니다.
      • 김수현
        초보자가 적은 글이라 내용이 틀릴 수도 있습니다.
        틀린 부분이 있으면 댓글 달아주시면 감사하겠습니다.

        Git은 파일의 변경사항이 없다면 브랜치들 사이로 자유롭게 이동이 가능합니다.
        하지만 변경사항이 있을 경우에는 커밋/스태쉬한 후 이동해야 합니다.
        (강제적인 경우, 비강제적인 경우?가 있습니다.)

        Git은 예외적인 경우 1개를 제외하고는
        다른 브렌치에 갈 때에는 수정사항을 반드시 commit/stash한 후에 가야함
        (에러메시지가 나고 움직이지 않음 <--- 강제적으로 이동을 못하게 설계됨,
        예외적인 1경우(한개의 경우)에도 비강제적이지만 커밋/스태쉬를 해야 함)

        예외적인 1경우는 가지(branch)를 만들고 커밋을 한번도 하지 않은 경우입니다.
        커밋을 한번도 안한 경우란 2가지 경우가 있습니다.
        1) 새로운파일을 만들고 커밋하지 않은 경우
        2) 브랜치를 만들고 분기한 브랜치 사이에 이름이 같은 파일이,
        양쪽 브랜치에서 1번의 변경도 없다가... 처음으로 변경하고 커밋하지 않은 경우

        1)의 경우 새로운 파일을 만들 때마다 커밋하지 않고 다른 어떤 브랜치로도 이동이 가능합니다.
        그렇지만 그 파일을 커밋하고 1번째 수정부터는 커밋하지 않으면 이동이 되지 않습니다.
        어느 브랜치에 커밋하는 순간 등록?되는 것 같습니다. 이파일은 이소속의 파일이다.
        변경후에 다른 브렌치로 가려면 커밋/스태쉬해야 한다는 식의...메시지가 나오고 이동이 되지 않음.

        그리고
        2)의 경우에는 분기했던 브랜치로 이동이 가능하지만
        분기하지 않은 다른 브랜치로는 이동이 되지 않음.
        (이경우 예를 들어 master브랜치에서 분기한 경우라면...
        master브랜치에서 분기한 가지가 더 있고
        master브랜치의 Head?와 같은 상황이라면(커밋이 한번도 없었다면)
        그 브랜치로 이동 가능 <--- master와 상황이 같으므로..)
        그리고 한번 커밋을 하여 이름이 같더라도 내용이 다르게 된 후에는
        파일변경후 커밋/스태쉬하지 않고 이동할 수 없음
        -----------------------------------------------------------------------

        위와 같은 경우에 있어서는...
        git이 강제적으로 다른 브렌치로의 이동을 금지하는 것은 아니지만
        그렇더라도 아래와 같은 이유(다른 브랜치에 영향을 줌) 때문에 커밋/스태쉬를 해야 함.

        예를들어 master가지에서 exp브랜치를 만들고 한번도 커밋하지 않았을 경우에는 커밋/스태쉬를 하지 않고 브랜치 사이로 자유롭게 이동할 수 있음.( 위의 1), 2)의 경우 참조 )

        <같은 이름의 파일을 변경 - 위2)의 경우>
        이경우 예를 들어 exp브랜치에서 '같은 이름의 파일'을 변경한 경우에는 커밋/스태쉬하지 않고 master브랜치로 가서 '같은 이름의 파일'을 보면 exp에서 변경한 내용이 반영된 것을 확인할 수 있음. 그리고 exp에서 변경한 파일이 master에서 git status 하면 커밋하지 않은 파일로 나옴.

        <다른 이름의 파일 생성 - 위1)의 경우>
        그리고 exp브랜치에서 '다른 이름의 파일'을 새로 만든 경우 커밋/스태쉬를 하지 않고 '다른 브랜치'에 가면 exp브랜치에서 만든 파일이 '다른 브랜치'에서 ls -al에 나오고 git status하면 커밋하지 않은 파일로 나옴.

        <다른 브랜치에서 커밋가능>
        그리고..다른 브랜치에서 파일을 만들거나/고친 후에 다른 브랜치로 이동했을 경우
        이동한 곳에서 커밋을 하면 다른브랜치에서 만든 파일이 그곳파일로 됨(커밋이 되고 'cat 파일이름'하면
        다른 브랜치에서 만든 파일이 등록된 것을 볼 수 있고
        그 경우 파일이 만들어진 브랜치에서 가서
        cat 파일명하고 파일 내용을 보면 > 변경하기전 파일로 되어 있음
        다른 브랜치에서 만든 파일을 커밋가능하다는 것 확인함,

        파일생성도 마찬가지로
        다른 브랜치에서 커밋가능 그 경우 만들어진 브랜치로 가서 보면 만들어진 파일이 없어진 것을 확인 함.


        위와 같이...
        커밋을 하지 않는 경우 다른 가지에 영향을 줄 수 있다는 것을 알 수 있음.
        따라서 예외적인 경우에도 커밋/스태쉬가 필요함.
        (위에서 처럼 예외적인 1경우는 커밋을 하지 않고 다른 브랜치로 이동할 수 있기 때문에,
        다른 브랜치로 이동하여 ls -al(파일리스트확인), cat 파일이름(파일내용확인)을 할 수 있었지만,
        다른 경우에는 강제적으로 이동을 막고 있기 때문에 위와 같은 내용으로 확인할 수 없었음.
        다른 경우에도 다른 파일에 영향을 주는 지는 모름)

        결국 다른 가지에 갈 때는 모든 경우에서 커밋/스태쉬를 해야 함. <--- ★ 결론 ★

        <위 내용은 직접 실험해본 내용입니다.>

        ---------------------------------------------------------------------------------------------
        브랜치는 새로운 작업공간을 만드는 것임. 파일도 달라지고 내용도 달라짐.

        윈도우에서 같은 디렉토리(=워킹디렉토리)지만...
        branch를 바꾸고 탐색기를 보면, 파일목록이 바뀌고 파일갯수가 달라지고 파일내용도 달라짐 >
        신기하게도 브랜치를 바꿀때마다 새로운 디렉토리로 이동하는 현상이 윈도우 탐색기에 나옴.
        탐색기에서 디렉토리를 변경하지 않았는데도...
        (이 경우 주의해야 할 점은
        위와 같은 현상을 보기 위해서는 "내문서"로 가면 안되고
        ---> c:/사용자/user/gitfth 와 같은 순으로 찾아가야 위 와 같은 현상을 볼 수 있음. 만약 내문서와 같은 디렉토리에서 작업하고 있다면...이곳 강의에서는 이 디렉토리에 저장되는 것 같음)

        브랜치를 바꿀 때마다 워킹디렉토리의 파일목록이나 파일내용이 바뀌는 것은...
        .git 디렉토리에 파일을 보관하고 있다가 브랜치를 바꾸면
        워킹디렉토리에 있는 기존 파일을 삭제하고 해당파일을 .git디렉토리에서 복사하여 옮겨오는 것 같음
        ----------------------------------------------------------------------------------
        스태쉬는 임시저장임.
        나중에...
        '변경된 커밋'은 원격저장장치(네트워크)로 저장하는 대상이 됨
        하지만 '스태쉬'는 원격저장장치로 저장되는 대상이 아님.
      • 김수현
        stash는 감추다 숨겨두다라는 뜻
        브랜치를 활발하게 사용할 경우 사용
        브랜치에서 작업하던 내용이 다 끝나지 않았는데
        다른 브렌치로 checkout해서 다른 일을 해야 하는 경우
        작업이 끝나지 않은 작업을 커밋할 수는 없고 커밋을 안하면 체크아웃할 수가 없고
        이런 경우 stash라는 것을 이용 > 작업했던 내용을 어딘가 숨겨 놓을 수 있음
        브랜치의 가장 최신 커밋(해드의 버젼)으로 이동해서 현제 브랜치의 상태를 깔끔하게 만들고
        다른 브랜치로 체크아웃할 수 있다.

        브랜치를 활발하게 사용하지 않는 경우 필요 없음 (그냥 그런게 있다 정도로 남겨 뒀다 필요시 사용할 것)
        git init
        vim f1.txt > a > git add f1.txt > git commit -m "1"(큰따음표 안해도 됨)
        이 상태에서 새로운 브랜치를 만들겠습니다.
        git checkout -b exp
        vim f1.txt > 담줄b > 아직 작업이 끝나지 않았는데...
        어떤 경우 master브랜치로 체크아웃해야 하는 경우에
        이상태에서 체크아웃하게 되면 어떤 문제가 생길까요?
        git checkout master
        git status했을 때 f1.txt가 add하지 않았다고 나옴
        exp에서 수정한 내용이 master에 까지 영향을 줌
        그러면 다시 git checkout exp
        git status > 여전히 add안했다고 나옴
        아직 수정했지만 커밋하기에는 부족한 소스를 어떻게 해야 할까?
        git stash --help
        git stash라고 하거나 save를 붙여준다 > git stash [save]
        Saved working directory and index state WIP on exp: d82c224 1 <--메시지가 조금 다름
        WIP : 워킹 인 프로세스 <-- 라는 이야기 (작업중이라는 뜻)
        워킹디렉토리와 인덱스에 있는 변경사항들이 save되었다
        git status > 커밋할 것이 아무것도 없는 것으로 나옴
        즉 vim f1.txt는 수정했던 내용이 사라짐
        이상태에서 git checkout master를 하게 되면 작업/내용확인 맘 편하게 할 수 있음
        그 작업이 끝나면 git checkout exp로 해서 작업을 계속 진행하면 됨
        감추어 놓았던 내용을 복원(5:30) --> git stash --help
        git stash apply
        f1.txt가 살아나 모디파이 되었다고 나옴 > 스태쉬한 것이 살아난 것을 볼 수가 있음
        git stash list
        git reset --hard HEAD <--- 수정했던 내용을 날림 < 가장 최신의 커밋 상태로 돌아감
        git status > 아무것도 커밋할 것이 없다고 나옴
        스태쉬한 내용을 잃어 버린 것일까? > 아닙니다. stash list > 여전히 남아 있음
        이상태에서 git stash apply > 다시 살아 남 > 무슨 이야기냐 하면 스태쉬의 내용은 명시적으로 삭제하지 않으면 살아 있다는 것
        vim f2.txt > a > git add f2.txt > f2.txt를 git stash하면 git status > 수정된 사항이 나오지 않음
        git stash list라고 하면 2개가 나옴
        방금 처리한 스태쉬는 위에것 [0]이 방금 처리한 내용임
        git stash apply > 제일 위에 있는 스태쉬를 적용함
        그러면 스테쉬 내용을 순차적으로 적용하려면 어떻게 해야 하는가?
        git stash drop > 가장 최신의 스테쉬를 삭제
        에러 같은 경우는 컴퓨터 상황 때문에 생기는 것 > 무시 > git stash list > 하나만 남아 있음
        git stash apply; git stash drop; <-- 적용/삭제를 한번에
        이것이 커멘드라인의 편리함임
        git status해보면 > 모두 살아 난 상태이고
        git stash list > 아무것도 나오지 않음
        불편함 > 한번에 하는 명령은? git status > git reset --hard
        git status > 다 지워서 아무것도 안나옴
        vim f1.txt > 담b > git add f1.txt > git stash > git status > 변경사항이 없어짐
        git stash pop <-- 스태쉬가 어플라이+드랍 모두 됨
        git stash --help
        git reset --hard
        vim f1.txt > 담b > vim f2.txt > a > git status > f1.txt(수정 -- 추적되고 있는 파일) , f2.txt(언트렉드 파일)
        이상태에서 git stash하게 되면 > git status > f2.txt는 언트렉이기 때문에 스태쉬가 되지 않음.
        git stash <-- 버젼관리가 되는 파일에 대해서만 스태쉬를 함
      • 폭스킴
        git 참 알듯말듯 하네요~ @_@
        현재 BRANCH의 작업내용을 COMMIT하기 애매한 생태에서, STAGING AREA에 있어서 TRACKING되고 있는 파일들만 임시 스택에 저장하고, 다른 BRANCH로 이동해서 작업하다 다시 돌아와 저장한 걸 복구하거나 버릴 수 있다는 거 맞나요?
      • code
        git stash --help
        git reset --hard HEAD

        git stash
        git stash --save
        git stash apply
        git stash drop
        git stash pop
        git stash list