【學記】git stash
git stash 的使用情境為何?讓我們先看一個例子:
當修改了 working directory 後,目前的 working directory 會成為 dirty 的。
而有時候會需要在 dirty 的情況下查看之前的 commit 或 pull,此時有以下 2 種作法:
- 將 working directory 的改動 commit 起來暫存
- 使用
git stash
假設目前情境如下:
When you are in the middle of something, your boss comes in and demands that you fix something immediately.
Traditionally, you would make a commit to a temporary branch to store your changes away, and return to your original branch to make the emergency fix.
- from git stash --help
Commit 的做法
1 | hack hack hack |
Using git stash
1 | hack hack hack |
從上面的例子可以看到 git stash 相比使用 commit 再 reset 要來得簡潔許多。
由此可知,git stash 的用途就是將 local 的修改 stash(存放) 起來,之後可以拿出來使用,就像倉鼠一樣!
git stash 的 command
而 git stash 有哪些 command 呢?我們可以透過 git stash --help 查看。
以下將介紹一些常用的 command。
git stash push
git stash command 實際上就是 git stash push,想不到吧!git stash 就像是縮寫一樣。
而為什麼是叫做 push 呢?
當我們把東西 stash 起來的時候,是存放到一個 list 的結構內,我們可以透過 git stash list 查看。
1 | $ git stash list |
所以如果要將東西放上這個 list,使用的是 push。
git stash 只會將已經 tracked 的 files stash 起來,那些新 create 的 files 並不會被 stash。
如果要將 Untracked files stash 起來,需要多加一個 flag:git stash push -u,當然,只打git stash -u也可以。
git stash list
同上所述,這個 command 會將目前的 stash list print 出來。
形式如下:
1 | $ git stash list |
stash@{0} 是 stash 的代稱。
git stash pop
當我們將東西 stash 起來後,就像倉鼠一樣,將東西存放在頰囊內,是之後要拿出來吃的!
這時候就可以用到 git stash pop 這個指令,會將 list 最上面的 stash pop 出來,放到目前的 branch 上。
如果要指定某個要 pop 的 stash,可以在 git stash pop 後面加上 stash 的代稱,如下:
1 | git stash pop stash@{0} |
指定 stash 做操作的 operation 同樣適用在其他類似的 command。
git stash apply
操作同 git stash pop,不過並不會將 stash 從 stash list 移除。
git stash drop
將 stash 從 list 上直接移除,如果沒有指定哪個 stash 的話,會移除最新的 stash,也就是 stash@{0}。
進階操作
stash index
如果在原本的 working directory 中,其中有些修改已經 staged 起來,這時候如果要使用 stash,可以透過 git stash push --keep-index。
在 pop 出來的時候特別指定連 index 也要 restore 即可,如下:
1 | git stash push --keep-index |
指定哪些要 stash
透過 push 的 --patch (or -p) flag,可以在後面指定要 stash 的 file 的路徑,如下:
1 | git stash push --patch /path/to/file |
path 也可以用 regular expression 表示。
像是git stash push --patch **/to/**
此時 git 會開啟 interactive 的模式,一一確認這個 hunk(這名詞後文有解釋) 是否要 stash,如下:
1 | diff --git a/test b/test |
[y,n,q,a,d,/,e,?] 解釋如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
hunk 是一個 files 中相對應的修改,可以透過
git diff查看,一般顯示如下:
1
2
3
4
5
6
7
8
9
10
11
12 diff --git a/example.txt b/example.txt
index e69de29..d95f3ad 100644
--- a/example.txt
+++ b/example.txt
@@ -1,5 +1,5 @@
line 1
-line 2
+line 2 modified
line 3
-line 4
+line 4 modified
line 5
而如果在 git stash push --patch 後面沒有指定路徑的話,git 將會針對所有的 hunk 詢問是否要 stash。
如果想要省時間, -- 可以直接替代 --patch,用法如下:
1 | git stash push -- /path/to/file |
或者這樣也可以
1 | git stash -- /path/to/file |
如果使用 -- 指定路徑,git 將會直接 stash 起來,而不會跳出 interactive 的詢問。











