iT邦幫忙

2021 iThome 鐵人賽

DAY 25
1
Modern Web

【Git】從零開始學習 Git - 30 天的學習筆記系列 第 25

Day25|【Git】git stash 暫存檔案

可能會遇到使用 git stash 指令情境:

  • 假想今天可能在公司進行手中任務時,突然接收到老闆或是合作夥伴的緊急求救,請你立刻放下目前工作,改進行新的棘手任務,那麼目前的任務要怎麼保存進度呢?讓你在完成臨時任務後可以切換回到當初進行的部份?

  • 先前有提到在合併 merge 或是提交到 GIt 時,有可能會發生衝突的情況,會出現以下訊息提示:

    commit your changes or stash them before you can merge.

當遇到以上情形,需要先告一段落,處理其他事情再返回繼續開發的時候,我們可以使用兩種方式來達到我們的需求。

  1. git addgit commit → 處理其他事情後回來 → git reset
  2. git stash 暫存檔案

方法一 |提交一個 commit 版本,處理完後再回來

先將所有的修改保存下來 - git add -all
可以採用先前習慣的方式保存目前的進度。先使用 git add 指令加至暫存區後,後使用 git commit 指令提交,如此一來可以先當作是一個 commit 版本,只是特別注意這是我們進行一半的版本,之後再繼續完成這個任務即可。

$ git add -all # 將目前修改內容加至暫存區
$ git commit -m"undone files" #提交到數據庫,並註明這是尚未完成的檔案

首先這是我目前手中進行的檔案內容(已有 git init 建立 Git 版本控制)

https://ithelp.ithome.com.tw/upload/images/20211005/20141010xyWA0lmUzo.png

https://ithelp.ithome.com.tw/upload/images/20211005/201410104ednTBrMlH.png

將目前進度加至暫存區 git add

https://ithelp.ithome.com.tw/upload/images/20211005/201410103bm34cs7w6.png

使用 git commit 指令將檔案提交,並註解這是「未完成的檔案」

https://ithelp.ithome.com.tw/upload/images/20211005/20141010dzDLntQJW0.png

因為接下來要進行臨時任務,先假設那個臨時任務是在我的另一個分支上,假使忘記分支有哪些,可以使用 git branch 指令查看現有的分支。

$ git branch # 檢視分支

檢視分支後,知道另一分支是 a_branch ,之後使用切換分支的指令,將臨時任務完成。

a_branch 分支是先前練習 git 時,就有建立好的分支,因此在這裡也可以自己新增分支來修改臨時任務,或是切換到實際任務的分支上。

https://ithelp.ithome.com.tw/upload/images/20211008/20141010xxh7x08RZU.png

https://ithelp.ithome.com.tw/upload/images/20211005/20141010EtauRxV4ZI.png

確保提交好進度中的檔案後,就可以使用切換分支的指令將分支切到我們需要完成的任務分支,等完成後再切回原來的分支,並進行 Reset 即可喔!

Reset 是因為先前的文章有提到過,可以將 HEAD 切換到上一次更新的 Commit 版本,如此一來我們就可以得到先前完成一半的進度,並持續將它完成。

切換到 a_branch 分支 - git checkout 指令

$ git checkout a_branch # 切換到 a_branch 分支

https://ithelp.ithome.com.tw/upload/images/20211005/20141010WGIM7jVVYo.png

等臨時任務完成並提交後,我們可以再次切換回原來的分支,並使用以下指令回到上次提交前的版本。

$ git reset HEAD^ 

https://ithelp.ithome.com.tw/upload/images/20211005/20141010RQwx25WUBy.png

如此一來就可以繼續完成上次尚未完成的動作囉!


方法二| git stash 暫存檔案

👉 假設今天不想要為還沒完成的檔案額外新增一個 Commit ,也不想要使用切換分支再回來 Reset 的動作,那麼在 Git 的指令中, git stash 指令也可以達到同樣暫存檔案的效果。

講解 git stash 指令前,先整理關於 git stash 常用到的指令

  • git stash - 暫存目前檔案
  • git stash list - 查看暫存的檔案列表
  • git stash pop - 叫回暫存的檔案,並從 stash list 中移除
  • git stash drop - 清除暫存檔案(最新的暫存檔案)
  • git stash apply - 將某個暫存檔案套用在目前分支,原本的 Stash 依然保留著
  • git stash clear - 清除全部暫存

