git reset 命令原理

git reset 命令原理


本文摘抄自《Pro Git》

git如何管理版本

認識git

git中有HEAD、Index和working Directory下表是他們的用途

名稱 用途
HEAD 上一次提交的快照,下一次提交的父結點
Index 預期的s下一次提交的快照,可以理解爲暫存區
Working Directory 工作目錄

  HEAD 是當前分支引用的指針,它總是指向該分支上的最後一次提交.
  Indox是預期的下一次提交。 也就是指向 Git 的 “暫存區域”,這就是當你運行 git commit 時 Git 看起來的樣子。
  working directory 會將.git文件夾中的內容解包爲實際的文件以便編輯,

git的工作流程

  git主要是操縱上述三個地方來實現其版本管理的功能的
在這裏插入圖片描述  下面我們來一步一步實現這個過程:

step1: 創建git

  假設我們進入到一個新目錄,其中有一個文件。 我們稱其爲該文件的 v1 版本,將它標記爲藍色。 現在運行 git init,這會創建一個 Git 倉庫,其中的 HEAD 引用指向未創建的分支(master 還不存在)。
在這裏插入圖片描述  此時,只有工作目錄有內容

step2: 向索引中添加內容

  現在我們想要提交這個文件,所以用git add來獲取工作目錄中的內容,並將其複製到索引中
在這裏插入圖片描述

step3: 提交當前版本

  運行git commit,它會取得索引中的內容並將它保存爲一個永久的快照,然後創建一個指向該快照的提交對象,最後更新 master 來指向本次提交在這裏插入圖片描述  現在我們來運行一下git status 命令發現沒有任何改動,這是因爲現在這三個地方的文件是相同的

step4: 對文件做改動

  現在我們想要對文件進行修改然後提交它。 我們將會經歷同樣的過程;首先在工作目錄中修改文件。 我們稱其爲該文件的 v2 版本,並將它標記爲紅色。在這裏插入圖片描述  如果現在運行 git status,我們會看到文件顯示在 “Changes not staged for commit,” 下面並被標記爲紅色,因爲該條目在索引與工作目錄之間存在不同。

step5: 將新修改加入暫存區

  我們運行 git add 來將它暫存到索引中
在這裏插入圖片描述
  此時,由於索引和 HEAD 不同,若運行 git status 的話就會看到 “Changes to be committed” 下的該文件變爲綠色 ——也就是說,現在預期的下一次提交與上一次提交不同

step6: 提交新修改

  我們運行 git commit 來完成提交在這裏插入圖片描述  現在我們來運行一下git status 命令發現沒有任何改動,這是因爲現在這三個地方的文件是相同的

  以上就是git對版本控制的工作流程以及各個流程階段工作目錄,暫存區和本地倉庫的狀態

git的分支切換和克隆流程

  切換分支或克隆的過程也類似。 當檢出一個分支時,它會修改 HEAD 指向新的分支引用,將 索引 填充爲該次提交的快照,然後將 索引 的內容複製到 工作目錄 中

重置

  知道了git的工作流程,現在我們可以來看一下git是如何重置的.
  假設我們再次修改了 file.txt 文件並第三次提交它。 現在的歷史看起來是這樣的:在這裏插入圖片描述

step1: 移動HEAD(–soft)

   reset做的第一件事是移動 HEAD 的指向. (這與checkout改變 HEAD 自身是不同)
   此時本地的狀態如下圖所示

在這裏插入圖片描述   該命令等同與git reset --soft HEAD~如圖,它本質上是撤銷了上一次 git commit 命令。 當你在運行 git commit 時,Git 會創建一個新的提交,並移動 HEAD 所指向的分支來使其指向該提交。 當你將它 reset 退回 HEAD~(HEAD 的父結點)時,其實就是把該分支移動回原來的位置,而不會改變索引和工作目錄
   如果此時你運行git status命令,你會看到如下輸出在這裏插入圖片描述你現在可以直接使用git commit 將其提交

step2: 更新索引(–mixed)

   接下來,reset 會用 HEAD 指向的當前快照的內容來更新索引
在這裏插入圖片描述   git在上一步的基礎上,取消了暫存區的所有東西,於是,我們回滾到了上次commit之後.
   此時運行git status會看到如下輸出:在這裏插入圖片描述   reset 命令默認就是執行git reset --mixed HEAD~ 所以如果你運行git reset commitID,git會爲你清空暫存區並將HEAD指針指向commitID的位置.

step3: 更新工作目錄(–hard)

   如果你使用–hard選項,那麼git會爲你更新工作目錄
在這裏插入圖片描述
   必須注意,–hard 標記是 reset 命令唯一的危險用法,它也是 Git 會真正地銷燬數據的僅有的幾個操作之一。 其他任何形式的 reset 調用都可以輕鬆撤消,但是 --hard 選項不能,因爲它強制覆蓋了工作目錄中的文件。 在這種特殊情況下,我們的 Git 數據庫中的一個提交內還留有該文件的 v3 版本,我們可以通過 reflog 來找回它。但是若該文件還未提交,Git 仍會覆蓋它從而導致無法恢復.

總結

   在使用reset命令時,你可以通過指定參數來選擇你想要回滾的位置

  1. 移動該分支中HEAD的指向,保留暫存區和工作目錄中的數據 (–soft)
  2. 移動該分支中HEAD的指向,只保留工作目錄中的數據(–mixed)
  3. 移動該分支中HEAD的指向,清空暫存區和工作目錄(–hard)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章