柚子快報(bào)激活碼778899分享:Git -- reset 詳解
柚子快報(bào)激活碼778899分享:Git -- reset 詳解
引言
當(dāng)我們?cè)陧?xiàng)目中有多個(gè)人協(xié)同開發(fā)時(shí)候,難免會(huì)出現(xiàn)一些錯(cuò)誤的提交或者刪除了一些重要文件。我們需要回滾到指定的某一個(gè)節(jié)點(diǎn)。那些亂七八糟的各種提交都要清除掉。
這時(shí)候,我們的指令就要用到了。reset
正文
git reset。它的一句話概括
git-reset - Reset current HEAD to the specified state
意思就是可以讓HEAD這個(gè)指針指向其他的地方。例如我們有一次commit不是不是很滿意,需要回到上一次的Commit里面。那么這個(gè)時(shí)候就需要通過reset,把HEAD指針指向上一次的commit的點(diǎn)。 它有三種模式,soft,mixed,hard,具體的使用方法下面這張圖,展示的很全面。
另外git reset --hard HEAD^ 等價(jià)于git reset --hard xxx(xxx為commit id)
git各個(gè)區(qū)域和命令關(guān)系
這三個(gè)模式理解了,對(duì)于使用這個(gè)命令很有幫助。在理解這三個(gè)模式之前,需要略微知道一點(diǎn)Git的基本流程。正如上圖,Git會(huì)有三個(gè)區(qū)域:
Working Tree?當(dāng)前的工作區(qū)域Index/Stage?暫存區(qū)域,和git stash命令暫存的地方不一樣。使用git add xx,就可以將xx添加近Stage里面Repository?提交的歷史,即使用git commit提交后的結(jié)果
文件存入Repository流程
以下簡(jiǎn)單敘述一下把文件存入Repository流程:
剛開始 working tree 、 index 與 repository(HEAD)里面的內(nèi)容都是一致的 ? 階段1 當(dāng)git管理的文件夾里面的內(nèi)容出現(xiàn)改變后,此時(shí) working tree 的內(nèi)容就會(huì)跟 index 及 repository(HEAD)的不一致,而Git知道是哪些文件(Tracked File)被改動(dòng)過,直接將文件狀態(tài)設(shè)置為 modified (Unstaged files)。 ? 階段2 當(dāng)我們執(zhí)行 git add 后,會(huì)將這些改變的文件內(nèi)容加入 index 中 (Staged files),所以此時(shí)working tree跟index的內(nèi)容是一致的,但他們與repository(HEAD)內(nèi)容不一致。 ? 階段3 接著執(zhí)行 git commit 后,將Git索引中所有改變的文件內(nèi)容提交至 Repository 中,建立出新的 commit 節(jié)點(diǎn)(HEAD)后, working tree 、 index 與與repository(HEAD)區(qū)域的內(nèi)容 又會(huì)保持一致。 ? 階段4
實(shí)戰(zhàn)演示
reset --hard:重置stage區(qū)和工作目錄:
reset --hard?會(huì)在重置?HEAD?和branch的同時(shí),重置stage區(qū)和工作目錄里的內(nèi)容。當(dāng)你在?reset?后面加了?--hard?參數(shù)時(shí),你的stage區(qū)和工作目錄里的內(nèi)容會(huì)被完全重置為和HEAD的新位置相同的內(nèi)容。換句話說,就是你的沒有commit的修改會(huì)被全部擦掉。
例如你在上次?commit?之后又對(duì)文件做了一些改動(dòng):把修改后的ganmes.txt文件add到stage區(qū),修改后的shopping list.txt保留在工作目錄
git status
最初狀態(tài) 然后,你執(zhí)行了reset并附上了--hard參數(shù):
git reset --hard HEAD^
你的?HEAD?和當(dāng)前?branch?切到上一條commit?的同時(shí),你工作目錄里的新改動(dòng)和已經(jīng)add到stage區(qū)的新改動(dòng)也一起全都消失了:
git status
reset --hard head^之后 可以看到,在?reset --hard?后,所有的改動(dòng)都被擦掉了。
reset --soft:保留工作目錄,并把重置 HEAD 所帶來的新的差異放進(jìn)暫存區(qū)
reset --soft?會(huì)在重置?HEAD?和?branch?時(shí),保留工作目錄和暫存區(qū)中的內(nèi)容,并把重置?HEAD?所帶來的新的差異放進(jìn)暫存區(qū)。
什么是「重置?HEAD?所帶來的新的差異」?就是這里:
由于?HEAD?從 4 移動(dòng)到了 3,而且在 reset 的過程中工作目錄和暫存區(qū)的內(nèi)容沒有被清理掉,所以 4 中的改動(dòng)在?reset?后就也成了工作目錄新增的「工作目錄和?HEAD?的差異」。這就是上面一段中所說的「重置?HEAD?所帶來的差異」。
此模式下會(huì)保留?working tree工作目錄的內(nèi)容,不會(huì)改變到目前所有的git管理的文件夾的內(nèi)容;也會(huì) 保留?index暫存區(qū)的內(nèi)容,讓?index 暫存區(qū)與?working tree?工作目錄的內(nèi)容是一致的。就只有?repository?中的內(nèi)容的更變需要與?reset?目標(biāo)節(jié)點(diǎn)一致,因此原始節(jié)點(diǎn)與reset節(jié)點(diǎn)之間的差異變更集合會(huì)存在與index暫存區(qū)中(Staged files),所以我們可以直接執(zhí)行?git commit?將?index暫存區(qū)中的內(nèi)容提交至?repository?中。當(dāng)我們想合并「當(dāng)前節(jié)點(diǎn)」與「reset目標(biāo)節(jié)點(diǎn)」之間不具太大意義的?commit?記錄(可能是階段性地頻繁提交)時(shí),可以考慮使用?Soft Reset?來讓?commit?演進(jìn)線圖較為清晰點(diǎn)。
所以在同樣的情況下,還是老樣子:把修改后的ganmes.txt文件add到stage區(qū),修改后的shopping list.txt保留在工作目錄
git status
最初狀態(tài)
假設(shè)此時(shí)當(dāng)前?commit?的改動(dòng)內(nèi)容是新增了?laughters.txt?文件:
git show --stat
git show --stat
如果這時(shí)你執(zhí)行:
git reset --soft HEAD^
那么除了?HEAD?和它所指向的?branch1?被移動(dòng)到?HEAD^?之外,原先?HEAD?處?commit?的改動(dòng)(也就是那個(gè)?laughters.txt?文件)也會(huì)被放進(jìn)暫存區(qū):
git status
使用git reset --soft HEAD^后 這就是--soft?和?--hard?的區(qū)別:--hard?會(huì)清空工作目錄和暫存區(qū)的改動(dòng),*而?--soft則會(huì)保留工作目錄的內(nèi)容,并把因?yàn)楸A艄ぷ髂夸泝?nèi)容所帶來的新的文件差異放進(jìn)暫存區(qū)。
reset 不加參數(shù)(mixed):保留工作目錄,并清空暫存區(qū)
reset?如果不加參數(shù),那么默認(rèn)使用?--mixed?參數(shù)。它的行為是:保留工作目錄,并且清空暫存區(qū)。也就是說,工作目錄的修改、暫存區(qū)的內(nèi)容以及由?reset?所導(dǎo)致的新的文件差異,都會(huì)被放進(jìn)工作目錄。簡(jiǎn)而言之,就是「把所有差異都混合(mixed)放在工作目錄中」。
還以同樣的情況為例:
git status
最初狀態(tài)
修改了 的games.txt 和 shopping list.txt,并把 games.txt 放進(jìn)了暫存區(qū)。
git show --stat
git show --stat
最新的 commit 中新增了 laughters.txt 文件。
這時(shí)如果你執(zhí)行無參數(shù)的reset或者帶--mixed參數(shù):
git reset HEAD^ git reset --mixed HEAD^
工作目錄的內(nèi)容和?--soft?一樣會(huì)被保留,但和?--soft?的區(qū)別在于,它會(huì)把暫存區(qū)清空,并把原節(jié)點(diǎn)和reset節(jié)點(diǎn)的差異的文件放在工作目錄,總而言之就是,工作目錄的修改、暫存區(qū)的內(nèi)容以及由?reset?所導(dǎo)致的新的文件差異,都會(huì)被放進(jìn)工作目錄
git status
git reset HEAD^之后
總結(jié)
reset 的本質(zhì):移動(dòng) HEAD 以及它所指向的 branch
實(shí)質(zhì)上,reset?這個(gè)指令雖然可以用來撤銷?commit?,但它的實(shí)質(zhì)行為并不是撤銷,而是移動(dòng)?HEAD?,并且「捎帶」上?HEAD?所指向的?branch(如果有的話)。也就是說,reset?這個(gè)指令的行為其實(shí)和它的字面意思 "reset"(重置)十分相符:它是用來重置?HEAD?以及它所指向的?branch?的位置的。
而?reset --hard HEAD^?之所以起到了撤銷?commit?的效果,是因?yàn)樗?HEAD?和它所指向的 branch 一起移動(dòng)到了當(dāng)前?commit?的父?commit?上,從而起到了「撤銷」的效果:
git reset
Git 的歷史只能往回看,不能向未來看,所以把?HEAD?和?branch?往回移動(dòng),就能起到撤回?commit?的效果。
所以同理,reset --hard?不僅可以撤銷提交,還可以用來把?HEAD?和?branch?移動(dòng)到其他的任何地方。
git reset --hard branch2
git reset --hard branch2
reset三種模式區(qū)別和使用場(chǎng)景
區(qū)別:
--hard:重置位置的同時(shí),直接將?working Tree工作目錄、?index 暫存區(qū)及?repository?都重置成目標(biāo)Reset節(jié)點(diǎn)的內(nèi)容,所以效果看起來等同于清空暫存區(qū)和工作區(qū)。 --soft:重置位置的同時(shí),保留working Tree工作目錄和index暫存區(qū)的內(nèi)容,只讓repository中的內(nèi)容和?reset?目標(biāo)節(jié)點(diǎn)保持一致,因此原節(jié)點(diǎn)和reset節(jié)點(diǎn)之間的【差異變更集】會(huì)放入index暫存區(qū)中(Staged files)。所以效果看起來就是工作目錄的內(nèi)容不變,暫存區(qū)原有的內(nèi)容也不變,只是原節(jié)點(diǎn)和Reset節(jié)點(diǎn)之間的所有差異都會(huì)放到暫存區(qū)中。 --mixed(默認(rèn)):重置位置的同時(shí),只保留Working Tree工作目錄的內(nèi)容,但會(huì)將?Index暫存區(qū)?和?Repository?中的內(nèi)容更改和reset目標(biāo)節(jié)點(diǎn)一致,因此原節(jié)點(diǎn)和Reset節(jié)點(diǎn)之間的【差異變更集】會(huì)放入Working Tree工作目錄中。所以效果看起來就是原節(jié)點(diǎn)和Reset節(jié)點(diǎn)之間的所有差異都會(huì)放到工作目錄中。
使用場(chǎng)景:
--hard:(1)?要放棄目前本地的所有改變時(shí),即去掉所有add到暫存區(qū)的文件和工作區(qū)的文件,可以執(zhí)行?git reset -hard HEAD?來強(qiáng)制恢復(fù)git管理的文件夾的內(nèi)容及狀態(tài);(2)?真的想拋棄目標(biāo)節(jié)點(diǎn)后的所有commit(可能覺得目標(biāo)節(jié)點(diǎn)到原節(jié)點(diǎn)之間的commit提交都是錯(cuò)了,之前所有的commit有問題)。 --soft:原節(jié)點(diǎn)和reset節(jié)點(diǎn)之間的【差異變更集】會(huì)放入index暫存區(qū)中(Staged files),所以假如我們之前工作目錄沒有改過任何文件,也沒add到暫存區(qū),那么使用reset --soft后,我們可以直接執(zhí)行?git commit?將 index暫存區(qū)中的內(nèi)容提交至?repository?中。為什么要這樣呢?這樣做的使用場(chǎng)景是:假如我們想合并「當(dāng)前節(jié)點(diǎn)」與「reset目標(biāo)節(jié)點(diǎn)」之間不具太大意義的?commit?記錄(可能是階段性地頻繁提交,就是開發(fā)一個(gè)功能的時(shí)候,改或者增加一個(gè)文件的時(shí)候就commit,這樣做導(dǎo)致一個(gè)完整的功能可能會(huì)好多個(gè)commit點(diǎn),這時(shí)假如你需要把這些commit整合成一個(gè)commit的時(shí)候)時(shí),可以考慮使用reset --soft來讓?commit?演進(jìn)線圖較為清晰。總而言之,可以使用--soft合并commit節(jié)點(diǎn)。 --mixed(默認(rèn)):(1)使用完reset --mixed后,我們可以直接執(zhí)行?git add?將這些改變果的文件內(nèi)容加入?index 暫存區(qū)中,再執(zhí)行?git commit?將?Index暫存區(qū)?中的內(nèi)容提交至Repository中,這樣一樣可以達(dá)到合并commit節(jié)點(diǎn)的效果(與上面--soft合并commit節(jié)點(diǎn)差不多,只是多了git add添加到暫存區(qū)的操作);(2)移除所有Index暫存區(qū)中準(zhǔn)備要提交的文件(Staged files),我們可以執(zhí)行?git reset HEAD?來?Unstage?所有已列入?Index暫存區(qū)?的待提交的文件。(有時(shí)候發(fā)現(xiàn)add錯(cuò)文件到暫存區(qū),就可以使用命令)。(3)commit提交某些錯(cuò)誤代碼,或者沒有必要的文件也被commit上去,不想再修改錯(cuò)誤再commit(因?yàn)闀?huì)留下一個(gè)錯(cuò)誤commit點(diǎn)),可以回退到正確的commit點(diǎn)上,然后所有原節(jié)點(diǎn)和reset節(jié)點(diǎn)之間差異會(huì)返回工作目錄,假如有個(gè)沒必要的文件的話就可以直接刪除了,再commit上去就OK了。
柚子快報(bào)激活碼778899分享:Git -- reset 詳解
相關(guān)文章
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。