#1 - git stash 暫存檔案

$ git stash # 暫存檔案

https://ithelp.ithome.com.tw/upload/images/20211005/2014101077Oh04Y6pW.png

只用 git stash 暫存檔案指令後,會得到訊息回饋:

👉 Saved working directory and index state WIP on master: 59a05db update index.html

這裡的 WIP 意思是:Work In Progress

使用這指令後,回到 index.html 檔案會發現內容全部不見了。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010snnrapzdJb.png

這是什麼回事呢?東西去哪裡了?

#2 - git stash list 查看暫存檔案列表

在第一部分,我們使用 git stash 指令將檔案暫存,那麼檔案存到哪裡呢?我們可以使用 git stash list 指令查詢。

$ git stash list # 查看暫存檔案列表

https://ithelp.ithome.com.tw/upload/images/20211005/20141010UZlOUnlZQm.png

得到的訊息回饋會是:

https://ithelp.ithome.com.tw/upload/images/20211005/20141010PULRoYBaI0.png

👉 stash@{0}: WIP on master: 59a05db update index.html

stash@{0} 為 Stash 的代名詞,0 代表第一筆資料
WIP 為 Work In Progress,為進行中之意。

暫存列表可以存很多檔案,假設我在 a_branch 分支也有想要暫存的檔案。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010Q0CBzPVj2e.png

$ git checkout a_branch # 切換到 a_branch 分支
$ git stash # 暫存檔案
$ touch hello.html # 新增 hello.html 檔案
$ git add . # 將所有檔案加至暫存區
$ git stash # 暫存檔案

這裡第一次 git stash 指令的訊息回饋是:No local changes to save

是因為我都已經提交完成,沒有什麼改變的檔案需要暫存。因此我新增一個 hello.html 檔案,並在裡面加入內容,之後加至暫存區,再使用 git stash 指令將檔案暫存。

