原文: git merge使用不當引發(fā)的代碼丟失血案@blog.23lab.com
背景
幾年前大批量的團隊都在轉(zhuǎn)用git
忆畅,git
的本地庫和分支特性讓代碼管理的便利性大大增加蔑祟,也因為本地庫和分支的大批量使用導致了代碼之間的頻繁merge光稼,我們團隊以前就有遇到過git merge
以后丟代碼的情況,表現(xiàn)就是某些變更開發(fā)A提交了,經(jīng)過中間以序列的commit
, merge
掰曾,push
,最終某些改動沒了停团,去看commit history旷坦,也沒有相應(yīng)的變更記錄。一次次commit對比以后總是會找到某次的merge
佑稠,但是也沒法解釋為什么會丟秒梅,最后為了保險通常會選擇beyond compare全量對比一次確保所有丟失的代碼找回來,那是一個痛苦而又讓人睡不安穩(wěn)的解決辦法舌胶。
今天又遇到了一次這個問題番电,這次的更加詭異,在我查為什么丟的時候辆琅,另外一個同事提交代碼以后竟然丟失的代碼回來了漱办,我當時腦袋里面只想到一個詞,那就是: 見鬼婉烟。但是冷靜下來想娩井,git這種工具出現(xiàn)真丟代碼的概率肯定很小,肯定是我們姿勢不對似袁。于是認認真真的研究了我們今天的提交記錄洞辣,終于找到答案,就是git merge
后只提交部分代碼導致的昙衅,這里順帶提一下扬霜,git pull
等于git fetch + git merge
,所以git pull
時也需要特別關(guān)注本文提到的問題而涉。
驗證過程
為了驗證這個問題著瓶,我建了一個全新的git
庫來復現(xiàn)上述問題,根據(jù)我們遇到的情況模擬啼县,整個過程我使用三個用戶模擬交叉提交和合并材原,分別是user1,user2季眷,user3余蟹,為了方便我沒有選擇注冊三個號,而是在提交信息里面都帶上了名字子刮,可以制造兩次代碼沖突威酒,并且兩次都進行部分提交。最終的代碼提交記錄如下:
為了更清晰的看到這個提交過程挺峡,我將三個用戶的提交分開來葵孤,并根據(jù)提交先后做了下面的圖。
代碼怎么丟的沙郭?
首先佛呻,第1步和第2步,user1和user2分別在本地做修改病线,共同修改了file1
吓著,只有user2對file2
也做了修改,所以如果這兩人的代碼合并送挑,可以預計合并的時file1
會沖突绑莺,file2不會。user2修改完成以后做了一次git push
惕耕,這時候git
遠端庫的head應(yīng)該是指向user2的最后一次提交的纺裁。接著user1做git pull
,因為file1被兩個用戶修改了,所以需要合并欺缘,接著user1處理完沖突以后只提交了file1
栋豫,沒有提交file2
(用命令行需要手動reset
,但是用有些GUI工具是可以選擇只提交file1
的)谚殊。此時的庫已經(jīng)丟失了user2:file2:add line
的那次改動丧鸯,這就是血案的開始,丟代碼嫩絮〈灾可以對比一下 merge前 和merge后 。
代碼怎么"恢復"的剿干?
前面只是驗證了代碼怎么丟蜂怎,但是事情沒有結(jié)束,我上面提到更詭異的是代碼恢復了置尔,這又是怎么回事呢杠步?user1在第3步合完代碼以后,自己進行了兩次提交撰洗,修改了file3和file1篮愉,同時,user3加入并本地修改了file1(預計會和user1沖突)差导,接著user1git push
试躏,然后user3 git pull
,這時候會報file1
沖突设褐,同樣颠蕴,user3犯了user1類似的錯誤,只提交了沖突文件file1
助析。按第3步丟代碼的經(jīng)驗犀被,file3
的改動肯定是沒有了,驗證以后確實如此外冀,但是再看看file2的變更呢寡键,它竟然又回來了,所以所謂的恢復不是恢復雪隧,所謂的丟失沒有丟失西轩,就問你怕不怕。更可怕的是我們再去看file2
的變更歷史脑沿。
中間消失和恢復的過程沒有任何變更記錄藕畔,這也是之前我們經(jīng)常查到?jīng)]法往下查到地方。從表現(xiàn)上看庄拇,是第一次誤操作忽略了這一行的變更注服,而第二次誤操作韭邓,可以理解為是忽略了忽略添加這一行的那一次變更,但是溶弟,所有的都沒有記錄女淑。
總結(jié)
上面的實驗可能看起來有點繁瑣,總結(jié)一下可很,核心的問題就是不要在git merge
的時候只提交部分代碼诗力,特別是好多人剛剛用git
的時候,運行完成一次git merge
我抠,發(fā)現(xiàn)自己修改了1個文件,結(jié)果git
提示要提交100個袜茧,這時候小心謹慎的新同學就會選擇只提交自己的變動吧菜拓,殊不知這是在犯大錯啊。除了這種情況笛厦,之前還遇到有的新同學會修改git
默認生成的merge信息纳鼎,這也是非常不好的習慣,改了以后在查問題的時候沒辦法很容易的看到哪些是merge裳凸。所以請注意:
git merge以后不要部分提交<伞!
git merge以后不要部分提交R坦取逗宁!
git merge以后不要部分提交!梦湘!
git merge的信息不要手動改O箍拧!
git merge的信息不要手動改0埔椤哼拔!
git merge的信息不要手動改!瓣颅!
文中提到的實驗庫的地址是: find-the-missing-code, 有興趣的童鞋可以自己詳細看一下倦逐。