Git 儲(chǔ)藏(Stashing)

2018-09-27 15:50 更新

經(jīng)常有這樣的事情發(fā)生,當(dāng)你正在進(jìn)行項(xiàng)目中某一部分的工作,里面的東西處于一個(gè)比較雜亂的狀態(tài),而你想轉(zhuǎn)到其他分支上進(jìn)行一些工作。問(wèn)題是,你不想提交進(jìn)行了一半的工作,否則以后你無(wú)法回到這個(gè)工作點(diǎn)。解決這個(gè)問(wèn)題的辦法就是git stash命令。

“‘儲(chǔ)藏”“可以獲取你工作目錄的中間狀態(tài)——也就是你修改過(guò)的被追蹤的文件和暫存的變更——并將它保存到一個(gè)未完結(jié)變更的堆棧中,隨時(shí)可以重新應(yīng)用。

儲(chǔ)藏你的工作

為了演示這一功能,你可以進(jìn)入你的項(xiàng)目,在一些文件上進(jìn)行工作,有可能還暫存其中一個(gè)變更。如果你運(yùn)行 git status,你可以看到你的中間狀態(tài):

$ git status
# On branch master
# 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
#

現(xiàn)在你想切換分支,但是你還不想提交你正在進(jìn)行中的工作;所以你儲(chǔ)藏這些變更。為了往堆棧推送一個(gè)新的儲(chǔ)藏,只要運(yùn)行 git stash:

$ git stash
Saved working directory and index state \
  "WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
(To restore them type "git stash apply")

你的工作目錄就干凈了:

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

這時(shí),你可以方便地切換到其他分支工作;你的變更都保存在棧上。要查看現(xiàn)有的儲(chǔ)藏,你可以使用 git stash list:

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

在這個(gè)案例中,之前已經(jīng)進(jìn)行了兩次儲(chǔ)藏,所以你可以訪問(wèn)到三個(gè)不同的儲(chǔ)藏。你可以重新應(yīng)用你剛剛實(shí)施的儲(chǔ)藏,所采用的命令就是之前在原始的 stash 命令的幫助輸出里提示的:git stash apply。如果你想應(yīng)用更早的儲(chǔ)藏,你可以通過(guò)名字指定它,像這樣:git stash apply stash@{2}。如果你不指明,Git 默認(rèn)使用最近的儲(chǔ)藏并嘗試應(yīng)用它:

$ git stash apply
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   index.html
#      modified:   lib/simplegit.rb
#

你可以看到 Git 重新修改了你所儲(chǔ)藏的那些當(dāng)時(shí)尚未提交的文件。在這個(gè)案例里,你嘗試應(yīng)用儲(chǔ)藏的工作目錄是干凈的,并且屬于同一分支;但是一個(gè)干凈的工作目錄和應(yīng)用到相同的分支上并不是應(yīng)用儲(chǔ)藏的必要條件。你可以在其中一個(gè)分支上保留一份儲(chǔ)藏,隨后切換到另外一個(gè)分支,再重新應(yīng)用這些變更。在工作目錄里包含已修改和未提交的文件時(shí),你也可以應(yīng)用儲(chǔ)藏——Git 會(huì)給出歸并沖突如果有任何變更無(wú)法干凈地被應(yīng)用。

對(duì)文件的變更被重新應(yīng)用,但是被暫存的文件沒(méi)有重新被暫存。想那樣的話,你必須在運(yùn)行 git stash apply 命令時(shí)帶上一個(gè) --index 的選項(xiàng)來(lái)告訴命令重新應(yīng)用被暫存的變更。如果你是這么做的,你應(yīng)該已經(jīng)回到你原來(lái)的位置:

$ git stash apply --index
# On branch master
# 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
#

apply 選項(xiàng)只嘗試應(yīng)用儲(chǔ)藏的工作——儲(chǔ)藏的內(nèi)容仍然在棧上。要移除它,你可以運(yùn)行 git stash drop,加上你希望移除的儲(chǔ)藏的名字:

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

你也可以運(yùn)行 git stash pop 來(lái)重新應(yīng)用儲(chǔ)藏,同時(shí)立刻將其從堆棧中移走。

取消儲(chǔ)藏(Un-applying a Stash)

在某些情況下,你可能想應(yīng)用儲(chǔ)藏的修改,在進(jìn)行了一些其他的修改后,又要取消之前所應(yīng)用儲(chǔ)藏的修改。Git沒(méi)有提供類似于 stash unapply 的命令,但是可以通過(guò)取消該儲(chǔ)藏的補(bǔ)丁達(dá)到同樣的效果:

$ git stash show -p stash@{0} | git apply -R
同樣的,如果你沒(méi)有指定具體的某個(gè)儲(chǔ)藏,Git 會(huì)選擇最近的儲(chǔ)藏:

$ git stash show -p | git apply -R
你可能會(huì)想要新建一個(gè)別名,在你的 Git 里增加一個(gè) stash-unapply 命令,這樣更有效率。例如:

$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply

從儲(chǔ)藏中創(chuàng)建分支

如果你儲(chǔ)藏了一些工作,暫時(shí)不去理會(huì),然后繼續(xù)在你儲(chǔ)藏工作的分支上工作,你在重新應(yīng)用工作時(shí)可能會(huì)碰到一些問(wèn)題。如果嘗試應(yīng)用的變更是針對(duì)一個(gè)你那之后修改過(guò)的文件,你會(huì)碰到一個(gè)歸并沖突并且必須去化解它。如果你想用更方便的方法來(lái)重新檢驗(yàn)?zāi)銉?chǔ)藏的變更,你可以運(yùn)行 git stash branch,這會(huì)創(chuàng)建一個(gè)新的分支,檢出你儲(chǔ)藏工作時(shí)的所處的提交,重新應(yīng)用你的工作,如果成功,將會(huì)丟棄儲(chǔ)藏。

$ 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/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)

這是一個(gè)很棒的捷徑來(lái)恢復(fù)儲(chǔ)藏的工作然后在新的分支上繼續(xù)當(dāng)時(shí)的工作。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)