Pro Git --- 讀書筆記 (Chaptero4)
互動式暫存
git add -i
- 進入互動式終端,輸入相應指令,可以暫存檔案、取消暫存檔案、暫存檔案的一部分、新增未被追蹤的檔案、顯示暫存內容的區別
貯藏與清理
-
git stash
指令會處理工作目錄的髒狀態,即跟蹤檔案的修改與暫存的改動,然後將未完成的修改儲存到一個棧上,而你可以在任何時候重新應用這些改動(甚至在不同的分支上) -
檢視貯藏的資訊
git stash list
- 將剛剛貯藏的工作重新應用
git stash apply
- 應用一個更加舊的貯藏
git stash apply stash@{<num>}
-
但是之前暫存的檔案沒有重新暫存,這時候需要在指令後面加入
--index
-
應用選項只是還原,但是stash上還有它,需要手動刪除
git stash drop stash@{<num>}
- 也可以應用並丟棄
git stash pop
-
預設是不會貯藏未跟蹤檔案,需要加上
--include-untracked
或-u
選項 -
從貯藏建立一個分支,會應用成功後丟棄貯藏
git stash branch <branch>
修改最後一次提交
git commit --amend
- 修正會改變提交的校驗和,類似於一個小的變基,如果已經推送了,那麼就不要修正了
重置揭密
- 以Git的思維框架來管理三棵不同的樹
樹 | 用途 |
---|---|
HEAD | 上一次提交的快照,下一次提交的父結點 |
INDEX | 預期的下一次提交的快照 |
Working Directory | 沙盒 |
- HEAD是當前分支引用的指標,它總是指向該分支上的最後一次提交
- INDEX是預期的下一次提交,可以將該概念引用為Git的“暫存區”
- 工作目錄或者工作區。另外兩棵樹以一種高效但並不直觀的方式,將它們的內容儲存在.git資料夾中,工作目錄會將它們解包為實際的檔案以便編輯,可以把工作目錄當作沙盒,在將修改提交到暫存區並記錄到歷史之前,可以隨意修改
重置的作用
- 重置之前
- 移動HEAD,reset做的第一件事是移動HEAD的指向,這與改變HEAD自身不同(這是checkout所做的),reset移動HEAD指向的分支,這意味著如果HEAD設定為master分支,執行
git reset 9e5e6a4
無論呼叫哪一種形式的帶有一個提交的reset,首先都會嘗試這樣做,使用--soft
,它將僅僅停在那兒
這個本質上是撤銷了上一次git commit
指令,當reset
回來時,其實就是把該分支移動回原來的位置,而不會改變索引和工作目錄,現在可以更新索引並再次git commit
來完成git commit --amend
所要做的事情了
- 更新索引(--mixed),接下來
reset
將會用HEAD指向的當前快照更新索引
如果指定--mixed
選項,這也是預設選項,那麼reset
會停留在這裡;所以這個階段發生的事情是,會撤銷上一次提交,然後取消暫存的所有的東西,於是,這相當於我們會回滾到git commit
和git add
之前
- 更新工作目錄(--hard),
reset
要做的第三件事就是讓工作目錄看起來像索引
現在,reset
會撤銷提交、撤銷add、撤銷修改
通過路徑重置
當指定reset的作用路徑之後,它將會跳過第一步,並且將它的作用範圍限定為指定的檔案或檔案集合。因為HEAD只是一個指標,無法讓它同時指向兩個提交中的各自一部分。不過索引和工作目錄可以部分更新,所以重置可以繼續2、3步
git reset xxx.txt
等價於
git reset --mixed HEAD xxx.txt
- 該指令將會移動HEAD分支的指向(已跳過),讓索引看起來像HEAD,所以它本質上只是將xxx.txt從HEAD複製到索引中,其實就是取消暫存檔案的效果
我們也可以指定具體的一個提交來拉取該檔案的對應版本
git reset eb43bf xxx.txt
檢出(checkout)
該命令於reset
之間的區別,在於是否給該命令傳遞一個檔案路徑
不帶路徑
git checkout <branch>
git reset --hard <branch>
- 這兩個命令的效果非常相似,都會更新所有的三棵樹使其和某branch一樣
- 首先,於
reset
不同,checkout對工作目錄是安全的,它會通過檢查來確保不會將已更改的檔案弄丟。 - 還有就是,checkout只會移動HEAD自身來指向另一個分支
- 首先,於
帶路徑
當指令帶檔案路徑,效果和reset
一樣不會移動HEAD
git reset --hard <branch> file
git checkout file
- 索引和工作目錄的指定檔案都會更新為特定版本,但是HEAD不會移動
資料恢復
在reset --hard
指令下,可以將HEAD回退到舊的提交中,而之前的提交就沒有其他的分支指向了,變成了遊離的提交
-
git reflog
指令,當在工作中,Git會默默地記錄每一次你改變HEAD時的值,每一次改變分支或者提交時,reflog都會被更新 - 或者
git log -g
指令,可以更加詳細地檢視到reflog - 當得知遊離的那個commit-hash之後,就可以建立一個分支來指向這個commit
git branch <branch> <commit>
- 還有一種情況,當因為某種原因,reflog沒有了這些記錄,那需要別的工具來尋找那個丟失的commit
-
git fsck
工具,這將會檢查資料庫的完整性,當加上--full
選項之後,將會顯示出所有沒有被其他物件指向的物件("dangling commit"就是丟失的那個提交)