標籤:

git合併分支,為什麼會比svn容易?

我們一直使用svn作為版本控制服務。具體用法是,在svn中建2個庫 :開發庫和測試庫。開發人員平時在開發庫工作,當完成代碼後,使用beyond compare等比較工具將代碼合併到測試庫。這種做法能覆蓋大多數場景。

不過也有例外,幾個月前我們有一個大模塊要上線,為了不和日常開發衝突,我們從主分支里拉了一個新分支出來,大模塊的功能代碼都提交到新分支上。等到這個模塊開發完畢,需要合併回主分支的時候,麻煩就大了:經過幾個月的發展,兩個分支之間的代碼已經千差萬別,有些代碼段甚至是排他性修改,因此,合併起來異常痛苦。

我在網上搜了一下有沒有好的解決辦法,很多人提到,用git。例如這篇文章提到svn合併分支的窘態,和我們很像:

SVN的分支合併

當你在一個分支上工作數周或幾個月之後,主幹的修改也同時在進行著,兩條線的開發會區別巨大,當你想合併分支回主幹,可能因為太多衝突,已經無法輕易合併你的分支和主幹的修改。

另一個問題,Subversion不會記錄任何合併操作,當你提交本地修改,版本庫並不能判斷出你是通過svn merge還是手工修改得到這些文件。所以你必須手工記錄這些信息(說明合併的特定版本號或是版本號的範圍)。

要解決以上的問題只有通過有規律的將主幹合併到分支來避免,制定這樣一個政策:每周將上周的修改合併到分支,注意這樣做時需要小心,你必須手工記錄合併的過程,以避免重複的合併,你需要小心的撰寫合併的日誌信息,精確的描述合併包括的範圍。這樣做看起來有點像是脅迫。

這篇文章提到Git合併分支很容易,似乎是我們要的答案:

處理GIT的分支卻是相當的簡單和有趣。你可以從同一個工作目錄下快速的在幾個分支間切換。你很容易發現未被合併的分支,你能簡單而快捷的合併這些文件。

但是,我有一點疑惑,像我們這種情況,即使是那段代碼的開發人員使用beyond compare合併代碼都覺得困難,git怎麼能完成合併呢?


Gir的軟文有誇大的成分……

當:

兩個分支之間的代碼已經千差萬別,有些代碼段甚至是排他性修改

沒有什麼東西能讓合併成為一件簡單的事情。

誠然,SVN在設計之初是沒有將合併分支考慮在內的,但是SVN也並非像那些文章所說的無法記錄合併記錄。如果你正確的操作SVN,那麼合併記錄是會記錄在SVN屬性裡面的。但這些都無法解決兩個獨立發展很長一段時間的分支的合併,Git從數據結構上更好的支持了分支合併,但我們都知道合併的麻煩程度總是取決於衝突的數量……


我工作中用過CC,用過SVN,現在用GIT。在使用這些工具的時候我從來沒有期待過他們一定能幫我解決所有的合併操作,因為代碼是在被人寫的,在解決合併衝突這方面,這三個工具並沒有很大的實質差別。

版本控制只是工具,被控制的內容才是應該關注的核心,對我們來說就是代碼。

我見過好多人都覺得版本控制做merge自動給你resolve衝突天經地義。有這種想法的人還處於不太懂得協作的階段。多人開發如果沒有事前溝通而形成了具有衝突的多個branch,簡單的例子,一個常量在A Branch被修改為了1,在B Branch被修改為了2,這兩個commit在合併到一個Branch的時候沒有什麼工具能自動決策的,這是無法避免的衝突。必須當事人協商然後手動Resolve。舉這個簡單的例子是想說,衝突來自於團隊協作中存在信息不對稱問題,這是團隊和項目劃分問題,不是工具不夠智能。題主這種主流和分支流並行開發的行為本來就預先埋下了產生衝突的可能,既然選擇了這種開發模式,就要做好手動解決衝突的準備,沒有什麼人工智慧可以幫你決策來自兩個大腦的權重平等的不同想法,在svn下的衝突換到git還是照樣衝突。


兩個分支經過長期的隔離發展已經產生了生殖隔離(霧)

強行撮合它們的後果就是

1 無法產生後代:自動合併失敗

2 產生無法生育的後代:全是不可思議BUG,無法繼續推進項目,但是功能的整合使得其某些方面的能力得到提升

所以為了讓他們合在一起,要想辦法篡改歷史,把變化一個接一個的合併進去,仔細處理,而不是一口氣搞進去。

