git reset 怎么还原_如何在Git中重置、恢复,返回到以前的状态
編輯推薦:
本文來自51cto,在本文中,我們將帶你了解如何去重置、恢復(fù)和完全回到以前的狀態(tài),做到這些只需要幾個(gè)簡(jiǎn)單而優(yōu)雅的
Git 命令。
用簡(jiǎn)潔而優(yōu)雅的 Git 命令撤銷倉庫中的改變。
使用 Git 工作時(shí)其中一個(gè)鮮為人知(和沒有意識(shí)到)的方面就是,如何輕松地返回到你以前的位置 ——
也就是說,在倉庫中如何很容易地去撤銷那怕是重大的變更。在本文中,我們將帶你了解如何去重置、恢復(fù)和完全回到以前的狀態(tài),做到這些只需要幾個(gè)簡(jiǎn)單而優(yōu)雅的
Git 命令。
重置
我們從 Git 的 reset 命令開始。確實(shí),你應(yīng)該能夠認(rèn)為它就是一個(gè) “回滾” —— 它將你本地環(huán)境返回到之前的提交。這里的
“本地環(huán)境” 一詞,我們指的是你的本地倉庫、暫存區(qū)以及工作目錄。
先看一下圖 1。在這里我們有一個(gè)在 Git 中表示一系列提交的示意圖。在 Git 中一個(gè)分支簡(jiǎn)單來說就是一個(gè)命名的、指向一個(gè)特定的提交的可移動(dòng)指針。在這里,我們的
master 分支是指向鏈中最新提交的一個(gè)指針。
圖 1:有倉庫、暫存區(qū)、和工作目錄的本地環(huán)境
如果看一下我們的 master 分支是什么,可以看一下到目前為止我們產(chǎn)生的提交鏈。
$
git log --oneline
b764644 File with three lines
7c709f0 File with two lines
9ef9173 File with one line
如果我們想回滾到前一個(gè)提交會(huì)發(fā)生什么呢?很簡(jiǎn)單 —— 我們只需要移動(dòng)分支指針即可。Git 提供了為我們做這個(gè)動(dòng)作的
reset 命令。例如,如果我們重置 master 為當(dāng)前提交回退兩個(gè)提交的位置,我們可以使用如下之一的方法:
$
git reset 9ef9173
(使用一個(gè)絕對(duì)的提交 SHA1 值 9ef9173)
或:
$
git reset current~2
(在 “current” 標(biāo)簽之前,使用一個(gè)相對(duì)值 -2)
圖 2 展示了操作的結(jié)果。在這之后,如果我們?cè)诋?dāng)前分支(master)上運(yùn)行一個(gè) git log
命令,我們將看到只有一個(gè)提交。
$
git log --oneline
9ef9173 File with one line
圖 2:在 reset 之后
git reset 命令也包含使用一些選項(xiàng),可以讓你最終滿意的提交內(nèi)容去更新本地環(huán)境的其它部分。這些選項(xiàng)包括:hard
在倉庫中去重置指向的提交,用提交的內(nèi)容去填充工作目錄,并重置暫存區(qū);soft 僅重置倉庫中的指針;而
mixed(默認(rèn)值)將重置指針和暫存區(qū)。
這些選項(xiàng)在特定情況下非常有用,比如,git reset --hard
| reference> 這個(gè)命令將覆蓋本地任何未提交的更改。實(shí)際上,它重置了(清除掉)暫存區(qū),并用你重置的提交內(nèi)容去覆蓋了工作區(qū)中的內(nèi)容。在你使用
hard 選項(xiàng)之前,一定要確保這是你真正地想要做的操作,因?yàn)檫@個(gè)命令會(huì)覆蓋掉任何未提交的更改。
恢復(fù)
git revert 命令的實(shí)際結(jié)果類似于 reset,但它的方法不同。reset 命令(默認(rèn))是在鏈中向后移動(dòng)分支的指針去“撤銷”更改,revert
命令是在鏈中添加一個(gè)新的提交去“取消”更改。再次查看圖 1 可以非常輕松地看到這種影響。如果我們?cè)阪溨械拿總€(gè)提交中向文件添加一行,一種方法是使用
reset 使那個(gè)提交返回到僅有兩行的那個(gè)版本,如:git reset HEAD~1。
另一個(gè)方法是添加一個(gè)新的提交去刪除第三行,以使最終結(jié)束變成兩行的版本 —— 實(shí)際效果也是取消了那個(gè)更改。使用一個(gè)
git revert 命令可以實(shí)現(xiàn)上述目的,比如:
$
git revert HEAD
因?yàn)樗砑恿艘粋€(gè)新的提交,Git 將提示如下的提交信息:
Revert
"File with three lines"
This reverts commit b764644bad524b804577684bf74e7bca3117f554.
# Please enter the commit message for your changes.
Lines starting
# with '#' will be ignored, and an empty message
aborts the commit.
# On branch master
# Changes to be committed:
# modified: file1.txt
#
圖 3(在下面)展示了 revert 操作完成后的結(jié)果。
如果我們現(xiàn)在運(yùn)行一個(gè) git log 命令,我們將看到前面的提交之前的一個(gè)新提交。
$
git log --oneline
11b7712 Revert "File with three lines"
b764644 File with three lines
7c709f0 File with two lines
9ef9173 File with one line
這里是工作目錄中這個(gè)文件當(dāng)前的內(nèi)容:
$
cat
Line 1
Line 2
圖 3 revert 操作之后
恢復(fù)或重置如何選擇?
為什么要優(yōu)先選擇 revert 而不是 reset 操作?如果你已經(jīng)將你的提交鏈推送到遠(yuǎn)程倉庫(其它人可以已經(jīng)拉取了你的代碼并開始工作),一個(gè)
revert 操作是讓他們?nèi)カ@得更改的非常友好的方式。這是因?yàn)?Git 工作流可以非常好地在分支的末端添加提交,但是當(dāng)有人
reset 分支指針之后,一組提交將再也看不見了,這可能會(huì)是一個(gè)挑戰(zhàn)。
當(dāng)我們以這種方式使用 Git 工作時(shí),我們的基本規(guī)則之一是:在你的本地倉庫中使用這種方式去更改還沒有推送的代碼是可以的。如果提交已經(jīng)推送到了遠(yuǎn)程倉庫,并且可能其它人已經(jīng)使用它來工作了,那么應(yīng)該避免這些重寫提交歷史的更改。
總之,如果你想回滾、撤銷或者重寫其它人已經(jīng)在使用的一個(gè)提交鏈的歷史,當(dāng)你的同事試圖將他們的更改合并到他們拉取的原始鏈上時(shí),他們可能需要做更多的工作。如果你必須對(duì)已經(jīng)推送并被其他人正在使用的代碼做更改,在你做更改之前必須要與他們溝通,讓他們先合并他們的更改。然后在這個(gè)侵入操作沒有需要合并的內(nèi)容之后,他們?cè)倮∽钚碌母北尽?/p>
你可能注意到了,在我們做了 reset 操作之后,原始的提交鏈仍然在那個(gè)位置。我們移動(dòng)了指針,然后
reset 代碼回到前一個(gè)提交,但它并沒有刪除任何提交。換句話說就是,只要我們知道我們所指向的原始提交,我們能夠通過簡(jiǎn)單的返回到分支的原始鏈的頭部來“恢復(fù)”指針到前面的位置:
git
reset
當(dāng)提交被替換之后,我們?cè)?Git 中做的大量其它操作也會(huì)發(fā)生類似的事情。新提交被創(chuàng)建,有關(guān)的指針被移動(dòng)到一個(gè)新的鏈,但是老的提交鏈仍然存在。
變基
現(xiàn)在我們來看一個(gè)分支變基。假設(shè)我們有兩個(gè)分支:master 和 feature,提交鏈如下圖 4 所示。master
的提交鏈?zhǔn)?C4->C2->C1->C0 和 feature 的提交鏈?zhǔn)?C5->C3->C2->C1->C0。
圖 4:master 和 feature 分支的提交鏈
如果我們?cè)诜种е锌此奶峤挥涗?#xff0c;它們看起來應(yīng)該像下面的這樣。(為了易于理解,C 表示提交信息)
$
git log --oneline master
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0
$ git log --oneline feature
79768b8 C5
000f9ae C3
259bf36 C2
f33ae68 C1
5043e79 C0
我告訴人們?cè)?Git 中,可以將 rebase 認(rèn)為是 “將歷史合并”。從本質(zhì)上來說,Git 將一個(gè)分支中的每個(gè)不同提交嘗試“重放”到另一個(gè)分支中。
因此,我們使用基本的 Git 命令,可以變基一個(gè) feature 分支進(jìn)入到 master 中,并將它拼入到
C4 中(比如,將它插入到 feature 的鏈中)。操作命令如下:
$
git checkout feature
$ git rebase master
First, rewinding head to replay your work on
top of it...
Applying: C3
Applying: C5
完成以后,我們的提交鏈將變成如下圖 5 的樣子。
圖 5:rebase 命令完成后的提交鏈
接著,我們看一下提交歷史,它應(yīng)該變成如下的樣子。
$
git log --oneline master
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0
$ git log --oneline feature
c4533a5 C5
64f2047 C3
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0
注意那個(gè) C3' 和 C5'— 在 master 分支上已處于提交鏈的“頂部”,由于產(chǎn)生了更改而創(chuàng)建了新提交。但是也要注意的是,rebase
后“原始的” C3 和 C5 仍然在那里 — 只是再?zèng)]有一個(gè)分支指向它們而已。
如果我們做了這個(gè)變基,然后確定這不是我們想要的結(jié)果,希望去撤銷它,我們可以做下面示例所做的操作:
$
git reset 79768b8
由于這個(gè)簡(jiǎn)單的變更,現(xiàn)在我們的分支將重新指向到做 rebase 操作之前一模一樣的位置 —— 完全等效于撤銷操作(圖
6)。
圖 6:撤銷 rebase 操作之后
如果你想不起來之前一個(gè)操作指向的一個(gè)分支上提交了什么內(nèi)容怎么辦?幸運(yùn)的是,Git 命令依然可以幫助你。用這種方式可以修改大多數(shù)操作的指針,Git
會(huì)記住你的原始提交。事實(shí)上,它是在 .git 倉庫目錄下,將它保存為一個(gè)特定的名為 ORIG_HEAD
的文件中。在它被修改之前,那個(gè)路徑是一個(gè)包含了大多數(shù)最新引用的文件。如果我們 cat 這個(gè)文件,我們可以看到它的內(nèi)容。
$
cat .git/ORIG_HEAD
79768b891f47ce06f13456a7e222536ee47ad2fe
我們可以使用 reset 命令,正如前面所述,它返回指向到原始的鏈。然后它的歷史將是如下的這樣:
$
git log --oneline feature
79768b8 C5
000f9ae C3
259bf36 C2
f33ae68 C1
5043e79 C0
在 reflog 中是獲取這些信息的另外一個(gè)地方。reflog 是你本地倉庫中相關(guān)切換或更改的詳細(xì)描述清單。你可以使用
git reflog 命令去查看它的內(nèi)容:
$
git reflog
79768b8 HEAD@{0}: reset: moving to 79768b
c4533a5 HEAD@{1}: rebase finished: returning
to refs/heads/feature
c4533a5 HEAD@{2}: rebase: C5
64f2047 HEAD@{3}: rebase: C3
6a92e7a HEAD@{4}: rebase: checkout master
79768b8 HEAD@{5}: checkout: moving from feature
to feature
79768b8 HEAD@{6}: commit: C5
000f9ae HEAD@{7}: checkout: moving from master
to feature
6a92e7a HEAD@{8}: commit: C4
259bf36 HEAD@{9}: checkout: moving from feature
to master
000f9ae HEAD@{10}: commit: C3
259bf36 HEAD@{11}: checkout: moving from master
to feature
259bf36 HEAD@{12}: commit: C2
f33ae68 HEAD@{13}: commit: C1
5043e79 HEAD@{14}: commit (initial): C0
你可以使用日志中列出的、你看到的相關(guān)命名格式,去重置任何一個(gè)東西:
$
git reset HEAD@{1}
一旦你理解了當(dāng)“修改”鏈的操作發(fā)生后,Git 是如何跟蹤原始提交鏈的基本原理,那么在 Git 中做一些更改將不再是那么可怕的事。這就是強(qiáng)大的
Git 的核心能力之一:能夠很快速、很容易地嘗試任何事情,并且如果不成功就撤銷它們。
總結(jié)
以上是生活随笔為你收集整理的git reset 怎么还原_如何在Git中重置、恢复,返回到以前的状态的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java面板中添加面板_如何把窗体加入面
- 下一篇: 此计算机到未能识别网络连接,本地连接显示