7.3 儲(chǔ)藏與清理

2018-02-24 15:22 更新

儲(chǔ)藏與清理

有時(shí),當(dāng)你在項(xiàng)目的一部分上已經(jīng)工作一段時(shí)間后,所有東西都進(jìn)入了混亂的狀態(tài),而這時(shí)你想要切換到另一個(gè)分支做一點(diǎn)別的事情。 問題是,你不想僅僅因?yàn)檫^會(huì)兒回到這一點(diǎn)而為做了一半的工作創(chuàng)建一次提交。 針對(duì)這個(gè)問題的答案是?git stash?命令。

儲(chǔ)藏會(huì)處理工作目錄的臟的狀態(tài) - 即,修改的跟蹤文件與暫存改動(dòng) - 然后將未完成的修改保存到一個(gè)棧上,而你可以在任何時(shí)候重新應(yīng)用這些改動(dòng)。

儲(chǔ)藏工作

為了演示,進(jìn)入項(xiàng)目并改動(dòng)幾個(gè)文件,然后可能暫存其中的一個(gè)改動(dòng)。 如果運(yùn)行?git status,可以看到有改動(dòng)的狀態(tài):

$ git status
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)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   lib/simplegit.rb

現(xiàn)在想要切換分支,但是還不想要提交之前的工作;所以儲(chǔ)藏修改。 將新的儲(chǔ)藏推送到棧上,運(yùn)行git stash?或?git stash save

$ 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í),你能夠輕易地切換分支并在其他地方工作;你的修改被存儲(chǔ)在棧上。 要查看儲(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è)之前做的儲(chǔ)藏,所以你接觸到了三個(gè)不同的儲(chǔ)藏工作。 可以通過原來 stash 命令的幫助提示中的命令將你剛剛儲(chǔ)藏的工作重新應(yīng)用:git stash apply。 如果想要應(yīng)用其中一個(gè)更舊的儲(chǔ)藏,可以通過名字指定它,像這樣:git stash apply stash@{2}。 如果不指定一個(gè)儲(chǔ)藏,Git 認(rèn)為指定的是最近的儲(chǔ)藏:

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

可以看到 Git 重新修改了當(dāng)你保存儲(chǔ)藏時(shí)撤消的文件。 在本例中,當(dāng)嘗試應(yīng)用儲(chǔ)藏時(shí)有一個(gè)干凈的工作目錄,并且嘗試將它應(yīng)用在保存它時(shí)所在的分支;但是有一個(gè)干凈的工作目錄與應(yīng)用在同一分支并不是成功應(yīng)用儲(chǔ)藏的充分必要條件。 可以在一個(gè)分支上保存一個(gè)儲(chǔ)藏,切換到另一個(gè)分支,然后嘗試重新應(yīng)用這些修改。 當(dāng)應(yīng)用儲(chǔ)藏時(shí)工作目錄中也可以有修改與未提交的文件 - 如果有任何東西不能干凈地應(yīng)用,Git 會(huì)產(chǎn)生合并沖突。

文件的改動(dòng)被重新應(yīng)用了,但是之前暫存的文件卻沒有重新暫存。 想要那樣的話,必須使用?--index?選項(xiàng)來運(yùn)行?git stash apply?命令,來嘗試重新應(yīng)用暫存的修改。 如果已經(jīng)那樣做了,那么你將回到原來的位置:

$ git stash apply --index
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#      modified:   index.html
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   lib/simplegit.rb
#

