記一次"詭異"的git merge錯誤

前言

今天照常開發(fā),在日常部署測試的時候進(jìn)行g(shù)it merge 竟然出現(xiàn)了"代碼丟失"的情況,相當(dāng)詭異,特此記錄烤惊。

問題由來

首先介紹下公司的日常發(fā)布測試的策略,公司使用git進(jìn)行代碼管理吁朦。如果某應(yīng)用同時有多人開發(fā),采用的方式是A會基于master新建feature_a分支渡贾,B基于master新建feature_b分支逗宜,然后在日常測試部署的時候通常會新建一個新的tag分支,如tag/20160711_test_xxxx空骚,然后將要測試部署的分支feature_a和feature_b合并到tag分支上去纺讲,然后使用tag分支部署并且測試。這樣做是完全沒有問題的囤屹,但是詭異的事情發(fā)生了熬甚,今天這么操作的時候合并出的tag分支丟了一行import,mavan編譯一直出錯

問題描述與分析

最開始碰到這個問題的時候我一直以為是發(fā)布構(gòu)建系統(tǒng)的問題(公司內(nèi)部系統(tǒng))肋坚,后來又懷疑是我在解決merge沖突的時候手賤刪除了這行乡括,重新merge還是出現(xiàn)這個問題。后來由于還得開發(fā)其他功能智厌,想著要不先讓feature_b分支先單獨(dú)發(fā)布測試好了诲泌。一直到下午手里的事情忙完了準(zhǔn)備搞定這個問題,發(fā)現(xiàn)同事feature_b分支還是沒有測試好铣鹏,想著不能等他了敷扫,開始著手解決這個問題。

問題描述如下,feature_a和feature_b同時修改了某個文件xx.java诚卸,feature_a上xx.java大概類似于:

package xxx.xx
import com.xx.xx.A
import com.xx.xx.Common

class xx {
  public void commonMethod(Common common){
  }

  public void aSpecMethod(A a){
  }
}

feature_b上的xx.java大概類似于:

package xxx.xx
import com.xx.xx.B
import com.xx.xx.Common

class xx {
  public void commonMethod(Common common){
  }

  public void bSpecMethod(B b){
  }
}

按理說合并出來的代碼應(yīng)該類似于:

package xxx.xx
import com.xx.xx.A
import com.xx.xx.B
import com.xx.xx.Common

class xx {
  public void commonMethod(Common common){
  }

  public void aSpecMethod(A a){
  }

  public void bSpecMethod(B b){
  }

}

但是最終合并出來的代碼卻是類似于這樣:

package xxx.xx
import com.xx.xx.B
import com.xx.xx.Common

class xx {
  public void commonMethod(Common common){
  }

  public void aSpecMethod(A a){
  }

  public void bSpecMethod(B b){
  }

}

筒子們發(fā)現(xiàn)問題了嗎葵第,NMmerge之后丟了import com.xx.xx.A這樣绘迁,maven編譯一直報解析不了A的錯誤,A都沒引進(jìn)來卒密,能解析就怪了...

我也是年輕呀缀台,開始的一個小時一直糾結(jié)在是不是這個發(fā)布系統(tǒng)的問題(哈哈,對不起栅受,讓你背鍋了)将硝,后來開始仔細(xì)研究git merge的原理,期間看到了How-does-Git-merge-work這篇文章講得比較通透屏镊。git merge的原理簡單來說就是x+y-w的過程依疼,其中w是x+y的merge base(也就是最近公共祖先),也即是說把y-w(y分支對w分支的改動)patch到x分支上而芥,或者說是把x-w(x分支對w分支的改動)patch到y(tǒng)分支上律罢,具體的做法就是:

merge過程

在知道原理之后就開始查看feature_b和feature_a分支分別對于xx.java文件的改動,發(fā)現(xiàn)feature_b(同事分支)將import com.xx.xx.A這句刪掉了(看到這我就應(yīng)該反應(yīng)過來的棍丐,但是我還是太連清...)误辑,我當(dāng)時想你刪了就刪了唄,我在feature_a分支引用進(jìn)來了呀歌逢,最后合并肯定還是存在的嘛(我承認(rèn)自己沒仔細(xì)想)巾钉,我接著checkout 到feature_a看了下,有import com.xx.xx.A這句呀秘案,最后合并的時候肯定應(yīng)該有的呀砰苍,git merge肯定不能因?yàn)槟承┓种h了這行就不新增其他分支的代碼,心中一千匹草泥馬在奔騰呀Z甯摺W肌!赤惊!