至於svn和git,我覺得他們倆在這個方面最大的差別應該是創建分支的代價,而不是合併的簡易程度。

其實我覺得代碼合併還是誰污染誰治理比較好,很難有人會比代碼作者更了解自己的代碼,在PR被merge進去前讓代碼作者自己處理衝突是最方便的。


問題不是出在工具,而是流程。

從主分支里拉了一個新分支出來,在合併回主分支之前,必須持續地把主分支的更改儘早儘快合併到新分支。新分支永遠保持 最新主幹代碼+新模塊代碼 的狀態。


樓上各位大哥都沒說到點子上,題主問的其實很簡單。

1. 因為你merge代碼的時候,用BC除非沒有衝突的文件,只要有add和delete操作的文件你都要逐個逐行進行處理啊,更別提有衝突的文件了。用git做merge無衝突文件且版本號高於master分支就自動幫你解決了,你只需要解決衝突就行;

2. git的主流用法是「做一件事情,new一個分支」,這樣你在開發併合並之前不會merge到別人的測試中非上線代碼,就會少很多衝突。如果像你之前SVN那麼做,上線之前大家都提到develop上,一不小心本地就摻進非上線代碼了。你合到master上還得往出摘,跟屎里挑韭菜似的,多噁心啊。

最後仍然強調不管CVS、SVN還是GIT都無法自動幫你解決衝突,拉屎韭菜多就得人工挑,要不別吃那麼多韭菜啊。


git合併分支容易的原因是,要經常和master分支merge,這樣把衝突消滅在萌芽狀態。

比如我每天下班前的最後一件事就是先從master拉一下,看看自己改的有沒有和master衝突,然後再提交到自己的分支。這樣自己的分支和master合併的時候,基本不會出現衝突。

然後勤開分支,一個小需求就開一個分支。快速寫完,寫完就提測,測試完就和master合併。


也不是說用git就一定更好合併,畢竟合併難度的本質在於衝突數量。但是git的好處是在於你在開發分支的時候可以很容易地隨時與主分支同步。這樣即使主分支繼經過了上月的開發你也可以很輕易的合併。


別空想了,建一個git,開幾個分支試試就好了。

看看git怎麼處理有衝突的代碼。如果svn讓你痛不欲生,git會再讓你感受一次。


git 合併分支的時候,如果有衝突,也需要你手動操作。選擇保留哪些內容,刪除哪些內容。

不過 git 創建分支的代價很小,所以我們經常是一個分支解決一個問題或者需求,搞定之後,就合併到 master 或者 development。而不是創建一個分支,做很多事情之後再合併。


兩個合併都是一樣的,有衝突改衝突,沒有衝突的自動合併。說句題外話,git好的地方在於,可以輕鬆開分支,而且還是本地的,可以非常容易的切換分支,這個常用SVN比較難體會到那種爽快,任何修改功能都可以開一個新分支,一邊改,同時及時的把主幹別人提交的東西合併的到你自己的分支里來,因為合併及時,衝突都不會多,最後你的功能改好之後合併到主幹,那麼衝突就會非常少,最後強調一下,你開的分支是本地的,完全不需要糾結,想開就開。如果一直使用svn的可以嘗試使用git,然後會對svn的用法也有新的改觀,兩個軟體都很好


你需要動用bc時,說明自動合併失敗,需要手工解決衝突,這時候不管是用git還是svn,都很麻煩。

git在自動合併上表現比svn好一些,會稍微減少衝突的數量,但如果換成git後沿用svn時的工作流程,你並不會輕鬆很多。

關鍵是git的典型使用方式,會使得branch和merge/rebase成為update、commit一樣的日常操作。這樣,雖然你要解決的總的衝突數量也許沒有減少,但從一次性處理大量衝突,變成時不時解決一兩個衝突,顯著降低了心智負擔。


誰告訴你容易了?這和你兩個分支的差異有關,如果天差地別的話,就沒有意義。

如果是feature分支的話,確保分支代碼不會和主幹衝突。


推薦閱讀:

git: 為什麼 pull request 不叫 push request ?
github上有哪些好的C開源項目?
git本地倉庫關聯多個remote,怎麼用本地一個分支向不同remote不同分支推送代碼?
如何在 GitHub 下載某個程序的特定版本(代碼)?
gitlab或github下fork後如何同步源的新更新內容?

TAG:Git | SVNSubversion |