可能會遇到使用 git stash
指令情境:
假想今天可能在公司進行手中任務時,突然接收到老闆或是合作夥伴的緊急求救,請你立刻放下目前工作,改進行新的棘手任務,那麼目前的任務要怎麼保存進度呢?讓你在完成臨時任務後可以切換回到當初進行的部份?
先前有提到在合併 merge 或是提交到 GIt 時,有可能會發生衝突的情況,會出現以下訊息提示:
commit your changes or stash them before you can merge.
當遇到以上情形,需要先告一段落,處理其他事情再返回繼續開發的時候,我們可以使用兩種方式來達到我們的需求。
git add
→ git commit
→ 處理其他事情後回來 → git reset
git stash
暫存檔案先將所有的修改保存下來 - git add -all
可以採用先前習慣的方式保存目前的進度。先使用 git add
指令加至暫存區後,後使用 git commit
指令提交,如此一來可以先當作是一個 commit 版本,只是特別注意這是我們進行一半的版本,之後再繼續完成這個任務即可。
$ git add -all # 將目前修改內容加至暫存區
$ git commit -m"undone files" #提交到數據庫,並註明這是尚未完成的檔案
首先這是我目前手中進行的檔案內容(已有 git init
建立 Git 版本控制)
將目前進度加至暫存區 git add
使用 git commit
指令將檔案提交,並註解這是「未完成的檔案」
因為接下來要進行臨時任務,先假設那個臨時任務是在我的另一個分支上,假使忘記分支有哪些,可以使用 git branch
指令查看現有的分支。
$ git branch # 檢視分支
檢視分支後,知道另一分支是 a_branch
,之後使用切換分支的指令,將臨時任務完成。
a_branch 分支是先前練習 git 時,就有建立好的分支,因此在這裡也可以自己新增分支來修改臨時任務,或是切換到實際任務的分支上。
確保提交好進度中的檔案後,就可以使用切換分支的指令將分支切到我們需要完成的任務分支,等完成後再切回原來的分支,並進行 Reset 即可喔!
Reset 是因為先前的文章有提到過,可以將 HEAD 切換到上一次更新的 Commit 版本,如此一來我們就可以得到先前完成一半的進度,並持續將它完成。
切換到 a_branch 分支 - git checkout
指令
$ git checkout a_branch # 切換到 a_branch 分支
等臨時任務完成並提交後,我們可以再次切換回原來的分支,並使用以下指令回到上次提交前的版本。
$ git reset HEAD^
如此一來就可以繼續完成上次尚未完成的動作囉!
git stash
暫存檔案👉 假設今天不想要為還沒完成的檔案額外新增一個 Commit ,也不想要使用切換分支再回來 Reset 的動作,那麼在 Git 的指令中, git stash
指令也可以達到同樣暫存檔案的效果。
講解 git stash
指令前,先整理關於 git stash 常用到的指令
git stash
暫存檔案$ git stash # 暫存檔案
只用 git stash
暫存檔案指令後,會得到訊息回饋:
👉 Saved working directory and index state WIP on master: 59a05db update index.html
這裡的
WIP
意思是:Work In Progress
使用這指令後,回到 index.html 檔案會發現內容全部不見了。
這是什麼回事呢?東西去哪裡了?
git stash list
查看暫存檔案列表在第一部分,我們使用 git stash
指令將檔案暫存,那麼檔案存到哪裡呢?我們可以使用 git stash list
指令查詢。
$ git stash list # 查看暫存檔案列表
得到的訊息回饋會是:
👉 stash@{0}: WIP on master: 59a05db update index.html
stash@{0}
為 Stash 的代名詞,0
代表第一筆資料WIP
為 Work In Progress,為進行中之意。
暫存列表可以存很多檔案,假設我在 a_branch 分支也有想要暫存的檔案。
$ 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 檔案顯示(已刪除)
檔案去哪裡了呢?我們可以使用 git stash list
指令查看。
在 item2 樣式設定裡,也可以看到他有提示目前有兩筆暫存檔案。
👉 新增的檔案:stash@{0}: WIP on a_branch: 59a05db update index.html
注意:原本為 master 分支時暫存的檔案 Stash 代名詞是
stash@{0}
,但現在變成stash@{1}
囉!
首先先從 pop
指令開始介紹。
#pop
指令 - 當某個 Stash 檔案拿回確定成功套用到分支上後,就會自動從暫存檔案列表中刪除。
因為我們沒有指定 pop
指令要拿回拿一個檔案,所以會自動拿回最新一次放進 Stash 裡的檔案,也就是編號最小的檔案。
當我們拿回檔案後,因成功套用到 a_branch 分支上,所以 Stash 檔案清單裡就刪除已被拿回的檔案,現在我的暫存檔案裡就只剩下一個檔案了。
--
當然我們也可以指定我們要拿回哪個暫存檔案,並取回後在暫存檔案裡清除。
上面這張圖我分別在新增 hello2.html 、hello3.html 檔案時都各自將檔案暫存。
可以觀察在每次暫存時,工作目錄及檔案的變化。
上圖是我將 hello2.html 檔案暫存後,它顯示已刪除,其實他只是被隱藏起來,所以在工作目錄中看不到 hello2.html 的檔案。
上圖一樣的概念,我將新增的 hello3.html 的檔案暫存後,在 git 裡他被儲存隱藏到暫存檔案列表,因此工作目錄中也看不到檔案。
使用 git stash list
指令查看現在的暫存檔案列表
假設我想拿回 hello2.html 這個檔案,Stash 的代名詞為 stash@{1}
,並且拿回後不再存在檔案列表中,那麼可以輸入以下指令達成:
$ git stash pop stash@{1}
拿回後,使用 git stash list
指令觀察現在暫存檔案列表的狀況:
上圖顯示現在剩兩個暫存檔案,且他們的原本
編號 2
的檔案會因為有刪除的檔案,而順勢變成編號 1
。
#drop
指令 - 可指定移除某個 Stash 檔案
👉 如果沒有指定移除哪個檔案的話,那麼預設就是直接移除編號最小的檔案。
$ git stash drop # 移除暫存檔案
$ git stash drop [指定檔案] # 移除暫存檔案中的某個指定檔案
#apply
指令 - 當某個 Stash 檔案拿回確定成功套用到分支上後,原本暫存的檔案依然保留在暫存列表中。
$ git stash apply # 拿回暫存檔案,但原本的暫存檔案依然保留在暫存列表中
$ git stash apply [指定檔案] # 可指定要拿回哪個檔案
上圖我拿回檔案後套用在 a_branch 分支上後,這時候再看一下檔案列表:
可以發現檔案列表依然還有這個檔案。
# 三個指令的關係
💡 pop 指令
可以看作是將 drop 指令
加上 apply 指令
以上三種指令可以針對不同的需求來使用。
git stash clear
一口氣移除所有暫存檔案$ git stash clear # 清除所有暫存檔案
如果有仔細觀察的話,會發現在每次使用 git stash
指令時,我都會先確保檔案有加至暫存區,這是因為 Untracked 狀態
的檔案預設是無法被 Stash 的,那這時候除了手動 git add 外,也可以使用 -u
參數,來做 Stash 指令。
假設今天新增了 hello4.html 檔案,直接使用 git stash
指令來暫存檔案。
No local changes to save
- 目前本地沒有什麼檔案可以儲存。(因為 hello4.html 是未追蹤狀態,因此無法被暫存)
改加上 -u
參數
$ git stash -u
可以看到成功新增一個暫存檔案,且 hello4.html 檔案被刪除了。
關於暫存檔案各種操作就先筆記到這裡啦!🙋