阿川私房教材:學程式,拿 offer!

63 個專案實戰,直接上手!
無需補習,按步驟打造你的面試作品。

立即解鎖你的轉職秘笈

標題: git reset --解釋

發表:真實

封面圖:https://thepracticaldev.s3.amazonaws.com/i/15wzb8t5310txcukt7t9.png

標籤: git, 重置

描述:「重置可能是最難理解的git 命令之一,而且還因危險而名聲不佳。這兩種說法都有充分的理由:是的,重置命令有點難以理解,並且在某些情況下在這種情況下,這可能很危險。


Reset 可能是最不被理解的 git 命令之一,而且還因危險而名聲不佳。這兩種說法都有一個合理的理由:是的,重置命令有點難以理解,在某些情況下,它可能會很危險。但是,這並不那麼難。因此,在這篇文章中,我將盡力向您展示重置命令的清晰而精煉的教程。為了簡短起見,我抽象化了一些非必要的細節並簡化了一些事情,但如果你想了解更多關於 git 的內部工作原理,你也可以查看我的理解 Git系列,了解這裡介紹的一些內容的更多細節。

Git 樹

在我們深入reset指令之前,我們需要先看一下所謂的 git 樹:工作目錄、暫存區和儲存庫。

git 閾值

從 git 的角度來看,您可以將它們視為可以進行更改的區域:

  • 工作目錄 - 檔案系統上的專案文件

  • 暫存區 - 下次提交的預覽

  • 儲存庫 - git 保存所有(過去)提交的資料儲存。

reset命令對這三個/區域進行操作,但首先,讓我們看看我們日常使用的addcommit命令如何影響這些區域。


假設我們有一個 Web 應用程式,並且我們對index.php檔案進行了一些重構。我們所做的更改反映在工作目錄中:

工作流程-1

我們可以透過執行git status來確認這一點:

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:   index.php

現在我們使用add命令將這些變更移至暫存區域:

工作流程-2

現在執行status指令會告訴我們:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
modified:   index.php

因為status指令發現我們在工作目錄和暫存區域都有相同版本的index.php文件,但在儲存庫中卻沒有。

要將其加入到此處,我們使用commit命令:

工作流程-3

現在工作目錄、暫存區和儲存庫都包含相同版本的index.php ,執行git status會告訴我們有:

nothing to commit, working tree clean

因此, status指令的工作方式是比較工作目錄、暫存區域和儲存庫中的檔案版本,如果存在不同,則存在要暫存/提交的檔案。


假設我們現在進一步重構index.php檔案並再次執行整個新增/提交週期。

現在我們的工作目錄、暫存區和儲存庫都包含了新的第二個版本的index.php檔案。

工作流程-4

但是第一個版本呢?如果您還記得,我們確實說過儲存庫保留所有先前的提交,因此index.php檔案的第一個版本仍然存在:

工作流程-5

為了追蹤我們的index.php檔案的當前版本,儲存庫有一個名為HEAD的特殊指針,它指向當前版本( status命令在將其與當前版本進行比較時僅查看HEAD指向的當前版本)暫存區的版本)。


現在我們已經了解了這些內容,我們終於可以轉到reset命令並透過操作這些區域的內容來查看它是如何運作的。

重置--軟

reset指令的第一種模式只會做一件事:

  • 移動HEAD指針。

在我們的例子中,我們將透過執行以下操作將其移至先前的提交( index.php的第一個版本): git reset --soft HEAD~1

重置軟1

git 的樹現在看起來像這樣:

重置軟2

如果我們執行git status我們會看到一條熟悉的訊息:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
modified:   index.php

因此,執行git reset --soft HEAD~1基本上撤消了我們上次的提交,但該提交中包含的更改不會丟失 - 它們位於我們的暫存區域和工作目錄中。

重置-混合

reset命令的第二種模式將做兩件事:

  • 移動HEAD指針

  • 更新暫存區(使用HEAD指向的內容)

因此,第一步與--soft模式相同。第二步驟取得HEAD指向的內容(在本例中,它是index.php檔案的版本一)並將其放入暫存區。

重置混合-1

因此,在執行git reset --mixed HEAD~1後,我們的區域如下所示:

重置混合2

如果我們現在執行git status ,我們會再次看到一條熟悉的訊息:

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:   index.php

因此,執行git reset - mixed HEAD~1已經撤銷了我們上次的提交,但是這次該提交的更改(僅)在我們的工作目錄中。

重置——硬

現在是臭名昭著的困難模式。執行reset -- hard會做三件事:

  • 移動HEAD指針

  • 更新暫存區(使用HEAD指向的內容)

  • 更新工作目錄以符合暫存區域

因此,前兩個HEAD--mixed相同。

重置硬1

因此,在執行git reset --hard HEAD~1後,我們的區域如下所示:

重置硬2

執行git status將為我們提供:

nothing to commit, working tree clean

因此,執行git reset - hard HEAD~1已經撤消了我們上次的提交,並且該提交中包含的更改現在既不在我們的工作目錄中,也不在暫存區域中。但他們並沒有完全迷失。 Git 不會從存儲庫中刪除提交(實際上,有時會這樣做,但很少),因此這意味著我們的第二個版本的提交仍在存儲庫中,只是它有點難找到(您可以通過看看來追蹤它)稱為reflog 的東西)。

那麼,重置危險的名聲到底是什麼呢?嗯,在一種情況下,某些更改可能會永久丟失。考慮這樣一種情況,在第二次提交之後,您對index.php檔案進行了更多更改,但沒有暫存並提交它們:

重置硬3

現在執行git reset --hard HEAD~1

重置硬4

由於reset命令將覆蓋工作目錄的內容以匹配暫存區域(即與HEAD匹配),並且您從未暫存並提交更改(存儲庫中沒有提交這些更改),因此所有這些更改都將現在迷失在時間裡……就像雨中的淚水。

硬重置的危險在於它不是工作目錄安全性- 這意味著如果您的工作目錄中有文件更改,並且如果您執行它,這些文件更改將被覆蓋(並丟失),它不會向您發出任何警告。因此,硬重置時要(格外)小心。


現在你已經有它了: reset指令。我希望我很好地解釋了它,並且你會同意這畢竟不那麼難。而且,是的,它可能很危險,但前提是與--hard選項一起使用。

如一開始所說,如果你想了解更多 git 的內部工作原理,你可以查看我的《理解 Git》系列,如果你想更深入地了解reset命令,你可以查看 git 的Reset Demystified章節親書。

附錄:

  • 在範例中,我們使用HEAD~1作為reset指令的參數。你可能已經知道 git 中的每個提交都有一個稱為校驗和的唯一標識符,我們也可以將它用作reset命令的參數

校驗和

  • 為了使範例更簡單,我們只有一個編輯和提交的文件,實際上,我們經常提交多個文件,因此特定的提交保存多個文件的不同版本。

提交

  • 特殊的HEAD指針通常不會直接指向提交(為了簡單起見,如範例所示),而是指向一個分支指針,然後該分支指針指向特定的提交

指針


原文出處:https://dev.to/konrad_126/git-reset---explain-49bl


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。

阿川私房教材:學程式,拿 offer!

63 個專案實戰,直接上手!
無需補習,按步驟打造你的面試作品。

立即解鎖你的轉職秘笈