但是...重要的是但是吼旧,我知道git merge首先會找他們的merge base,會基于這個合并未舟,在該場景里應(yīng)該是master(feature_a和feature_b都是基于master新建的)圈暗,我就checkout到了master上查看了下,發(fā)現(xiàn)master上赫然存在import com.xx.xx.A這行(當(dāng)時xx.java沒有并沒有引用到A.java類裕膀,這個import是多余的)厂置,我瞬間反應(yīng)過來問題了!魂角!

問題解決-真相大白

問題就在于x+y-w時和w是強(qiáng)相關(guān)的昵济,而在這個案例里面,w(也就是master)的代碼為:

package xxx.xx
import com.xx.xx.A
import com.xx.xx.Common

class xx {
  public void commonMethod(Common common){
  }

master中雖然沒有引用A,但是卻把A引進(jìn)來了(應(yīng)該是某次刪除代碼的時候忘了把Import刪掉了)

先分析下xx.java的合并過程吧
x:代表feature_a
w:master
y:代表feature_b
合并過程為x+(y-w)
y-w在這個過程中表現(xiàn)
增加

-import com.xx.xx.A
+import com.xx.xx.B
+public void bSpecMethod(B b){
+}

x為

package xxx.xx
import com.xx.xx.A
import com.xx.xx.Common

class xx {
  public void commonMethod(Common common){
  }

  public void aSpecMethod(A a){
  }
}

合并出來的代碼應(yīng)該為

package xxx.xx
import com.xx.xx.B
import com.xx.xx.Common

class xx {
  public void commonMethod(Common common){
  }

  public void aSpecMethod(A a){
  }


public void bSpecMethod(B b){
}

}

哈哈访忿,import com.xx.xx.A就這么丟了瞧栗,而且還就應(yīng)該丟,丟才是正確的海铆!

筒子們迹恐,看出來問題了嗎,問題就在于同事B看到xx.java中A并沒有被引用的時候把A 的import干掉了卧斟,而我在xx.java中加入的方法剛好用到了A(我以為A是我import進(jìn)去的殴边,沒想到竟然master上竟然存在),造成結(jié)果就是git 記住的改動是feature_b把A的import干掉了珍语,feature_a對這個import沒有修改锤岸,結(jié)果就是...

知道了原因,解決就很簡單了板乙,故意將Import A挪個位置并Push讓git意識到change是偷,這樣下次merge的時候git既會知道feature_b的改動也會知道feature_a的改動會觸發(fā)一次merge conflict,然后手動解決就好了

警示

在對類進(jìn)行修改刪除了某些方法時募逞,一定要將無用的import清理掉蛋铆,保持import區(qū)的干凈!7沤印刺啦!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市纠脾,隨后出現(xiàn)的幾起案子洪燥,更是在濱河造成了極大的恐慌,老刑警劉巖乳乌,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異市咆,居然都是意外死亡汉操,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門蒙兰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來磷瘤,“玉大人,你說我怎么就攤上這事搜变〔筛浚” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵挠他,是天一觀的道長扳抽。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么贸呢? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任镰烧,我火速辦了婚禮,結(jié)果婚禮上楞陷,老公的妹妹穿的比我還像新娘怔鳖。我一直安慰自己,他們只是感情好固蛾,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布结执。 她就那樣靜靜地躺著,像睡著了一般艾凯。 火紅的嫁衣襯著肌膚如雪献幔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天览芳,我揣著相機(jī)與錄音斜姥,去河邊找鬼。 笑死沧竟,一個胖子當(dāng)著我的面吹牛铸敏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悟泵,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼杈笔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了糕非?” 一聲冷哼從身側(cè)響起蒙具,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎朽肥,沒想到半個月后禁筏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡衡招,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年篱昔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片始腾。...
    茶點(diǎn)故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡州刽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出浪箭,到底是詐尸還是另有隱情穗椅,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布奶栖,位于F島的核電站匹表,受9級特大地震影響门坷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桑孩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一拜鹤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧流椒,春花似錦敏簿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绣硝,卻和暖如春蜻势,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鹉胖。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工握玛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甫菠。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓挠铲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親寂诱。 傳聞我的和親對象是個殘疾皇子拂苹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容