Git命令學習之git-reset詳解

Git命令學習之git-reset詳解

git-reset的作用是重置當前分支的HEAD指針,將HEAD指針指向特定的狀態。

使用概述

git?reset?[<tree-ish>]?[--]?<pathspec> git?reset?[--pathspec-from-file=<file>?[--pathspec-file-nul]]?[<tree-ish>] git?reset?(--patch?|?-p)?[<tree-ish>]?[--]?[<pathspec>] git?reset?[--soft?|?--mixed?[-N]?|?--hard?|?--merge?|?--keep]?[<commit>]</commit></pathspec></tree-ish></tree-ish></file></pathspec></tree-ish>

前三行reset命令的作用是將指定的內容作為參考依據,然后把內容拷貝到目標的緩存區中。

就是像樹一樣的東西,git中是有很多都能組成樹的,比如commit樹或者tag樹。

最后一行reset命令的作用是將當前分支的HEAD指針指向,同時可以使用多種可選項來控制是否修改緩存區或工作區。

在以上所有的命令形式中,都是把默認作為HEAD指針。

git reset [] [–]

該方法有如下規則:

  • 會將與相匹配的路徑資源在緩存區中重置成中的狀態。不了解是什么?

  • 被提交到緩存區中的改動會被還原到工作區中。

舉個?

假設項目中有一個coffee.txt文件,文件內容如下:

卡布奇諾納瑞冰-19.9¥ 標準美式-14.9¥ 香草拿鐵-19.9¥ 生椰愛摩卡-19.9¥ ...

我們使用git的tag命令將當前的版本標記成v1.0.0(這里使用tag標簽作為)。

隨后修改coffee.txt文件,修改內容如下:

卡布奇諾納瑞冰-19.9¥?--&gt;?卡布奇諾納瑞冰-14.9¥ 標準美式-14.9¥?--&gt;?標準美式-9.9¥ 香草拿鐵-19.9¥?--&gt;?香草拿鐵-14.9¥ 生椰愛摩卡-19.9¥?--&gt;?生椰愛摩卡-14.9¥ ...

變更了coffee.txt文件后,再使用git tag打上了v1.0.1標記。

如果此時想將coffee.txt文件還原成v1.0.0版本中的文件,就可以使用git reset命令并指定為v1.0.0,操作如下:

git?reset?v1.0.0?coffee.txt

使用vscode查看緩存區的文件變動:

Git命令學習之git-reset詳解

可以看到圖中的右側的代碼改動對比,此時緩存區中的coffee.txt文件已經成功被重置成v1.0.0版本中文件的狀態(規則1)。并且此時v1.0.1已經提交到緩存區中的變動也被還原到了工作樹中(規則2)。

Git命令學習之git-reset詳解

可以看出git reset命令與git add命令作用相反,一個是將指定的資源添加到緩存區,另一個則是從緩存區中移除。并且這個命令與git restore [–source=] –staged 具有相同的作用,對restore感興趣的可以看看不了解是什么?

上面說過了,在使用reset命令后,此時緩存區中文件內容是v1.0.0的,可以配合git restore命令將緩存區中的內容還原到工作區中然后進行修改:

git?restore?coffee.txt?--staged

也可以根據需要選擇還原工作區的內容:

git?restore?coffee.txt?--worktree

git reset?[–pathspec-from-file= [–pathspec-file-nul]] []

在上面的例子中每次進行reset和restore的都是想同的路徑(coffee.txt)。因為該文件路徑比較簡單,所以每次操作都比較方便輸入。但是在一些情況下,可能需要reset比較復雜的路徑,比如項目目錄層次較深,那么很可能需要輸入一長串的路徑,這樣每次進行操作就會很麻煩,所以git提供了一個–pathspec-from-file選項,讓我們能夠直接指定一個文件,這個文件就包含了可能需要重復使用的路徑。不了解是什么?有更詳細的用法。

該文件每一行都是一個,如果有多個使用換行符作為分隔。當然也可以使用–pathspec-file-nul讓NUL作為每一個的分隔符。

git reset (–patch | -p) [] [–] []

交互式的選擇與緩存區之間的差異而產生的hunks。這些被選擇的hunks將會撤銷緩存區中的產生的修改。不了解是什么?有更詳細的–patch選項用法。

git reset [] []

該命令會把當前分支的HEAD指針指向某個,然后由決定是否同時更新緩存區或工作區的內容。默認值是–mixed,且必須是以下幾種:

–soft

工作區和緩存區中的文件變動都將被保留,然后將HEAD指針指向

還是以咖啡菜單為?,假如第一次commit到倉庫中的文件內容如下:

卡布奇諾納瑞冰-19.9¥ 標準美式-14.9¥ 香草拿鐵-19.9¥ 生椰愛摩卡-19.9¥ ...

然后做第二次commit操作,刪除標準美式,增加生椰拿鐵:

卡布奇諾納瑞冰-19.9¥ -標準美式-14.9¥ +生椰拿鐵-19.9¥ 香草拿鐵-19.9¥ 生椰愛摩卡-19.9¥ ...

在commit后,修改卡布奇諾納瑞冰的價格,添加到緩存區。再修改香草拿鐵的價格,保留在工作區:

