git stash用於將當前工作區的修改暫存起來,就像堆棧一樣,可以隨時將某一次緩存的修改再重新應用到當前工作區。
一旦用好了這個命令,會極大提高工作效率。
直接舉例說明:
1、准備工作,首先初始化一個git倉
隨便建立一個目錄,進去,然后使用 :
$:
git init .
添加一個文件:
$: touch hello
$: git add .
$: git commit -m "first add"
2、暫存當前修改內容(git stash)
假設我們在寫一個C函數,如下:
yang@Ubuntu64:~/code/linux/git$ vim hello.c yang@Ubuntu64:~/code/linux/git$ git diff diff --git a/hello.c b/hello.c index e69de29..bdc92a5 100644 --- a/hello.c +++ b/hello.c @@ -0,0 +1,2 @@ +void func1(void) {printf("this is func1");} +void main(void) {return func1();}
調試OK,發現func1功能OK,但是應該優化一下,可能效率更高,這個時候怎么辦?
直接改func1的話,如果發現修改不合適,想回退的話很麻煩,這個時候可以用git stash將將修改暫存起來。
yang@Ubuntu64:~/code/linux/git$ git stash Saved working directory and index state WIP on master: 452b08d rename hello as hello.c HEAD is now at 452b08d rename hello as hello.c yang@Ubuntu64:~/code/linux/git$ git status On branch master nothing to commit, working directory clean
3、彈出修改內容(git stash pop)
這個時候你重新編寫func1, 發現效果不好,后悔了,於是可以用git stash pop命令,彈出剛才的內容(注意先用git checkout . 清空工作區)
yang@Ubuntu64:~/code/linux/git$ vim hello.c yang@Ubuntu64:~/code/linux/git$ git diff diff --git a/hello.c b/hello.c index e69de29..9c5bff3 100644 --- a/hello.c +++ b/hello.c @@ -0,0 +1 @@ +some bad chenges.... yang@Ubuntu64:~/code/linux/git$ git checkout . yang@Ubuntu64:~/code/linux/git$ git stash pop On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: hello.c no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (208ca2e2c0c455da554986a6770a74ad0de5b1e0) yang@Ubuntu64:~/code/linux/git$ git diff diff --git a/hello.c b/hello.c index e69de29..bdc92a5 100644 --- a/hello.c +++ b/hello.c @@ -0,0 +1,2 @@ +void func1(void) {printf("this is func1");} +void main(void) {return func1();}
注意,git stash pop 彈出成功后,暫存列表里面就沒有了,如果當前工作區不干凈,彈出時有沖突,則暫存列表會繼續保留修改。
4、可以保存多個修改
假設你在實現一個功能,有好幾種算法可以實現,你想逐個嘗試看效果。
現在你在func1中實現了一種方法,准備嘗試寫func2,用另一種方法。
那么可以將func1的修改入棧,去寫fun2,等fun2寫好后,你又想試試func3,那么沒關系,可以用同樣的方法保存func2的修改:
yang@Ubuntu64:~/code/linux/git$ git diff diff --git a/hello.c b/hello.c index e69de29..bdc92a5 100644 --- a/hello.c +++ b/hello.c @@ -0,0 +1,2 @@ +void func1(void) {printf("this is func1");} +void main(void) {return func1();} yang@Ubuntu64:~/code/linux/git$ git stash Saved working directory and index state WIP on master: 452b08d rename hello as hello.c HEAD is now at 452b08d rename hello as hello.c yang@Ubuntu64:~/code/linux/git$ git status On branch master nothing to commit, working directory clean yang@Ubuntu64:~/code/linux/git$ vim hello.c yang@Ubuntu64:~/code/linux/git$ git diff diff --git a/hello.c b/hello.c index e69de29..7fd0a13 100644 --- a/hello.c +++ b/hello.c @@ -0,0 +1,2 @@ +void func2(void) {printf("this is func2");} +void main(void) {return func2();} yang@Ubuntu64:~/code/linux/git$ git stash Saved working directory and index state WIP on master: 452b08d rename hello as hello.c HEAD is now at 452b08d rename hello as hello.c yang@Ubuntu64:~/code/linux/git$ git status On branch master nothing to commit, working directory clean
5、查看保存的內容列表(git stash list)
現在我們保存了兩個修改,一個func1,一個func2,可以通過git stash list去查看保存內容列表:
yang@Ubuntu64:~/code/linux/git$ git stash list stash@{0}: WIP on master: 452b08d rename hello as hello.c stash@{1}: WIP on master: 452b08d rename hello as hello.c
可以清楚的看到這兩次修改,stash@{0}和stash@{1}, 那么哪個對應func1,哪個對應func2的修改呢?
這時我們需要使用git stash show stash@{X}命令來查看,其中‘X’表示列表號。
yang@Ubuntu64:~/code/linux/git$ git show stash@{0} commit 72e6a391bcad186ab24676aa1db8d5831c99cec9 Merge: 452b08d 6c95c30 Author: NickYang <yang@Ubuntu64> Date: Sat Mar 12 19:56:18 2016 +0800 WIP on master: 452b08d rename hello as hello.c diff --cc hello.c index e69de29,e69de29..7fd0a13 --- a/hello.c +++ b/hello.c @@@ -1,0 -1,0 +1,2 @@@ ++void func2(void) {printf("this is func2");} ++void main(void) {return func2();} yang@Ubuntu64:~/code/linux/git$ git show stash@{1} commit 7fcca4b66640c51ca76e637df03264b7c41885be Merge: 452b08d 1c37881 Author: NickYang <yang@Ubuntu64> Date: Sat Mar 12 19:54:35 2016 +0800 WIP on master: 452b08d rename hello as hello.c diff --cc hello.c index e69de29,e69de29..bdc92a5 --- a/hello.c +++ b/hello.c @@@ -1,0 -1,0 +1,2 @@@ ++void func1(void) {printf("this is func1");} ++void main(void) {return func1();}
發現stash@{0}對應func2的修改, stash@{1}對應func1的修改,原來新入棧的修改,其代號為0,循環命名。
6、應用任意一次修改到當前目錄(git apply stash@{x})
如果現在又想回到func1的修改,怎么辦呢?在工作區干凈的情況下,要使用git stash apply stash@{1}。
注意這時不能使用git stash pop, 它將最棧頂,即stash@{0}的修改彈出來,而func1現在已經是stash@{1}了。
yang@Ubuntu64:~/code/linux/git$ git stash apply stash@{1} On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: hello.c no changes added to commit (use "git add" and/or "git commit -a") yang@Ubuntu64:~/code/linux/git$ git diff diff --git a/hello.c b/hello.c index e69de29..bdc92a5 100644 --- a/hello.c +++ b/hello.c @@ -0,0 +1,2 @@ +void func1(void) {printf("this is func1");} +void main(void) {return func1();}
可見git stash apply可以將列表中任何一次修改應用到當前工作區,我們再次git stash list一把:
yang@Ubuntu64:~/code/linux/git$ git stash list stash@{0}: WIP on master: 452b08d rename hello as hello.c stash@{1}: WIP on master: 452b08d rename hello as hello.c
我們發現,雖然func1的修改已經被彈出應用到當前工作區,其修改內容還繼續保留在暫存列表,並未丟棄。
當然,我們可以使用git stash drop stash@{1}來丟掉stash@{1}
7、保存時打標記(git stash save)
假設現在我們又開始嘗試寫func3, 這樣越來越多,這樣列表會越來越大,你要想搞清楚某次修改對應哪個函數,就要挨個用git stash show看一遍,很麻煩。
那么,這個時候git stash 的save參數就有用了,它可以為這次暫存做個標記,使得你用git stash list的時候顯示這些標記,方便你回憶是修改的什么:
yang@Ubuntu64:~/code/linux/git$ vim hello.c yang@Ubuntu64:~/code/linux/git$ git diff diff --git a/hello.c b/hello.c index e69de29..786c214 100644 --- a/hello.c +++ b/hello.c @@ -0,0 +1,2 @@ +void func3(void) {printf("this is func3");} +void main(void) {return func3();} yang@Ubuntu64:~/code/linux/git$ git stash save "this is func3" Saved working directory and index state On master: this is func3 HEAD is now at 452b08d rename hello as hello.c yang@Ubuntu64:~/code/linux/git$ git stash list stash@{0}: On master: this is func3 stash@{1}: WIP on master: 452b08d rename hello as hello.c stash@{2}: WIP on master: 452b08d rename hello as hello.c
我們在save后面指定一個字符串,作為提醒,這樣在git stash list查看時就能知道每一個代號對應的修改了。