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指針指向
在以上所有的命令形式中,都是把
git reset [
該方法有如下規則:
-
會將與
相匹配的路徑資源在緩存區中重置成 中的狀態。不了解 是什么? -
被提交到緩存區中的改動會被還原到工作區中。
舉個?
假設項目中有一個coffee.txt文件,文件內容如下:
卡布奇諾納瑞冰-19.9¥ 標準美式-14.9¥ 香草拿鐵-19.9¥ 生椰愛摩卡-19.9¥ ...
我們使用git的tag命令將當前的版本標記成v1.0.0(這里使用tag標簽作為)。
隨后修改coffee.txt文件,修改內容如下:
卡布奇諾納瑞冰-19.9¥?-->?卡布奇諾納瑞冰-14.9¥ 標準美式-14.9¥?-->?標準美式-9.9¥ 香草拿鐵-19.9¥?-->?香草拿鐵-14.9¥ 生椰愛摩卡-19.9¥?-->?生椰愛摩卡-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查看緩存區的文件變動:
可以看到圖中的右側的代碼改動對比,此時緩存區中的coffee.txt文件已經成功被重置成v1.0.0版本中文件的狀態(規則1)。并且此時v1.0.1已經提交到緩存區中的變動也被還原到了工作樹中(規則2)。
可以看出git reset命令與git add命令作用相反,一個是將指定的資源添加到緩存區,另一個則是從緩存區中移除。并且這個命令與git restore [–source=
上面說過了,在使用reset命令后,此時緩存區中文件內容是v1.0.0的,可以配合git restore命令將緩存區中的內容還原到工作區中然后進行修改:
git?restore?coffee.txt?--staged
也可以根據需要選擇還原工作區的內容:
git?restore?coffee.txt?--worktree
git reset?[–pathspec-from-file=
在上面的例子中每次進行reset和restore的都是想同的
該文件每一行都是一個
git reset (–patch | -p) [
交互式的選擇
git reset [
該命令會把當前分支的HEAD指針指向某個
–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被拋棄了:
同時所有的工作區和緩存區的改動都被保留了:
當前只有兩次的commit,是為了方便演示–soft選項的作用。但是在實際開發中,我們可能會commit多次,尤其是在測試環境改幾個bug就要提交到發布平臺,這樣會導致很多無意義的commit。這時候就可以使用–soft選項,重置HEAD到指定的
–mixed
重置緩存區,但是會保留工作區的內容,這是
相信在理解了–soft作用后,理解–mixed不難,上面例子中如果是使用–mixed那么最終結果如下:
該選項會重置緩存區,但是保留工作區的改動,并將當前指針指向
–hard
重置緩存區和工作區中的所有的變動,并且將指針指向
–hard更加的簡單粗暴,我們將–soft例子改為–hard來查看結果:
如圖所示,工作區和緩存區的內容都被重置了。不止是如此,就連Untracked文件同樣也會被刪除。
–merge
該選項的作用,看字面意思就知道大概就是把當前分支和指定的
-
重置緩存區,任何已經添加到緩存區的改動都將被拋棄
-
如果
和HEAD之間有文件存在不同(這個不同指的是文件被刪除或者新增),那么將會把該文件重置成 中的狀態(新增或刪除)。 -
如果
和HEAD之間有文件存在不同(這個不同是指文件內容的不同),且此時工作區也存在未提交的改動,那么本次的reset將會被終止。 -
如果一個文件在
和HEAD中完全相同,但是它的工作區存與緩存區存在著不同(也就是改動未提交到緩存區),那么該文件在工作區的改動在重置之后就會被保留。
我們舉個例子來驗證一下以上列出的規則,假設此時的咖啡店項目有如下的幾個commit。
第一個commit和文件內容如下:
第一個commit中只有一個coffee.txt菜單文件,此時如果咖啡店引進了新品種開始賣果汁,那么就需要新增果汁菜單文件fruits.txt,于是就有了第二個commit:
此時我們做一些改動來驗證1,2,4這幾點的規則,改動后的文件如下:
首先修改coffee.txt文件,新增一款生椰拿鐵咖啡,保留在工作區中。然后增加咖啡豆菜單文件beans.txt,將其添加到緩存區中。
假設因需求變動,咖啡豆菜單文件在緩存區中需要清除,果汁菜單文件需要刪除,只有咖啡菜單中新增的生椰拿鐵的改動需要保留。那么就可以使用git reset –merge將HEAD和commit-1進行合并,操作如下:
git?reset?--merge?HEAD^
結果如下:
執行命令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如下:
接下去同樣新增水果茶菜單,然后再修改coffee.txt文件,第二個commit如下:
然后在HEAD中再修改coffee.txt文件,刪除掉標準美式品種:
此時,如果我們再使用git reset –merge HEAD^就無法再進行重置,該操作會被git終止(規則3)。并且控制臺會進行報錯提示:
–keep
該選參的作用和–merge相似,唯一的區別就是緩存區中被重置的會被保留在工作區中。
構造如下第一個commit:
改造第二個commit:
在HEAD中進行修改
使用git reset –keep命令:
從結果上來看,只有fruits.txt文件被刪除了,beans.txt文件被重置回了工作區中。coffee.txt文件的改動也被保留了。
–[no-]recurse-submodules
使用該選項可以控制是否遞歸的重置submdoule。如果想要更詳細了解,不了解
總結
git-reset命令的作用就是重置緩存區和工作區,同時它也提供多個選項來做更具體的控制,使得該命令更加靈活多變。git-reset命令在我們的工作中經常使用,因此熟練掌握該命令是非常重要的。
更多編程相關知識,請訪問:不了解