1. 程式人生 > 其它 >Pro Git --- 讀書筆記 (Chaptero4)

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資料夾中,工作目錄會將它們解包為實際的檔案以便編輯,可以把工作目錄當作沙盒,在將修改提交到暫存區並記錄到歷史之前,可以隨意修改

重置的作用

  • 重置之前
  1. 移動HEAD,reset做的第一件事是移動HEAD的指向,這與改變HEAD自身不同(這是checkout所做的),reset移動HEAD指向的分支,這意味著如果HEAD設定為master分支,執行git reset 9e5e6a4
    這會使master指向9e5e6a4

無論呼叫哪一種形式的帶有一個提交的reset,首先都會嘗試這樣做,使用--soft,它將僅僅停在那兒
這個本質上是撤銷了上一次git commit指令,當reset回來時,其實就是把該分支移動回原來的位置,而不會改變索引和工作目錄,現在可以更新索引並再次git commit來完成git commit --amend所要做的事情了

  1. 更新索引(--mixed),接下來reset將會用HEAD指向的當前快照更新索引

如果指定--mixed選項,這也是預設選項,那麼reset會停留在這裡;所以這個階段發生的事情是,會撤銷上一次提交,然後取消暫存的所有的東西,於是,這相當於我們會回滾到git commitgit add之前

  1. 更新工作目錄(--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一樣
    1. 首先,於reset不同,checkout對工作目錄是安全的,它會通過檢查來確保不會將已更改的檔案弄丟。
    2. 還有就是,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"就是丟失的那個提交)