Git筆記(27) 儲藏與清理


1. 混亂的狀態

有時,當在項目的一部分上已經工作一段時間後,所有東西都進入了混亂的狀態
而這時想要切換到另一個分支做一點別的事情

問題是,不想僅僅因爲過會兒回到這一點而爲做了一半的工作創建一次提交
針對這個問題的答案是 git stash 命令

儲藏會處理工作目錄的髒的狀態
即跟蹤文件的修改與暫存的改動
然後將未完成的修改保存到一個棧上
可以在任何時候重新應用這些改動


2. 儲藏工作

爲了演示,進入項目並改動幾個文件,然後可能暫存其中的一個改動
如果運行 git status,可以看到有改動的狀態:

$ 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

現在想要切換分支,但是還不想要提交之前的工作
所以儲藏修改, 將新的儲藏推送到棧上,運行 git stashgit 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 命令的幫助提示中的 git stash apply將儲藏的工作重新應用

如果想要應用其中一個更舊的儲藏
可以通過名字指定它,像這樣:

$ git stash apply stash@{2}

如果不指定一個儲藏,Git 認爲指定的是最近的儲藏:

$ 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 重新修改了當你保存儲藏時撤消的文件

在本例中:

  1. 應用儲藏時有一個乾淨的工作目錄
  2. 應用在保存它時所在的分支

但是有一個乾淨的工作目錄與應用在同一分支並不是成功應用儲藏的充分必要條件

可以在一個分支上保存一個儲藏,切換到另一個分支,然後嘗試重新應用這些修改
當應用儲藏時工作目錄中也可以有修改與未提交的文件
如果有任何東西不能幹淨地應用,Git 會產生合併衝突

文件的改動被重新應用了,但是之前暫存的文件卻沒有重新暫存
想須使用 --index 選項來運行 git stash apply 命令,來嘗試重新應用暫存的修改
如果已經那樣做了,那麼將回到原來的位置:

$ 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

應用選項只會嘗試應用暫存的工作——在堆棧上還有它
可以運行 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 來應用儲藏然後立即從棧上扔掉它


3. 創造性的儲藏

有幾個儲藏的變種可能也很有用
第一個非常流行的選項是 stash save 命令的 --keep-index 選項

它告訴 Git 不要儲藏任何你通過 git add 命令已暫存的東西
當做了幾個改動並只想提交其中的一部分,過一會兒再回來處理剩餘改動時
這個功能會很有用

$ 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

另一個經常使用儲藏來做的事情是像儲藏跟蹤文件一樣儲藏未跟蹤文件
默認情況下,git stash 只會儲藏已經在索引中的文件
如果指定 --include-untracked-u 標記,Git 也會儲藏任何創建的未跟蹤文件

$ 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 標記,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

4. 從儲藏創建一個分支

如果儲藏了一些工作,將它留在那兒了一會兒
然後繼續在儲藏的分支上工作,在重新應用工作時可能會有問題

如果應用嘗試修改剛剛修改的文件,會得到一個合併衝突並不得不解決它
如果想要一個輕鬆的方式來再次測試儲藏的改動
可以運行 git stash branch 創建一個新分支,檢出儲藏工作時所在的提交
重新在那應用工作,然後在應用成功後扔掉儲藏:

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

這是在新分支輕鬆恢復儲藏工作並繼續工作的一個很不錯的途徑。


5. 清理工作目錄

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

有一些通用的原因比如說爲了移除由合併或外部工具生成的東西
或是爲了運行一個乾淨的構建而移除之前構建的殘留

需要謹慎地使用這個命令,因爲它被設計爲從工作目錄中移除未被追蹤的文件
如果改變主意了,也不一定能找回來那些文件的內容
一個更安全的選項是運行 git stash --all 來移除每一樣東西並存放在棧中

使用 git clean 命令去除冗餘文件或者清理工作目錄
使用 git clean -f -d 命令來移除工作目錄中所有未追蹤的文件以及空的子目錄

如果只是想要看看它會做什麼,可以使用 -n 選項來運行命令
這意味着 “做一次演習然後告訴你將要移除什麼”

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

默認情況下,只會移除沒有忽略的未跟蹤文件
任何與 .gitiignore 或其他忽略文件中的模式匹配的文件都不會被移除

如果也想要移除那些文件
例如爲了做一次完全乾淨的構建而移除所有由構建生成的 .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/

另一個小心處理過程的方式是使用 -i 或 “interactive” 標記來運行它

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

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


參考: git
以上內容,均根據git官網介紹刪減、添加和修改組成


相關推薦:

Git筆記(26) 交互式暫存
Git筆記(25) 選擇修訂版本
Git筆記(24) 維護項目
Git筆記(23) 不同角色的貢獻
Git筆記(22) 項目貢獻要點


謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章