標籤:

如何克服解決 Git 衝突的恐懼症?

我們有一個課程項目,4個人參與,使用 Java 開發。為了解決我們互相拿U盤拷代碼的不方便,我費了十分大的力氣說服他們使用 Git 並教會他們基本的操作。但是使用Git 不可避免的會產生編輯衝突。

可是除了我以外其他的同學都害怕解決衝突。可能認為解決衝突太麻煩。

於是每到周末,我們的課程項目進度就會停兩天,周一我要親自去給他們解決衝突。

大家有沒有好的方法或者是好的工具能克服解決 Git 衝突的恐懼症?


首先,如果一直是這樣大量的衝突,說明是分工的不對。沒法把任務切乾淨。這樣的話,不管是用git,還是用hg,還是用svn,還是用p4,都會出現一樣的衝突。

第二,你如果用的是git,就應該用rebase,而不是merge。那樣的話是在pull的時候就自行在本地解決兩路衝突,而不用到merge的時候來個麻煩的多路merge。這才是git的正確使用方式。

第三,如果連rebase的兩路衝突都無法克服,那就說明做不了這行。


蟹妖,我覺著吧,初學者有分支恐懼症,rebase恐懼症,conflict恐懼症都可以理解啊!幫不上忙就算了,還在那說風涼話,秀優越……我賭五毛你們都沒有女盆友。

  1. 根本方法:掌握Git基礎之後,玩一玩有我參與漢化校閱的 Learn Git Branching 小遊戲,該web app完全由前端實現,實在是pcottle大大的傑作,在全世界範圍內聲名遠揚。特點是:由淺入深,一天精通,包教包會,學不會不收錢(學會了也不收錢)。結果是:用人單位搶著要,交錢預定都滿足不了!

  2. 治標方法,立竿見影,從此神經比較大,就再也不怕不怕不怕啦!——「熟練掌握reflog+reset。」告訴你後悔葯是如何吃的,這就跟學車是一樣的道理,一定要先學會踩剎車,心裡才有底。不過,初次接觸 reflog 的界面的童鞋很可能會不太熟悉,不知道怎麼退出去,不要害怕,谷歌會給你答案。

  3. 輔助方法,裝個好的前端比如 SourceTree,一般性的操作,都可以不用指令,出了錯有UI界面解決衝突時只需動動滑鼠,輕鬆加寫意。


用sourcetree, smartgit這些界面比較友好的工具應該能解決大部分小團隊做小型項目遇到的問題吧


所以我招程序員的時候只有一個硬性要求就是會用 git 和 github,這也算是自學能力的一個測試吧,如果連 Pro Git 和 NodeSchool 的 git-it 這樣優秀的教材都看不下去,也不用想再培養別的能力了。


說服無效、威逼無效、懇求無效。然後知道能掌控的只有自己,何必強求他人。既然git人家玩不轉也不想玩,就定好介面,各自負責各自模塊唄。

沒有什麼git衝突恐懼症,只是不想學,這方面的內因缺失你是幫不上忙的。


我這邊遇到的更嚴重的問題是

github服務不穩定....

以及它是英文網站....

其實衝突並不常見,很少會遇到衝突問題。

前提是在開發之處做好分工的話,整理好架構。

嘛。。現在我把項目放在開源中國了......


《人月神話》里講了 accidental complexity 和 essential complexity。看這道題的答案,這麼久過去了,大多數人還是不知道有這兩種 complexity。

Git 有什麼難學的。Git 的難點都是 accidental complexity。如果只用 cmd 你當然覺得難學。有個好的可視化工具 visualize 一下 logs 就全齊了。裝 SourceTree 就行了。然後要做什麼操作之前如果拿不準可以用個例子 repository 做做實驗。


工具很重要,對於衝突恐懼症,我推薦tortoisegit和beyondcompare的組合,在解決衝突這一點上,這是我用過的最好的兩個工具。

註:我的工作內容導致我幾乎每天都要合併超過100+源代碼文件,平均每天要解決30+的衝突,也許linus同志在命令行下也乾的很愉快,但對我而言,tortoisegit和beyondcompare是我能找到的效率最高的工具組合。是的,我乾的事情和linus還真是差不多,每天都要大量合併代碼。


強制練習


其實就是怎麼解決懶的問題。。


首先我想說像git,vim之類的工具用不來只會浪費時間,降低效率。

當然,他們本身確實是牛X的工具,但前提是你要會用,這些個工具學習成本都不低。特別是還不會用的時候就上正式項目,效率打折,萬一丟數據就更慘。所以平常自己先玩玩試試。


我在公司里也遇到過這樣的事兒。剛來的實習生以前只用過svn,然後教他用git。基本的都會,就是解決衝突的時候老要出問題。然後又一次merge代碼直接把我的代碼merge沒了,程序跑起來出問題。然後我去查log發現是實習生merge的時候有衝突,沒解決好給merge沒了。那次之後實習生就更不敢merge代碼了,已有衝突就開始慌。後來我覺得這樣也不行啊,於是就把我們每天類似日報一樣的記錄一些數據的活兒改成了一個git項目,讓他們每天記錄好後用git同步,每天都練。自己也帶著實習生一起做了幾次merge,多練幾次,多merge幾次情況就好多了。其實說再多,也不過是一個道理。唯手熟爾。多學多練就好。


開發軟體項目不用源代碼版本控制簡直是不可思議,你可以讓其他三個隊友退學了。


最近也在Java團隊里推git,說說自己的經驗。Java開發中的衝突很多是因為依賴 IDE 生成大塊代碼或配置文件導致。衝突對新手的確麻煩,但我認為拷貝代碼問題更大啊。我的建議有:

