Git_stash

git stash 用法

git stash用于将当前工作区的修改暂存起来,就像堆栈一样,可以随时将某一次缓存的修改再重新应用到当前工作区。
一旦用好了这个命令,会极大提高工作效率。

注意,暂存内容与分支无关。

假设你在A分支暂存了一次修改。此时,你将分支切换到B分支,然后在B分支应用你的缓存,完全没问题。

常用操作命令列表

git stash
git stash pop
git stash list
git stash show stash@{X}
git apply stash@{x}
git stash drop stash@{1}
git stash save

直接举例说明:

1、准备工作,首先初始化一个git仓

随便建立一个目录,进去,然后使用 :
$: git init .
添加一个文件:
$: touch hello
$: git add .
$: git commit -m "first add"

2、暂存当前修改内容(git stash)

假设我们在写一个C函数,如下:
$ vim hello.c 
$ 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将将修改暂存起来。
$ 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
$ git status
On branch master
nothing to commit, working directory clean

3、弹出修改内容(git stash pop)

这个时候你重新编写func1, 发现效果不好,后悔了,于是可以用git stash pop命令,弹出刚才的内容(注意先用git checkout . 清空工作区)
$ vim hello.c 
$ 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....
$ git checkout .
$ 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)
$ 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的修改:
$ git diff
diff --git a/hello.c b/hello.c
i--- 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();}
$ 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去查看保存内容列表:
$ 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’表示列表号。
$ 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();}
$ 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}了。
$ 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")
$ 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一把:
$ 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的时候显示这些标记,方便你回忆是修改的什么:
$ vim hello.c 
$ 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();}
$ 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
$ 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查看时就能知道每一个代号对应的修改了。

时间仓促,感谢泡面狂的分享

07-15 更新

场景:你想在切换分支前,将修改文件缓存。此时发现,新创建的文件无法用stash缓存。你只能缓存那些已经被Git追踪的文件。好,此时你感觉好慌,心跳加速,脸上皮肤收紧,额头开始冒汗,然后坐立不安。怎么办呢?现在将跟踪文件的修改缓存,新添加的文件没办法缓存。这种情况如果切换分支,会不会导致新添加文件的丢失?放心大胆的切换分支,那些新建的文件会完好无损的跟着你来到新的分支。

08-05

场景:你一不小心在同一批修改中修改了多个需求或者bug。然后你想将其中一个需求或者bug的修改缓存,注意,这里时缓存一部分你的修改,而其余部分的修改代码仍在代码修改区。怎么做呢?
做法:
1,将不需要缓存的文件add到暂存区
2,使用git stash save --keep-index '这里是关于本次缓存的简短标记,有利于区分不同的缓存,最好养成添加缓存时加标记的习惯'。
这样操作后,你修改区的文件就加入了缓存区。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355