March 09, 2023 | Created # 用 git stash pop 取回檔案失敗 ### 前言提醒 暫存後會需要修改相同檔案的狀況下,不建議使用 stash,使用 commit 直接推到遠端分支會更安全,除了可以正常取回檔案外,也不用擔心本機電腦出問題而沒有任何備份資料。 ### git stash pop command is not working > *我剛剛使用 `git stash -u`,現在想要 `git stash pop`* > *但指令輸入完後,用 `git status` 確認,並沒有看見剛剛想要 pop 出來的檔案!* > *花這麼多心力的檔案不見了嗎!?* 首先,先別著急。 使用 `git stash list`,查看一下剛剛 stash 的分支在不在,真的被 drop 掉了嗎?  若真的 drop 掉了,則此篇不適用於你的問題。 正常來說,只要 `git stash -u` 有成功,在使用 `git stash drop` 前,暫存都不會消失。 ### 既然沒有消失,為何無法 pop 取回資料呢? 比較常見的狀況是,該分支曾經使用 `git pull` 取得並更新至最新的分支狀態,導致 stash 中的檔案有衝突。 與 `git pull` 時造成的 `Conflict` 不同,當 stash 檔案有衝突時,便會取消 pop 動作,導致指令輸入完後,`git status` 結果並未改變。 ### 那該怎麼辦? > *stash 中的檔案花了我很多心思,而且我當前有檔案異動,這些檔案我也想留。如果可以,我還是希望把檔案取回來 ...* 首先為了雙方有共識,先假設: > 當前有異動檔案的分支: A分支 > 專案最新檔案所在的分支: develop > 當前異動檔:當前異動檔 > stash 拋不回的檔案:暫存檔 開始前,先了解一下接下來我們大概要做些什麼: 1. 保留 `A分支` **當前異動檔** 2. 保留 `A分支` 的狀態,讓**當前異動檔**隨時可以取回 3. 切換至 develop 並建立 `B分支` 取回**暫存檔** 4. `B分支` 取回檔案後,先處理完並 push 上 `遠端B分支` 5. 回到 `A分支` 取回**當前異動檔** 6. pull `遠端B分支`,使其產生 Conflict 並解掉 7. 恭喜你**暫存檔**與**當前異動檔**都回來了 如果這個流程可以理解每個環節該怎麼做,就可以不用繼續往下看囉。 若還無法,接下來會告訴你各環節為什麼要這麼做,那我們就開始吧! --- 首先必須瞭解,在 `git stash pop` 前,分支最好保持乾淨。 不過既然現在問題已經發生了,就必須思考: >在不影響**當前異動檔**分支的前提下,應該如何處理 因此,我們最好另外開一個乾淨的分支來處理**暫存檔**。 為了開一個乾淨的分支,我們就需要執行 `1.保留 A分支 當前異動檔` ### 保留 A分支 當前異動檔 ```bash= git stash -u # 暫存檔案 git stash list # 確認檔案確實有暫存成功 git status # 確認分支狀態無任何異動檔案 ``` ### 保留 A分支 的狀態,讓當前異動檔隨時可以取回 現在 `A分支` 乾淨囉。 *當然,這代表可以處理**暫存檔**的問題了,但是同時也會導致**當前異動檔**會 pop 不回來。* **那麼問題還是沒有解決,對吧?** 所以這個分支別再做任何異動,包含:檔案異動、`git pull` 等,會更新分支狀態的行為。 務必維持分支的狀態,之後要回來處理**當前異動檔**,才能夠無後顧之憂的 pop 回來。 ### 切換至 develop 並建立 B分支 取回暫存檔 前面都瞭解後,就可以開始準備取回暫存檔囉! #### 請務必留意!切換回 develop ,絕對不要 pull! > 很有可能會因為最新的檔案又造成衝突。 > 不過若不慎發生這種事,也還是可以利用 `git reset HEAD^` 的方式回到前一個 commit,就不再此文贅述了 ```bash= git checkout develop # 切換回 develop git checkout -b B分支 # 建立 B分支,分支名稱請自行更換 git stash list # 確認暫存清單 ``` 到這裡,你會發現暫存清單中有兩筆暫存,清單依照 stash 順序,最後推入的暫存為 `stash@{0}`,舊的暫存序號會依序往後推1號。 因此依照這個規則,**當前異動檔**是最後推入的: > 當前異動檔:stash@{0} > 暫存檔:stash@{1} 那麼我們就將暫存檔取回來吧 ```bash= git stash pop stash@{1} ``` > OS 如果是 win7,會因為作業系統限制,只能安裝較舊的 npm 及相關環境,導致此語法有錯,此處只須加上雙引號即可: > `git stash pop "stash@{1}"` ### B分支 取回檔案後,先處理完並 push 上遠端B分支 一般而言,分支都需要經過 code review 後才會 merge 進 develop。 此步驟重點: > 將檔案推到遠端分支,利用解 Conflict 的方式,來取代 stash pop 因衝突而無法順利取回資料的狀況。 因此你也可以直接推到遠端建立 `B分支` ```bash= git add . git commit -m "你的commit描述" git push origin B分支 ``` ### 回到 A分支 取回當前異動檔 剛剛 push 完,現在 `B分支` 就結束他的任務囉! 讓我們回到 `A分支` ,並將**當前異動檔**取回來 ```bash= git checkout A分支 git stash list # 此時只剩 1 個暫存資料 git stash pop stash@{0} # 取回當前異動檔 ``` ### pull 遠端B分支,使其產生 Conflict 並解掉 現在我們的 `A分支` 恢復到一開始有**當前異動檔**的狀態,接下來就可以將**暫存檔**從 `遠端B分支` 找回來了 ```bash= git pull origin B分支 ``` 接著一定會產生 Conflict! 畢竟一開始就是因為檔案衝突才會無法 pop 檔案,那麼就耐心解決掉所有的衝突吧~ 最後, ### 恭喜你暫存檔與當前異動檔都回來了 什麼? 還沒有? 或許再回頭看看有沒有什麼步驟漏掉了 或是留言給我,我可以試著通靈看看~ --- ###### tags: [`git`](https://hackmd.io/@elzuoc?tags=%5B%22git%22%5D) [`git stash`](https://hackmd.io/@elzuoc?tags=%5B%22git+stash%22%5D) ###### 文章若有任何錯誤,也請不吝給予留言指正,謝謝大家!
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.