-卡布奇諾納瑞冰-19.9¥ +卡布奇諾納瑞冰-14.9¥?//?添加到緩存區中 生椰拿鐵-19.9¥ -香草拿鐵-19.9¥ +香草拿鐵-14.9¥?//?保留在工作區 生椰愛摩卡-19.9¥ ...

此時我想保留工作區和緩存區做的改動,并且將HEAD指針指向第一次commit。這時可以使用–soft選項實現:

git?reset?HEAD^?--soft?//?這里使用HEAD^表示上一個commit,同樣也可以使用hash?id

使用git log查看當前HEAD指針確實已經指向第一個commit,第二個commit被拋棄了:

Git命令學習之git-reset詳解

同時所有的工作區和緩存區的改動都被保留了:

Git命令學習之git-reset詳解

當前只有兩次的commit,是為了方便演示–soft選項的作用。但是在實際開發中,我們可能會commit多次,尤其是在測試環境改幾個bug就要提交到發布平臺,這樣會導致很多無意義的commit。這時候就可以使用–soft選項,重置HEAD到指定的只保留一到兩個重要的commit。

–mixed

重置緩存區,但是會保留工作區的內容,這是的默認值。

相信在理解了–soft作用后,理解–mixed不難,上面例子中如果是使用–mixed那么最終結果如下:

Git命令學習之git-reset詳解

該選項會重置緩存區,但是保留工作區的改動,并將當前指針指向

–hard

重置緩存區和工作區中的所有的變動,并且將指針指向

–hard更加的簡單粗暴,我們將–soft例子改為–hard來查看結果:

Git命令學習之git-reset詳解

如圖所示,工作區和緩存區的內容都被重置了。不止是如此,就連Untracked文件同樣也會被刪除。

–merge

該選項的作用,看字面意思就知道大概就是把當前分支和指定的進行合并,規則如下:

  • 重置緩存區,任何已經添加到緩存區的改動都將被拋棄

  • 如果和HEAD之間有文件存在不同(這個不同指的是文件被刪除或者新增),那么將會把該文件重置成中的狀態(新增或刪除)。

  • 如果和HEAD之間有文件存在不同(這個不同是指文件內容的不同),且此時工作區也存在未提交的改動,那么本次的reset將會被終止。

  • 如果一個文件在和HEAD中完全相同,但是它的工作區存與緩存區存在著不同(也就是改動未提交到緩存區),那么該文件在工作區的改動在重置之后就會被保留。

我們舉個例子來驗證一下以上列出的規則,假設此時的咖啡店項目有如下的幾個commit。

第一個commit和文件內容如下:

Git命令學習之git-reset詳解

第一個commit中只有一個coffee.txt菜單文件,此時如果咖啡店引進了新品種開始賣果汁,那么就需要新增果汁菜單文件fruits.txt,于是就有了第二個commit:

Git命令學習之git-reset詳解

此時我們做一些改動來驗證1,2,4這幾點的規則,改動后的文件如下:

Git命令學習之git-reset詳解

首先修改coffee.txt文件,新增一款生椰拿鐵咖啡,保留在工作區中。然后增加咖啡豆菜單文件beans.txt,將其添加到緩存區中。

假設因需求變動,咖啡豆菜單文件在緩存區中需要清除,果汁菜單文件需要刪除,只有咖啡菜單中新增的生椰拿鐵的改動需要保留。那么就可以使用git reset –merge將HEAD和commit-1進行合并,操作如下:

git?reset?--merge?HEAD^

結果如下:

Git命令學習之git-reset詳解

執行命令reset命令產生了如下效果:

  • 將當前HEAD指針指向了commit-1
  • 將緩存區中的beans.txt文件拋棄(規則1)
  • HEAD(commit-2)和commit-1中的fruits.txt文件存在不同(commit-2中新增fruits.txt),所以會將fruits.txt刪除(規則2)
  • coffee.txt文件新增生椰拿鐵的改動被保留在工作區中(規則4)

再來驗證一下第3點規則,假設咖啡店項目此時第一個commit如下:

Git命令學習之git-reset詳解

接下去同樣新增水果茶菜單,然后再修改coffee.txt文件,第二個commit如下:

Git命令學習之git-reset詳解

然后在HEAD中再修改coffee.txt文件,刪除掉標準美式品種:

Git命令學習之git-reset詳解

此時,如果我們再使用git reset –merge HEAD^就無法再進行重置,該操作會被git終止(規則3)。并且控制臺會進行報錯提示:

Git命令學習之git-reset詳解

–keep

該選參的作用和–merge相似,唯一的區別就是緩存區中被重置的會被保留在工作區中。

構造如下第一個commit:

Git命令學習之git-reset詳解

改造第二個commit:

Git命令學習之git-reset詳解

在HEAD中進行修改

Git命令學習之git-reset詳解

使用git reset –keep命令:

Git命令學習之git-reset詳解

從結果上來看,只有fruits.txt文件被刪除了,beans.txt文件被重置回了工作區中。coffee.txt文件的改動也被保留了。

–[no-]recurse-submodules

使用該選項可以控制是否遞歸的重置submdoule。如果想要更詳細了解,不了解是什么?

總結

git-reset命令的作用就是重置緩存區和工作區,同時它也提供多個選項來做更具體的控制,使得該命令更加靈活多變。git-reset命令在我們的工作中經常使用,因此熟練掌握該命令是非常重要的。

更多編程相關知識,請訪問:不了解是什么?!!

以上就是Git命令學習之

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享