使用Git進(jìn)行版本控制開發(fā)時(shí)難免會(huì)遇到回顧的情況,這里來解釋下該如何正確的回滾
idea 使用 git 切換版本博文鏈接
1.本地倉庫回滾
本地回滾就很簡單,只是要撤銷 commit 信息即可??梢灾苯邮褂?Reset HEAD進(jìn)行回滾。
HEAD^ 是還原到上一個(gè)版本,HEAD^^ 是還原到上上一個(gè)版本。
Reset Type 有三種:
- mixed 默認(rèn)方式,只保留源碼,回退commit和index信息
- soft 回退到某個(gè)版本,只回退了commit的信息,不會(huì)恢復(fù)到index file一級(jí)。如果還要提交,直接commit
- hard 徹底回退,本地源碼也會(huì)變成上一個(gè)版本內(nèi)容
2.遠(yuǎn)程倉庫回滾
2.1錯(cuò)誤案例
遠(yuǎn)程倉庫代碼回滾,如果上 Google 上一搜,基本出來的答案都是使用 Reset HEAD 加上 git push -f 強(qiáng)制提交的方式。
我本地測試了一下,如果有兩個(gè)人同時(shí)在這條分支上開發(fā),其中一個(gè)人 小 A 如果使用這種方式進(jìn)行回滾了遠(yuǎn)程倉庫代碼,另外一個(gè)人 小 B 此時(shí)本地還是回滾之前的代碼,小 B 那里就會(huì)出現(xiàn)本地代碼版本高于遠(yuǎn)程分支版本的情況,此時(shí)若小 B 進(jìn)行了 push 操作,之前小 A 回滾的代碼就又會(huì)被推送到遠(yuǎn)程的倉庫了。除非小 B 在回滾后,將其本地倉庫的版本也進(jìn)行回滾。才能保證不會(huì)把回滾的代碼重新 push 回遠(yuǎn)程倉庫,但是如果開發(fā)人員多,就無法保證所有開發(fā)人員的本地分支都回滾!
因此,不要使用 git push -f 這種方式來強(qiáng)制回滾遠(yuǎn)程倉庫代碼!
2.2正確操作
比如想要回滾到“細(xì)微變動(dòng),無功能變化”
就需要把遠(yuǎn)程倉庫回滾到“細(xì)微變動(dòng),無功能變化”這個(gè)提交點(diǎn)
選中后右鍵,選擇Revert Commit
應(yīng)該是會(huì)提示commit,在commit之后push到遠(yuǎn)程倉庫中,
注意:慎用reset commit,這個(gè)會(huì)把這條commit之前的所有commit給刪掉
其他開發(fā)人員如果進(jìn)行了 pull,其本地倉庫也被正確回滾到了 dev-103 提交點(diǎn),就無需再擔(dān)心回滾的代碼又被重新 push 到遠(yuǎn)程倉庫啦
3.代碼提交到錯(cuò)誤的分支解決
前提是尚未將修改提交到錯(cuò)誤的分支
> git stash //將修改的代碼暫存到stash
> git checkout rightbranch //切換到正確的分支
> git stash pop //從stashz中去除暫存的代碼修改
> git add .
> git commit -m xxx
4.Git Rest三種模式詳解(soft,mixed,hard)
有時(shí)候,我們用Git的時(shí)候有可能commit提交代碼后,發(fā)現(xiàn)這一次commit的內(nèi)容是有錯(cuò)誤的,那么有兩種處理方法:
- 修改錯(cuò)誤內(nèi)容,再次commit一次
- 使用git reset 命令撤銷這一次錯(cuò)誤的commit
第一種方法比較直接,但會(huì)多次一次commit記錄。
而我個(gè)人更傾向第二種方法,錯(cuò)誤的commit沒必要保留下來。
那么今天來說一下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,具體的使用方法下面這張圖,展示的很全面了。
- Working Tree 當(dāng)前的工作區(qū)域
- Index/Stage 暫存區(qū)域,和git stash命令暫存的地方不一樣。使用git add xx,就可以將xx添加近Stage里面
- Repository 提交的歷史,即使用git commit提交后的結(jié)果
文字介紹下文件存入Repository的過程
-
剛開始 working tree 、 index 與 repository(HEAD)里面的內(nèi)容都是一致的
-
當(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)。
-
當(dāng)執(zhí)行 git add 后,會(huì)將這些改變的文件內(nèi)容加入 index 中 (Staged files),所以此時(shí)working tree跟index的內(nèi)容是一致的,但他們與repository(HEAD)內(nèi)容不一致。
-
接著執(zhí)行 git commit ,將Git索引中所有改變的文件內(nèi)容提交至 Repository 中,建立出新的 commit 節(jié)點(diǎn)(HEAD)后, working tree 、 index 與repository(HEAD)區(qū)域的內(nèi)容 又會(huì)保持一致。
4.1操作演示
reset --hard:重置stage區(qū)(暫存區(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狀態(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)也一起全都消失了:
可以看到,在 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保留在工作目錄
查看此時(shí)的狀態(tài):
假設(shè)此時(shí)當(dāng)前 commit 的改動(dòng)內(nèi)容是新增了 laughters.txt 文件:
輸入: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ū):
這就是–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)工作目錄。簡而言之,就是「把所有差異都混合(mixed)放在工作目錄中」。
還是把修改后的ganmes.txt文件add到stage區(qū),修改后的shopping list.txt保留在工作目錄
最新的 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)工作目錄
4.2總結(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 的歷史只能往回看,不能向未來看,所以把 HEAD 和 branch 往回移動(dòng),就能起到撤回 commit 的效果。
所以同理,reset --hard 不僅可以撤銷提交,還可以用來把 HEAD 和 branch 移動(dòng)到其他的任何地方。
4.3三種模式的區(qū)別和使用場景
區(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ì)放到工作目錄中
使用場景
-
–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 中。為什么要這樣呢?這樣做的使用場景是:假如我們想合并「當(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了
5.Rest后的復(fù)原
如果不小心執(zhí)行 reset 或 rebase 等可能會(huì)造成版本號(hào)消失的指令時(shí),而我們想要恢復(fù)但卻在演進(jìn)線圖(commit log)上找不到commit結(jié)點(diǎn),這時(shí)候就可通過 git reflog 找出所有歷史記錄,通過 HEAD@{N} 這個(gè)特殊的「參考名稱」來對(duì)此版本「定位」,進(jìn)而使用 git reset --hard HEAD@{N} 指令回歸原有版本。
剛執(zhí)行了git reset --hard HEAD~2
,此時(shí)后悔想要恢復(fù),結(jié)果是找不到原始commit節(jié)點(diǎn)的
這時(shí)候可以執(zhí)行 git reflog
列出所有歷史記錄,其中 HEAD@{0}~HEAD@{4} 都是剛剛進(jìn)行測試時(shí)所產(chǎn)生的,因此需要恢復(fù)到執(zhí)行 reset 指令之前的 commit 節(jié)點(diǎn),也就是HEAD@{5}這個(gè)節(jié)點(diǎn)的位置。
執(zhí)行 git reset --hard HEAD@{5}
回歸原始版本,會(huì)連同working tree(工作目錄)檔案也會(huì)一併恢復(fù)。
看一下線圖,真的回來了,真的沒有什么回不來的~~文章來源:http://www.zghlxwxcb.cn/news/detail-754341.html
參考文章(侵刪):
https://www.cnblogs.com/vcmq/p/10162051.html
Git Reset 三種模式文章來源地址http://www.zghlxwxcb.cn/news/detail-754341.html
到了這里,關(guān)于idea中代碼git的版本穿梭&Git Rest三種模式詳解(soft,mixed,hard)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!