7.3 儲藏與清理

2018-02-24 15:22 更新

儲藏與清理

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

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

儲藏工作

為了演示,進(jìn)入項目并改動幾個文件,然后可能暫存其中的一個改動。 如果運行?git status,可以看到有改動的狀態(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)在想要切換分支,但是還不想要提交之前的工作;所以儲藏修改。 將新的儲藏推送到棧上,運行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

在這時,你能夠輕易地切換分支并在其他地方工作;你的修改被存儲在棧上。 要查看儲藏的東西,可以使用?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

在本例中,有兩個之前做的儲藏,所以你接觸到了三個不同的儲藏工作。 可以通過原來 stash 命令的幫助提示中的命令將你剛剛儲藏的工作重新應(yīng)用:git stash apply。 如果想要應(yīng)用其中一個更舊的儲藏,可以通過名字指定它,像這樣:git stash apply stash@{2}。 如果不指定一個儲藏,Git 認(rèn)為指定的是最近的儲藏:

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

文件的改動被重新應(yīng)用了,但是之前暫存的文件卻沒有重新暫存。 想要那樣的話,必須使用?--index?選項來運行?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)用選項只會嘗試應(yīng)用暫存的工作 - 在堆棧上還有它。 可以運行?git stash drop?加上將要移除的儲藏的名字來移除它:

$ 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)

也可以運行?git stash pop?來應(yīng)用儲藏然后立即從棧上扔掉它。

創(chuàng)造性的儲藏

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

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

$ 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

另一個經(jīng)常使用儲藏來做的事情是像儲藏跟蹤文件一樣儲藏未跟蹤文件。 默認(rèn)情況下,git stash只會儲藏已經(jīng)在索引中的文件。 如果指定?--include-untracked?或?-u?標(biāo)記,Git 也會儲藏任何創(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 不會儲藏所有修改過的任何東西,但是會交互式地提示哪些改動想要儲藏、哪些改動需要保存在工作目錄中。

$ 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

從儲藏創(chuàng)建一個分支

如果儲藏了一些工作,將它留在那兒了一會兒,然后繼續(xù)在儲藏的分支上工作,在重新應(yīng)用工作時可能會有問題。 如果應(yīng)用嘗試修改剛剛修改的文件,你會得到一個合并沖突并不得不解決它。 如果想要一個輕松的方式來再次測試儲藏的改動,可以運行?git stash branch?創(chuàng)建一個新分支,檢出儲藏工作時所在的提交,重新在那應(yīng)用工作,然后在應(yīng)用成功后扔掉儲藏:

$ 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ù)儲藏工作并繼續(xù)工作的一個很不錯的途徑。

清理工作目錄

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

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

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

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

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

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

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

$ 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?命令將會做什么,在將?-n?改為?-f?來真正做之前總是先用?-n?來運行它做雙重檢查。 另一個小心處理過程的方式是使用?-i?或 “interactive” 標(biāo)記來運行它。

這將會以交互模式運行 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>

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

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號