前言
在做項(xiàng)目時遇到了一個問題,就是不知道什么操作,無緣無故把test分支代碼合并到了master,導(dǎo)致花了好長時間去恢復(fù)master分支的代碼,所以研究了一下,到底是什么原因?qū)е碌倪@個問題
PS: 后來分析出來根本原因,確定這確實(shí)是IDEA的一個BUG,在下面會有詳細(xì)描述
復(fù)現(xiàn)方式
-
當(dāng)我們在test分支時,通過pull拉取更新代碼,這時候會有一個進(jìn)度條
-
進(jìn)度條走完之前,我們想要去另一個分支看東西,點(diǎn)了checkout分支master,這時候我們切換到master分支
-
pull動作走完,這時候會提示合并代碼,這時候有兩種情況
-
情況一:如果有文件沖突,會彈出合并窗口,沒注意點(diǎn)了合并代碼,就會把test分支的代碼合并到master分支上
-
情況二:如果沒有代碼沖突,這時候會直接合并代碼,也會把test分支的代碼合并到master分支上
- 這時候可能有的同學(xué)把代碼提交到遠(yuǎn)程
這將是一個很嚴(yán)重的問題
經(jīng)過分析IDEA的日志發(fā)現(xiàn),在點(diǎn)擊更新按鈕時,IDEA并沒有直接執(zhí)行g(shù)it pull,而是拆成了兩步,第一步fetch 同步線上版本,第二步merge origin/test合并遠(yuǎn)程test分支到本地HEAD(這里沒有指定本地分支,所以會直接合并到HEAD分支上)。
這里就出現(xiàn)一個問題,兩個指令就是兩個鎖,這種見有十秒左右的空檔期,在這個空檔期我們不小心切換了分支mater,就會導(dǎo)致HEAD指向了切換后的分支master,再執(zhí)行merge origin/test ,就會導(dǎo)致遠(yuǎn)程test分支合并到master上,假如有沖突就會彈出合并沖突窗口,沒有沖突就直接合并上去了,這里有時候是沒有沖突的(我們很有可能剛剛從master拉出來分支A,A往test上合并時處理過沖突,就導(dǎo)致test分支合并到master分支并沒有沖突)
這里假如底層使用git pull一個指令也是沒有問題的,因?yàn)橐粋€指令就是一個鎖,你在執(zhí)行pull過程中想要切換分支時,因?yàn)橛墟i,會切換失敗,而不是導(dǎo)致合并錯誤
IDEA日志顯示的操作過程
第一步執(zhí)行 :fetch 操作
git -c core.quotepath=false -c log.showSignature=false fetch origin --recurse-submodules=no --progress --prune
第二步執(zhí)行:merge
git -c core.quotepath=false -c log.showSignature=false merge origin/test --no-stat -v
解決辦法
下面是分支版本示意圖
情況一:關(guān)掉合并窗口,點(diǎn)git》合并代碼》中止合并
情況二: 已合并,如果沒提交到遠(yuǎn)程倉庫,這時候可以用reset指令將代碼恢復(fù)到指定版本4,就可以
情況三:已合并,并提交到 遠(yuǎn)程倉庫 的情況下,
通過reset和revert指令,將代碼版本恢復(fù)到對應(yīng)版本4,這時候會生成版本6,再提交版本6到遠(yuǎn)程代碼庫
具體的操作驗(yàn)證
-
查看日志,記錄需還原的commit版本號, git log --pretty=oneline
git log --pretty =oneline -
撤銷已提交的commit,回滾到測試分支誤合并到開發(fā)分支的commit版本
git reset --mixed 回滾版本號 -
再次使用git log可以看到當(dāng)前HEAD指向了測試分支誤合并到開發(fā)分支的commit版本
-
這時候我們的代碼區(qū)多了很多未暫存的文件
-
把撤銷的代碼文件暫存起來
git stash save ‘保存撤銷的代碼’ -
再撤銷當(dāng)前commit并且不保留代碼(因?yàn)檫@里的代碼是從測試分支合并過來的,我們不需要這些代碼)
git revert HEAD^
注: 這里因?yàn)槭莔erge節(jié)點(diǎn)直接使用git revert HEAD^ 會提示指定主分支,這里用git log -5 指令確定一下哪個是我們要恢復(fù)的主分支即可 ,最終確定主分支是第二個merge節(jié)點(diǎn),所以執(zhí)行g(shù)it revert HEAD^ -m 2
- 把貯存區(qū)的代碼重新應(yīng)用出來
git stash list
git stash apply stash@{0} - 到這里就已經(jīng)去掉了測試分支的代碼,我們就可以push當(dāng)前代碼到遠(yuǎn)程了
最新方法: 直接執(zhí)行 git revert 合并節(jié)點(diǎn)版本號 -m 主分支編號 即可文章來源:http://www.zghlxwxcb.cn/news/detail-412866.html
#這個案例中為
git revert 版本5 -m 2
這里介紹一下reset 和revert區(qū)別,
reset:是移動本地代碼head指針到版本4 ,再pull拉取時會再把所有版本都拉取下來,再移動head指針到最新的節(jié)點(diǎn),提交代碼也會提示無可用的更新
revert:(git revert 節(jié)點(diǎn)5版本號) 進(jìn)行回滾操作,創(chuàng)建一個新版本節(jié)點(diǎn)N,這個版本N是執(zhí)行了一個與節(jié)點(diǎn)5相反的操作抵消調(diào)版本5中的所有操作,但是會保留節(jié)點(diǎn)5后面所有節(jié)點(diǎn)的操作(比如節(jié)點(diǎn)5后面有6、7、8修改的文件都會保留)。而且節(jié)點(diǎn)N是一個新的提交節(jié)點(diǎn),所以revert后再提交到遠(yuǎn)程是可以提交上去的文章來源地址http://www.zghlxwxcb.cn/news/detail-412866.html
到了這里,關(guān)于記錄一個IDEA中使用GIT的嚴(yán)重BUG,導(dǎo)致測試分支合并到主分支,以及代碼恢復(fù)解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!