應(yīng)用選項(xiàng)只會(huì)嘗試應(yīng)用暫存的工作 - 在堆棧上還有它。 可以運(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?來應(yīng)用儲(chǔ)藏然后立即從棧上扔掉它。

創(chuàng)造性的儲(chǔ)藏

有幾個(gè)儲(chǔ)藏的變種可能也很有用。 第一個(gè)非常流行的選項(xiàng)是?stash save?命令的?--keep-index?選項(xiàng)。 它告訴 Git 不要儲(chǔ)藏任何你通過 git add 命令已暫存的東西。

當(dāng)你做了幾個(gè)改動(dòng)并只想提交其中的一部分,過一會(huì)兒再回來處理剩余改動(dòng)時(shí),這個(gè)功能會(huì)很有用。

$ git status -s
M  index.html
 M lib/simplegit.rb

$ git stash --keep-index
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file

$ git status -s
M  index.html

另一個(gè)經(jīng)常使用儲(chǔ)藏來做的事情是像儲(chǔ)藏跟蹤文件一樣儲(chǔ)藏未跟蹤文件。 默認(rèn)情況下,git stash只會(huì)儲(chǔ)藏已經(jīng)在索引中的文件。 如果指定?--include-untracked?或?-u?標(biāo)記,Git 也會(huì)儲(chǔ)藏任何創(chuàng)建的未跟蹤文件。

$ git status -s
M  index.html
 M lib/simplegit.rb
?? new-file.txt

$ git stash -u
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file

$ git status -s
$

最終,如果指定了?--patch?標(biāo)記,Git 不會(huì)儲(chǔ)藏所有修改過的任何東西,但是會(huì)交互式地提示哪些改動(dòng)想要儲(chǔ)藏、哪些改動(dòng)需要保存在工作目錄中。

$ git stash --patch
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 66d332e..8bb5674 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -16,6 +16,10 @@ class SimpleGit
         return `#{git_cmd} 2>&1`.chomp
       end
     end
+
+    def show(treeish = 'master')
+      command("git show #{treeish}")
+    end

 end
 test
Stash this hunk [y,n,q,a,d,/,e,?]? y

Saved working directory and index state WIP on master: 1b65b17 added the index file

從儲(chǔ)藏創(chuàng)建一個(gè)分支

如果儲(chǔ)藏了一些工作,將它留在那兒了一會(huì)兒,然后繼續(xù)在儲(chǔ)藏的分支上工作,在重新應(yīng)用工作時(shí)可能會(huì)有問題。 如果應(yīng)用嘗試修改剛剛修改的文件,你會(huì)得到一個(gè)合并沖突并不得不解決它。 如果想要一個(gè)輕松的方式來再次測(cè)試儲(chǔ)藏的改動(dòng),可以運(yùn)行?git stash branch?創(chuàng)建一個(gè)新分支,檢出儲(chǔ)藏工作時(shí)所在的提交,重新在那應(yīng)用工作,然后在應(yīng)用成功后扔掉儲(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
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   lib/simplegit.rb
#
Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)

這是在新分支輕松恢復(fù)儲(chǔ)藏工作并繼續(xù)工作的一個(gè)很不錯(cuò)的途徑。

清理工作目錄

對(duì)于工作目錄中一些工作或文件,你想做的也許不是儲(chǔ)藏而是移除。?git clean?命令會(huì)幫你做這些事。

有一些通用的原因比如說為了移除由合并或外部工具生成的東西,或是為了運(yùn)行一個(gè)干凈的構(gòu)建而移除之前構(gòu)建的殘留。

你需要謹(jǐn)慎地使用這個(gè)命令,因?yàn)樗辉O(shè)計(jì)為從工作目錄中移除未被追蹤的文件。 如果你改變主意了,你也不一定能找回來那些文件的內(nèi)容。 一個(gè)更安全的選項(xiàng)是運(yùn)行?git stash --all?來移除每一樣?xùn)|西并存放在棧中。

你可以使用git clean命令去除冗余文件或者清理工作目錄。 使用git clean -f -d命令來移除工作目錄中所有未追蹤的文件以及空的子目錄。?-f?意味著?強(qiáng)制?或 “確定移除”。

如果只是想要看看它會(huì)做什么,可以使用?-n?選項(xiàng)來運(yùn)行命令,這意味著 “做一次演習(xí)然后告訴你將要?移除什么”。

$ git clean -d -n
Would remove test.o
Would remove tmp/

默認(rèn)情況下,git clean?命令只會(huì)移除沒有忽略的未跟蹤文件。 任何與?.gitiignore?或其他忽略文件中的模式匹配的文件都不會(huì)被移除。 如果你也想要移除那些文件,例如為了做一次完全干凈的構(gòu)建而移除所有由構(gòu)建生成的?.o?文件,可以給 clean 命令增加一個(gè)?-x?選項(xiàng)。

$ git status -s
 M lib/simplegit.rb
?? build.TMP
?? tmp/

$ git clean -n -d
Would remove build.TMP
Would remove tmp/

$ git clean -n -d -x
Would remove build.TMP
Would remove test.o
Would remove tmp/

如果不知道?git clean?命令將會(huì)做什么,在將?-n?改為?-f?來真正做之前總是先用?-n?來運(yùn)行它做雙重檢查。 另一個(gè)小心處理過程的方式是使用?-i?或 “interactive” 標(biāo)記來運(yùn)行它。

這將會(huì)以交互模式運(yùn)行 clean 命令。

$ git clean -x -i
Would remove the following items:
  build.TMP  test.o
*** Commands ***
    1: clean                2: filter by pattern    3: select by numbers    4: ask each             5: quit
    6: help
What now>

這種方式下可以分別地檢查每一個(gè)文件或者交互地指定刪除的模式。

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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)