1. 程式人生 > >git stash 的各項命令用法

git stash 的各項命令用法

今天在看一個bug,之前一個分支的版本是正常的,在新的分支上上加了很多日誌沒找到原因,希望回溯到之前的版本,確定下從哪個提交引入的問題,但是還不想把現在的修改提交,也不希望在Git上看到當前修改的版本(帶有大量日誌和除錯資訊)。因此呢,查查Git有沒有提供類似功能,就找到了git stash的命令。

綜合下網上的介紹和資料,git stash(git儲藏)可用於以下情形:

  • 發現有一個類是多餘的,想刪掉它又擔心以後需要檢視它的程式碼,想儲存它但又不想增加一個髒的提交。這時就可以考慮git stash
  • 使用git的時候,我們往往使用分支(branch)解決任務切換問題,例如,我們往往會建一個自己的分支去修改和除錯程式碼, 如果別人或者自己發現原有的分支上有個不得不修改的bug,我們往往會把完成一半的程式碼commit
    提交到本地倉庫,然後切換分支去修改bug,改好之後再切換回來。這樣的話往往log上會有大量不必要的記錄。其實如果我們不想提交完成一半或者不完善的程式碼,但是卻不得不去修改一個緊急Bug,那麼使用git stash就可以將你當前未提交到本地(和伺服器)的程式碼推入到Git的棧中,這時候你的工作區間和上一次提交的內容是完全一樣的,所以你可以放心的修Bug,等到修完Bug,提交到伺服器上後,再使用git stash apply將以前一半的工作應用回來。
  • 經常有這樣的事情發生,當你正在進行專案中某一部分的工作,裡面的東西處於一個比較雜亂的狀態,而你想轉到其他分支上進行一些工作。問題是,你不想提交進行了一半的工作,否則以後你無法回到這個工作點。解決這個問題的辦法就是git stash
    命令。儲藏(stash)可以獲取你工作目錄的中間狀態——也就是你修改過的被追蹤的檔案和暫存的變更——並將它儲存到一個未完結變更的堆疊中,隨時可以重新應用。

git stash用法

1. stash當前修改

git stash會把所有未提交的修改(包括暫存的和非暫存的)都儲存起來,用於後續恢復當前工作目錄。
比如下面的中間狀態,通過git stash命令推送一個新的儲藏,當前的工作目錄就乾淨了。

$ git status
On branch master
Changes to be committed:

new file:   style.css

Changes not staged for commit:

modified:   index.html

$ git stash
Saved working directory and index state WIP on master: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage

$ git status
On branch master
nothing to commit, working tree clean

需要說明一點,stash是本地的,不會通過git push命令上傳到git server上。
實際應用中推薦給每個stash加一個message,用於記錄版本,使用git stash save取代git stash命令。示例如下:

$ git stash save "test-cmd-stash"
Saved working directory and index state On autoswitch: test-cmd-stash
HEAD 現在位於 296e8d4 remove unnecessary postion reset in onResume function
$ git stash list
[email protected]{0}: On autoswitch: test-cmd-stash

2. 重新應用快取的stash

可以通過git stash pop命令恢復之前快取的工作目錄,輸出如下:

$ git status
On branch master
nothing to commit, working tree clean
$ git stash pop
On branch master
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

Dropped refs/[email protected]{0} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)

這個指令將快取堆疊中的第一個stash刪除,並將對應修改應用到當前的工作目錄下。
你也可以使用git stash apply命令,將快取堆疊中的stash多次應用到工作目錄中,但並不刪除stash拷貝。命令輸出如下:

$ git stash apply
On branch master
Changes to be committed:

    new file:   style.css

Changes not staged for commit:

    modified:   index.html

3. 檢視現有stash

可以使用git stash list命令,一個典型的輸出如下:

$ git stash list
[email protected]{0}: WIP on master: 049d078 added the index file
[email protected]{1}: WIP on master: c264051 Revert "added file_size"
[email protected]{2}: WIP on master: 21d80a5 added number to log

在使用git stash apply命令時可以通過名字指定使用哪個stash,預設使用最近的stash(即[email protected]{0})。

4. 移除stash

可以使用git stash drop命令,後面可以跟著stash名字。下面是一個示例:

$ git stash list
[email protected]{0}: WIP on master: 049d078 added the index file
[email protected]{1}: WIP on master: c264051 Revert "added file_size"
[email protected]{2}: WIP on master: 21d80a5 added number to log
$ git stash drop [email protected]{0}
Dropped [email protected]{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)

或者使用git stash clear命令,刪除所有快取的stash。

5. 檢視指定stash的diff

可以使用git stash show命令,後面可以跟著stash名字。示例如下:

$ git stash show
 index.html | 1 +
 style.css | 3 +++
 2 files changed, 4 insertions(+)

在該命令後面新增-p--patch可以檢視特定stash的全部diff,如下:

$ git stash show -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* {
+  text-decoration: blink;
+}
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+<link rel="stylesheet" href="style.css"/>

6. 從stash建立分支

如果你儲藏了一些工作,暫時不去理會,然後繼續在你儲藏工作的分支上工作,你在重新應用工作時可能會碰到一些問題。如果嘗試應用的變更是針對一個你那之後修改過的檔案,你會碰到一個歸併衝突並且必須去化解它。如果你想用更方便的方法來重新檢驗你儲藏的變更,你可以執行 git stash branch,這會建立一個新的分支,檢出你儲藏工作時的所處的提交,重新應用你的工作,如果成功,將會丟棄儲藏。

$ git stash branch testchanges
Switched to a new branch "testchanges"
# On branch testchanges
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#      modified:   index.html
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   lib/simplegit.rb
#
Dropped refs/[email protected]{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)

這是一個很棒的捷徑來恢復儲藏的工作然後在新的分支上繼續當時的工作。

7. 暫存未跟蹤或忽略的檔案

預設情況下,git stash會快取下列檔案:

  • 新增到暫存區的修改(staged changes)
  • Git跟蹤的但並未新增到暫存區的修改(unstaged changes)

但不會快取一下檔案:

  • 在工作目錄中新的檔案(untracked files)
  • 被忽略的檔案(ignored files)

git stash命令提供了引數用於快取上面兩種型別的檔案。使用-u或者--include-untracked可以stash untracked檔案。使用-a或者--all命令可以stash當前目錄下的所有修改。

至於git stash的其他命令建議參考Git manual。