這時候也可以看到剛剛新增的 hello.html 檔案顯示(已刪除

https://ithelp.ithome.com.tw/upload/images/20211008/201410102GCUALj8Bv.png

檔案去哪裡了呢?我們可以使用 git stash list 指令查看。

https://ithelp.ithome.com.tw/upload/images/20211008/201410108IDLU4Lw5d.png

在 item2 樣式設定裡,也可以看到他有提示目前有兩筆暫存檔案。

https://ithelp.ithome.com.tw/upload/images/20211008/201410108oi0pCxUdc.png

👉 新增的檔案:stash@{0}: WIP on a_branch: 59a05db update index.html

注意:原本為 master 分支時暫存的檔案 Stash 代名詞是 stash@{0} ,但現在變成 stash@{1} 囉!

#3 拿回 Stash 中的暫存檔案

  1. git stash pop - 叫回暫存的檔案,並從 stash list 中移除
  2. git stash drop - 清除暫存檔案
  3. git stash apply - 將某個暫存檔案套用在目前分支,原本的 Stash 依然保留著

首先先從 pop 指令開始介紹。

#pop 指令 - 當某個 Stash 檔案拿回確定成功套用到分支上後,就會自動從暫存檔案列表中刪除。

https://ithelp.ithome.com.tw/upload/images/20211008/20141010ahkqqgUhzB.png

因為我們沒有指定 pop 指令要拿回拿一個檔案,所以會自動拿回最新一次放進 Stash 裡的檔案,也就是編號最小的檔案。

當我們拿回檔案後,因成功套用到 a_branch 分支上,所以 Stash 檔案清單裡就刪除已被拿回的檔案,現在我的暫存檔案裡就只剩下一個檔案了。

https://ithelp.ithome.com.tw/upload/images/20211008/20141010p6mwSSlcTM.png

--

當然我們也可以指定我們要拿回哪個暫存檔案,並取回後在暫存檔案裡清除。

https://ithelp.ithome.com.tw/upload/images/20211008/20141010wpEKpH9yOP.png

上面這張圖我分別在新增 hello2.html 、hello3.html 檔案時都各自將檔案暫存。

可以觀察在每次暫存時,工作目錄及檔案的變化。

https://ithelp.ithome.com.tw/upload/images/20211008/201410109QwpPYPfgP.png

上圖是我將 hello2.html 檔案暫存後,它顯示已刪除,其實他只是被隱藏起來,所以在工作目錄中看不到 hello2.html 的檔案。

https://ithelp.ithome.com.tw/upload/images/20211008/201410106uCGVhv9Z8.png

上圖一樣的概念,我將新增的 hello3.html 的檔案暫存後,在 git 裡他被儲存隱藏到暫存檔案列表,因此工作目錄中也看不到檔案。

使用 git stash list 指令查看現在的暫存檔案列表

https://ithelp.ithome.com.tw/upload/images/20211008/20141010mzChnKYIjP.png

假設我想拿回 hello2.html 這個檔案,Stash 的代名詞為 stash@{1} ,並且拿回後不再存在檔案列表中,那麼可以輸入以下指令達成:

$ git stash pop stash@{1}

https://ithelp.ithome.com.tw/upload/images/20211008/20141010YaHkIavtTv.png

拿回後,使用 git stash list 指令觀察現在暫存檔案列表的狀況:

https://ithelp.ithome.com.tw/upload/images/20211008/201410108BZWCLDoGO.png

上圖顯示現在剩兩個暫存檔案,且他們的原本編號 2 的檔案會因為有刪除的檔案,而順勢變成編號 1

#drop 指令 - 可指定移除某個 Stash 檔案

👉 如果沒有指定移除哪個檔案的話,那麼預設就是直接移除編號最小的檔案。

$ git stash drop # 移除暫存檔案
$ git stash drop [指定檔案] # 移除暫存檔案中的某個指定檔案

https://ithelp.ithome.com.tw/upload/images/20211008/20141010pKG8WBw5Nb.png

#apply 指令 - 當某個 Stash 檔案拿回確定成功套用到分支上後,原本暫存的檔案依然保留在暫存列表中

$ git stash apply # 拿回暫存檔案,但原本的暫存檔案依然保留在暫存列表中
$ git stash apply [指定檔案] # 可指定要拿回哪個檔案

https://ithelp.ithome.com.tw/upload/images/20211008/20141010yqrjwJXzzb.png

上圖我拿回檔案後套用在 a_branch 分支上後,這時候再看一下檔案列表:

https://ithelp.ithome.com.tw/upload/images/20211008/20141010CRQlBcws98.png

可以發現檔案列表依然還有這個檔案。

三個指令的關係

💡 pop 指令可以看作是將 drop 指令 加上 apply 指令

以上三種指令可以針對不同的需求來使用。

#4 - git stash clear 一口氣移除所有暫存檔案

$ git stash clear # 清除所有暫存檔案

如果有仔細觀察的話,會發現在每次使用 git stash 指令時,我都會先確保檔案有加至暫存區,這是因為 Untracked 狀態的檔案預設是無法被 Stash 的,那這時候除了手動 git add 外,也可以使用 -u 參數,來做 Stash 指令。

假設今天新增了 hello4.html 檔案,直接使用 git stash 指令來暫存檔案。

https://ithelp.ithome.com.tw/upload/images/20211008/20141010hRwkf87uaa.png

https://ithelp.ithome.com.tw/upload/images/20211008/201410103Kf1hrq0Xe.png

No local changes to save - 目前本地沒有什麼檔案可以儲存。(因為 hello4.html 是未追蹤狀態,因此無法被暫存)

改加上 -u 參數

$ git stash -u

https://ithelp.ithome.com.tw/upload/images/20211008/20141010m6pieUi7vt.png

https://ithelp.ithome.com.tw/upload/images/20211008/201410107MhK22S5Ev.png

可以看到成功新增一個暫存檔案,且 hello4.html 檔案被刪除了。


關於暫存檔案各種操作就先筆記到這裡啦!🙋


上一篇
Day24|【Git】認識 git tag 標籤常用指令、標籤與分支的差異
下一篇
Day26|【Git】 從 Git 中移除重要個資或徹底清除檔案 - git filter-branch
系列文
【Git】從零開始學習 Git - 30 天的學習筆記30

尚未有邦友留言

立即登入留言