1,配置 .gitignore 忽略不必要的文件

2,規劃模塊,盡量避免修改同一頁面

3,告訴他們只需要遵循一點就不會出事:pull前一定要全部 commit

4,使用github或自己架個gitlab(如果有人恐懼英文國內也有幾個不錯的託管平台),一個特別方便的功能是在網頁上看每次的修改記錄,這個比客戶端什麼的好用多了。

5,作為推行人多做代碼 review

街邊手機碼字,差不多就這些


衝突的根源在哪裡?想過沒?

如果這個模塊是我負責的,那我遞交時為何會發現被別人改了?

所以,減少衝突的關鍵在於組織和分工、溝通和習慣。


課程項目重來不都是一個人寫的嗎,居然還真的一起做啊


代碼衝突大多是代碼設計不合理的表現。這裡簡單說一下, 個人對編程設計的一些基本原則簡單理解. 對避免代碼衝突應該會有些幫助. (注意, 這裡講的是避免, 而克服. 預防遠重於治療, 因為成本更小, 效果更佳)

SRP原則Single Responsibility Principle

說說個人的理解, 供大家參考. 這裡以大多系統對用戶的設計為例.

之前的做法: 創建一個user的類, 處理所有用戶的行為. 登錄, 添加一個login方法, 登出, 添加一個logout方法. 馬上問題就來了, 我們要修改密碼, 修改昵稱, 修改基本資料...這個類就越變越大了. 代碼衝突只是小事, 對登出的修改, 可能會讓登錄失敗.

之後的做法: 一種行為一個類. 登錄一個類, 登出一個類, 修改密碼一個類...

再進一步: 登錄的行為需要再拆分: 通過郵箱登錄, 通過手機登錄, 通過微信登錄...

開放與封閉

拓展介面,而非修改實現. 我的理解, 是變與不變. 以微信, 微博等第三方登錄為例: 不變的是, 他們幾乎都遵照OAuth2, 變的是具體實現. 代碼設計時, 需要將不變的東西, 抽象成介面. 所以, 實現微信登錄後, 再做微博登錄, 不應該去修改原來微信登錄的代碼, 而是擴展實現OAuth2的介面.

至上而下

何為上, 調用的代碼為上, 被調用的為下; 使用方為上, 實施方為下; 用戶為上, 寫代碼的為下. 需求提出方為上, 需求實現方為下. 所以, 往往, 代碼混亂的源頭是需求

以下幾個user story為例:

  1. 作為一般用戶, 我想要登錄到系統, 因為...(略去原因和criteria, 這些都很重要, 尤其是原因極其重要, 只是與此處問題無關, 估略去了)
  2. 作為一般用戶, 我想要從系統中退出, 因為...
  3. 作為管理員, 我想查看系統中的用戶, 因為...
  4. 作為管理員, 我想能夠屏蔽用戶, 因為...

使用者的不同, 是我們拆分模塊的重要依據. 簡單的說, 針對一般用戶功能的代碼扔到一處, 針對管理員功能的代碼扔到另一處. 不同的用戶, 不同的場景, 會有不同的行為, 不同的行為意味著不同的代碼. 相對應的代碼的架構設計, 也是遵照, 不同的用戶, 不同的場景進行設計.

更多資料, 可以參考&, &, &

說實話, 這些書都很難啃, 而且啃完後, 對於像我這樣智商偏低的童鞋, 該踩的坑, 幾乎一個都跑不掉. 所以, 多次磕磕碰碰後, 體會最深, 也是最行之有效的方法, 就是少量多次. 錯誤總是要犯的, 那就讓它來得儘可能早, 花費時間儘可能少, 產生影響儘可能少.

"世上本沒有路,走的人多了,便變成了路"
"本沒有什麼方法和原則, 嘗試的多了, 自然就用了"

少量多次

就此, 對於寫代碼的一些建議, 可以有效避免代碼衝突.

  1. 文件數量可以多, 但單個文件代碼要少,盡量不要過百行
  2. 頻繁多次commit, 每次commit只解決一個問題,哪怕只是改一個符號
  3. 頻繁多次code review, 每次code review只針對一個任務,需要控制代碼量, 近千行的代碼審核是一個災難
  4. 頻繁多次merge

git的工作流可以參考: A successful Git branching model


原來是15年的提問。

其實現在已經沒這個問題了。

比如,不提交不能push,有衝突不能push,節點落後不能push。

所以養成push之前先pull的習慣。至少代碼不會亂。

至於為什麼有這麼多衝突?那就是項目管理上的問題了。


我覺得恐懼症的根源是不夠熟悉git。

不夠熟悉,就會有一種「這個問題我或許會處理不了」的恐懼。更深層次的恐懼是「卡在某個中間狀態進退不得」的恐懼。

其實你掌握熟悉以後就知道中間狀態一般git reset --hard或者git rebase --abort就沒了,就不害怕了。


大部分IDE 集成的git 都很好用了,ui界面很直觀,解決衝突最怕的就是別人修改了你正在大改的代碼,這時最好是新建一個分支出去,及時跟蹤原來的分支,然後代碼始終保持最新的狀態再合併。

平時開發的時候要注意,各司其職不要隨意變動別人寫的代碼,不要多人同時修改一個文件,代碼要及時保存。

建議用source tree這個工具,中文界面交互,傻瓜式操作,滑鼠一點,你就知道。


推薦閱讀:

如何評價開源中國的碼雲?
我們可以使用 Git 以及 GitHub 做哪些事情?
github怎麼綁定自己的域名?
Github 上怎樣把新 commits 使用在自己的 fork 上?
如何評論開源中國的山寨Github?

TAG:Git | GitHub |