git-merge完全解析
Git的git-merge是在Git中頻繁使用的一個命令魄梯,很多人都覺得git合并是一個非常麻煩的事情咕娄,一不小心就會遇到丟失代碼的問題肌访,從而對git望而卻步。本文基于Git 2.8.2對git-merge命令進(jìn)行完整詳細(xì)的介紹杏慰,特別是關(guān)于交叉合并所帶來的代碼遺失問題捣作,在文末給出自己的建議誉结,希望能夠幫助到git的使用者。本文所介紹的內(nèi)容基于Git 2.8.2
git-merge命令是用于將兩個或兩個以上的開發(fā)歷史合并在一起的操作虾宇,通常也可寫作:git merge搓彻。
1.git-merge相關(guān)的選項參數(shù)
1.1摘要
在git-merge命令中如绸,有以下三種使用參數(shù):
git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]] [--[no-]rerere-autoupdate] [-m <msg>] [<commit>...]
git merge <msg> HEAD <commit>...
git merge --abort
1.2git-merge簡介
git-merge命令是用于從指定的commit(s)合并到當(dāng)前分支的操作。
注:這里的指定commit(s)是指從這些歷史commit節(jié)點開始旭贬,一直到當(dāng)前分開的時候怔接。
git-merge命令有以下兩種用途:
- 用于git-pull中,來整合另一代碼倉庫中的變化(即:git pull = git fetch + git merge)
- 用于從一個分支到另一個分支的合并
假設(shè)下面的歷史節(jié)點存在稀轨,并且當(dāng)前所在的分支為“master”:
那么
git merge topic
命令將會把在master分支上二者共同的節(jié)點(E節(jié)點)之后分離的節(jié)點(即topic分支的A B C節(jié)點)重現(xiàn)在master分支上扼脐,直到topic分支當(dāng)前的commit節(jié)點(C節(jié)點),并位于master分支的頂部奋刽。并且沿著master分支和topic分支創(chuàng)建一個記錄合并結(jié)果的新節(jié)點瓦侮,該節(jié)點帶有用戶描述合并變化的信息。
即下圖中的H節(jié)點佣谐,C節(jié)點和G節(jié)點都是H節(jié)點的父節(jié)點肚吏。
1.3git merge <msg> HEAD <commit>...
命令
該命令的存在是由于歷史原因,在新版本中不應(yīng)該使用它狭魂,應(yīng)該使用git merge -m <msg> <commit>....
進(jìn)行替代
1.4git merge --abort
命令
該命令僅僅在合并后導(dǎo)致沖突時才使用罚攀。git merge --abort
將會拋棄合并過程并且嘗試重建合并前的狀態(tài)。但是雌澄,當(dāng)合并開始時如果存在未commit的文件斋泄,git merge --abort
在某些情況下將無法重現(xiàn)合并前的狀態(tài)。(特別是這些未commit的文件在合并的過程中將會被修改時)
警告:運(yùn)行
git-merge
時含有大量的未commit文件很容易讓你陷入困境镐牺,這將使你在沖突中難以回退炫掐。因此非常不鼓勵在使用git-merge
時存在未commit的文件,建議使用git-stash
命令將這些未commit文件暫存起來睬涧,并在解決沖突以后使用git stash pop
把這些未commit文件還原出來募胃。
2.參數(shù)
本部分用于介紹git-merge
命令中使用的參數(shù)
2.1--commit
和--no-commit
--commit
參數(shù)使得合并后產(chǎn)生一個合并結(jié)果的commit節(jié)點。該參數(shù)可以覆蓋--no-commit
畦浓。
--no-commit
參數(shù)使得合并后摔认,為了防止合并失敗并不自動提交,能夠給使用者一個機(jī)會在提交前審視和修改合并結(jié)果宅粥。
2.2--edit
和-e
以及--no-edit
--edit
和-e
用于在成功合并、提交前調(diào)用編輯器來進(jìn)一步編輯自動生成的合并信息电谣。因此使用者能夠進(jìn)一步解釋和判斷合并的結(jié)果秽梅。
--no-edit
參數(shù)能夠用于接受自動合并的信息(通常情況下并不鼓勵這樣做)。
如果你在合并時已經(jīng)給定了
-m
參數(shù)(下文介紹)剿牺,使用--edit
(或-e
)依然是有用的企垦,這將在編輯器中進(jìn)一步編輯-m
所含的內(nèi)容。
舊版本的節(jié)點可能并不允許用戶去編輯合并日志信息晒来。
2.3--ff
命令
--ff
是指fast-forward命令钞诡。當(dāng)使用fast-forward模式進(jìn)行合并時,將不會創(chuàng)造一個新的commit節(jié)點。默認(rèn)情況下荧降,git-merge
采用fast-forward模式接箫。
關(guān)于fast-forward模式的詳細(xì)解釋,請看我的另一篇文章:一個成功的Git分支模型的“關(guān)于fast forward”一節(jié)朵诫。
2.4--no-ff
命令
即使可以使用fast-forward模式辛友,也要創(chuàng)建一個新的合并節(jié)點。這是當(dāng)git merge
在合并一個tag時的默認(rèn)行為剪返。
2.5--ff-only
命令
除非當(dāng)前HEAD節(jié)點已經(jīng)up-to-date(更新指向到最新節(jié)點)或者能夠使用fast-forward模式進(jìn)行合并废累,否則的話將拒絕合并,并返回一個失敗狀態(tài)脱盲。
2.5 --log[=<n>]
和 --no-log
--log[=<n>]
將在合并提交時邑滨,除了含有分支名以外,還將含有最多n個被合并commit節(jié)點的日志信息钱反。
--no-log
并不會列出該信息掖看。
2.6 --stat
, -n
, --no-stat
命令
--stat
參數(shù)將會在合并結(jié)果的末端顯示文件差異的狀態(tài)。文件差異的狀態(tài)也可以在git配置文件中的merge.stat配置诈铛。
相反乙各,-n
, --no-stat
參數(shù)將不會顯示該信息。
2.7--squash
和--no-squash
--squash
當(dāng)一個合并發(fā)生時幢竹,從當(dāng)前分支和對方分支的共同祖先節(jié)點之后的對方分支節(jié)點耳峦,一直到對方分支的頂部節(jié)點將會壓縮在一起,使用者可以經(jīng)過審視后進(jìn)行提交焕毫,產(chǎn)生一個新的節(jié)點蹲坷。
注意1:該參數(shù)和
--no-ff
沖突
注意2:該參數(shù)使用后的結(jié)果類似于在當(dāng)前分支提交一個新節(jié)點。在某些情況下這個參數(shù)非常有用邑飒,例如使用Git Flow時(關(guān)于Git Flow循签,請參考:一個成功的Git分支模型),功能分支在進(jìn)行一個功能需求的研發(fā)時疙咸,開發(fā)者可能在本地提交了大量且無意義的節(jié)點县匠,當(dāng)需要合并到develop分支時,可能僅僅需要用一個新的節(jié)點來表示這一長串節(jié)點的修改內(nèi)容撒轮,這時
--squash
命令將會發(fā)揮作用乞旦。此外,如果功能分支的多次提交并不是瑣碎而都是有意義的题山,使用--no-ff
命令更為合適兰粉。
--no-squash
的作用正好相反。
2.8 -s <strategy>
和 --strategy=<strategy>
-s <strategy>
和 --strategy=<strategy>
用于指定合并的策略顶瞳。默認(rèn)情況如果沒有指定該參數(shù)玖姑,git將按照下列情況采用默認(rèn)的合并策略:
- 合并節(jié)點只含有單個父節(jié)點時(如采用fast-forward模式時)愕秫,采用recursive策略(下文介紹)。
- 合并節(jié)點含有多個父節(jié)點時(如采用no-fast-forward模式時)焰络,采用octopus策略(下文介紹)戴甩。
2.9 -X <option>
和 --strategy-option=<option>
在-s <strategy>
時指定該策略的具體參數(shù)(下文介紹)。
2.10 --verify-signatures
, --no-verify-signatures
用于驗證被合并的節(jié)點是否帶有GPG簽名舔琅,并在合并中忽略那些不帶有GPG簽名驗證的節(jié)點等恐。
(以下引用摘自一篇轉(zhuǎn)載的文章,由于我沒有找到原作者备蚓,因此無法提供原作者信息和原文鏈接课蔬,如果有所侵權(quán)請私信或者評論告知,我將刪除以下引用內(nèi)容郊尝。)
GPG是加密軟件二跋,可以使用GPG生成的公鑰在網(wǎng)上安全的傳播你的文件、代碼流昏。
為什么說安全的扎即?以Google所開發(fā)的repo為例,repo即采用GPG驗證的方式况凉,每個里程碑tag都帶有GPG加密驗證谚鄙,假如在里程碑v1.12.3處你想要做修改,修改完后將這個tag刪除刁绒,然后又創(chuàng)建同名tag指向你的修改點闷营,這必然是可以的。但是知市,在你再次clone你修改后的項目時傻盟,你會發(fā)現(xiàn),你對此里程碑tag的改變不被認(rèn)可嫂丙,驗證失敗娘赴,導(dǎo)致你的修改在這里無法正常實現(xiàn)。這就是GPG驗證的作用跟啤,這樣就能夠保證項目作者(私鑰持有者)所制定的里程碑別人將無法修改诽表。那么,就可以說隅肥,作者的代碼是安全傳播的关顷。
為什么會有這種需求?一個項目從開發(fā)到發(fā)布武福,再到后期的更新迭代,一定會存在若干的穩(wěn)定版本與開發(fā)版本(存在不穩(wěn)定因素)痘番。作為項目發(fā)起者捉片、持有者平痰,有權(quán)定義他(們)所認(rèn)可的穩(wěn)定版本,這個穩(wěn)定版本伍纫,將不允許其他開發(fā)者進(jìn)行改動宗雇。還以Google的repo項目為例,項目所有者定義項目開發(fā)過程中的點A為穩(wěn)定版v1.12.3莹规,那么用戶在下載v1.12.3版本后赔蒲,使用的肯定是A點所生成的項目、產(chǎn)品良漱,就算其他開發(fā)者能夠在本地對v1.12.3進(jìn)行重新指定舞虱,指定到他們修改后的B點,但是最終修改后的版本給用戶用的時候母市,會出現(xiàn)GPG簽名驗證不通過的問題矾兜,也就是說這樣的修改是不生效的。
2.11 —summary
,--no-summary
和--stat
與 --no-stat
相似患久,并將在未來版本移除椅寺。
2.12 -q
和 --quiet
靜默操作,不顯示合并進(jìn)度信息蒋失。
2.13 -v
和 --verbose
顯示詳細(xì)的合并結(jié)果信息返帕。
2.14 --progress
和 --no-progress
切換是否顯示合并的進(jìn)度信息。如果二者都沒有指定篙挽,那么在標(biāo)準(zhǔn)錯誤發(fā)生時荆萤,將在連接的終端顯示信息。請注意嫉髓,并不是所有的合并策略都支持進(jìn)度報告观腊。
2.15-S[<keyid>]
和 --gpg-sign[=<keyid>]
GPG簽名。
2.16-m <msg>
設(shè)置用于創(chuàng)建合并節(jié)點時的提交信息算行。
如果指定了--log
參數(shù)梧油,那么commit節(jié)點的短日志將會附加在提交信息里。
2.17--[no-]rerere-autoupdate
rerere即reuse recorded resolution州邢,重復(fù)使用已經(jīng)記錄的解決方案儡陨。它允許你讓 Git 記住解決一個塊沖突的方法,這樣在下一次看到相同沖突時量淌,Git 可以為你自動地解決它骗村。
2.18--abort
拋棄當(dāng)前合并沖突的處理過程并嘗試重建合并前的狀態(tài)。
3.關(guān)于合并的其他概念
3.1合并前的檢測
在合并外部分支時呀枢,你應(yīng)當(dāng)保持自己分支的整潔胚股,否則的話當(dāng)存在合并沖突時將會帶來很多麻煩。
為了避免在合并提交時記錄不相關(guān)的文件裙秋,如果有任何在index所指向的HEAD節(jié)點中登記的未提交文件琅拌,git-pull和git-merge命令將會停止缨伊。
3.2fast-forward合并
通常情況下分支合并都會產(chǎn)生一個合并節(jié)點,但是在某些特殊情況下例外进宝。例如調(diào)用git pull命令更新遠(yuǎn)端代碼時刻坊,如果本地的分支沒有任何的提交,那么沒有必要產(chǎn)生一個合并節(jié)點党晋。這種情況下將不會產(chǎn)生一個合并節(jié)點谭胚,HEAD直接指向更新后的頂端代碼,這種合并的策略就是fast-forward合并未玻。
3.3合并細(xì)節(jié)
除了上文所提到的fast-forward合并模式以外灾而,被合并的分支將會通過一個合并節(jié)點和當(dāng)前分支綁在一起,該合并節(jié)點同時擁有合并前的當(dāng)前分支頂部節(jié)點和對方分支頂部節(jié)點深胳,共同作為父節(jié)點绰疤。
一個合并了的版本將會使所有相關(guān)分支的變化一致,包括提交節(jié)點舞终,HEAD節(jié)點和index指針以及節(jié)點樹都會被更新轻庆。只要這些節(jié)點中的文件沒有重疊的地方,那么這些文件的變化都會在節(jié)點樹中改動并更新保存敛劝。
如果無法明顯地合并這些變化余爆,將會發(fā)生以下的情況:
- HEAD指針?biāo)赶虻墓?jié)點保持不變
-
MERGE_HEAD
指針被置于其他分支的頂部 - 已經(jīng)合并干凈的路徑在index文件和節(jié)點樹中同時更新
- 對于沖突路徑,index文件記錄了三個版本:版本1記錄了二者共同的祖先節(jié)點夸盟,版本2記錄了當(dāng)前分支的頂部蛾方,即HEAD,版本3記錄了
MERGE_HEAD
上陕。節(jié)點樹中的文件包含了合并程序運(yùn)行后的結(jié)果桩砰。例如三路合并算法會產(chǎn)生沖突。 - 其他方面沒有任何變化释簿。特別地亚隅,你之前進(jìn)行的本地修改將繼續(xù)保持原樣。
如果你嘗試了一個導(dǎo)致非常復(fù)雜沖突的合并庶溶,并想重新開始煮纵,那么可以使用git merge --abort
關(guān)于三路合并算法:
三路合并算法是用于解決沖突的一種方式,當(dāng)產(chǎn)生沖突時偏螺,三路合并算法會獲取三個節(jié)點:本地沖突的B節(jié)點行疏,對方分支的C節(jié)點,B套像,C節(jié)點的共同最近祖先節(jié)點A酿联。三路合并算法會根據(jù)這三個節(jié)點進(jìn)行合并。具體過程是,B贞让,C節(jié)點和A節(jié)點進(jìn)行比較采幌,如果B,C節(jié)點的某個文件和A節(jié)點中的相同震桶,那么不產(chǎn)生沖突;如果B或C只有一個和A節(jié)點相比發(fā)生變化征绎,那么該文件將會采用該變化了的版本蹲姐;如果B和C和A相比都發(fā)生了變化,且變化不相同人柿,那么則需要手動去合并;如果B柴墩,C都發(fā)生了變化,且變化相同凫岖,那么并不產(chǎn)生沖突江咳,會自動采用該變化的版本。最終合并后會產(chǎn)生D節(jié)點哥放,D節(jié)點有兩個父節(jié)點歼指,分別為B和C。
3.4合并tag
當(dāng)合并一個tag時甥雕,Git總是創(chuàng)建一個合并的提交踩身,即使這時能夠使用fast-forward模式。該提交信息的模板預(yù)設(shè)為該tag的信息社露。額外地挟阻,如果該tag被簽名,那么簽名的檢測信息將會附加在提交信息模板中峭弟。
3.5沖突是如何表示的
當(dāng)產(chǎn)生合并沖突時附鸽,該部分會以<<<<<<<
, =======
和 >>>>>>>
表示。在=======
之前的部分是當(dāng)前分支這邊的情況瞒瘸,在=======
之后的部分是對方分支的情況坷备。
3.6如何解決沖突
在看到?jīng)_突以后,你可以選擇以下兩種方式:
- 決定不合并挨务。這時击你,唯一要做的就是重置index到HEAD節(jié)點。
git merge --abort
用于這種情況谎柄。 - 解決沖突丁侄。Git會標(biāo)記沖突的地方,解決完沖突的地方后使用
git add
加入到index中朝巫,然后使用git commit
產(chǎn)生合并節(jié)點鸿摇。
你可以用以下工具來解決沖突: - 使用合并工具。
git mergetool
將會調(diào)用一個可視化的合并工具來處理沖突合并劈猿。 - 查看差異拙吉。
git diff
將會顯示三路差異(三路合并中所采用的三路比較算法)潮孽。 - 查看每個分支的差異。
git log --merge -p <path>
將會顯示HEAD
版本和MERGE_HEAD
版本的差異筷黔。 - 查看合并前的版本往史。
git show :1:文件名
顯示共同祖先的版本,git show :2:文件名
顯示當(dāng)前分支的HEAD版本佛舱,git show :3:文件名
顯示對方分支的MERGE_HEAD
版本椎例。
4.合并策略
Git可以通過添加-s參數(shù)來指定合并的策略。一些合并策略甚至含有自己的參數(shù)選項请祖,通過-X<option>
設(shè)置這些合并策略的參數(shù)選項订歪。(不要忘記,合并可以在git merge和git pull命令中發(fā)生肆捕,因此該合并策略同樣適用于git pull)刷晋。
4.1resolve
僅僅使用三路合并算法合并兩個分支的頂部節(jié)點(例如當(dāng)前分支和你拉取下來的另一個分支)。這種合并策略遵循三路合并算法慎陵,由兩個分支的HEAD節(jié)點以及共同子節(jié)點進(jìn)行三路合并眼虱。
當(dāng)然,真正會困擾我們的其實是交叉合并(criss-cross merge)這種情況荆姆。所謂的交叉合并蒙幻,是指共同祖先節(jié)點有多個的情況,例如在兩個分支合并時胆筒,很有可能出現(xiàn)共同祖先節(jié)點有兩個的情況發(fā)生邮破,這時候無法按照三路合并算法進(jìn)行合并(因為共同祖先節(jié)點不唯一)。resolve策略在解決交叉合并問題時是這樣處理的仆救,這里參考《Version Control with Git》:
In criss-cross merge situations, where there is more than one possible merge basis, the resolve strategy works like this: pick one of the possible merge bases, and hope for the best. This is actually not as bad as it sounds. It often turns out that the users have been working on different parts of the code. In that case, Git detects that it's remerging some changes that are already in place and skips the duplicate changes, avoiding the conflict. Or, if these are slight changes that do cause conflict, at least the conflict should be easy for the developer to handle
這里簡單翻譯一下:在交叉合并的情況時有一個以上的合并基準(zhǔn)點(共同祖先節(jié)點)抒和,resolve策略是這樣工作的:選擇其中一個可能的合并基準(zhǔn)點并期望這是合并最好的結(jié)果。實際上這并沒有聽起來的那么糟糕彤蔽。通常情況下用戶修改不同部分的代碼摧莽,在這種情況下,很多的合并沖突其實是多余和重復(fù)的顿痪。而使用resolve進(jìn)行合并時镊辕,產(chǎn)生的沖突也較易于處理,真正會遺失代碼的情況很少蚁袭。
4.2recursive
僅僅使用三路合并算法合并兩個分支征懈。和resolve不同的是,在交叉合并的情況時揩悄,這種合并方式是遞歸調(diào)用的卖哎,從共同祖先節(jié)點之后兩個分支的不同節(jié)點開始遞歸調(diào)用三路合并算法進(jìn)行合并,如果產(chǎn)生沖突,那么該文件不再繼續(xù)合并亏娜,直接拋出沖突焕窝;其他未產(chǎn)生沖突的文件將一直執(zhí)行到頂部節(jié)點。額外地维贺,這種方式也能夠檢測并處理涉及修改文件名的操作它掂。這是git合并和拉取代碼的默認(rèn)合并操作。
recursive合并策略有以下參數(shù):
4.2.1 ours
該參數(shù)將強(qiáng)迫沖突發(fā)生時,自動使用當(dāng)前分支的版本。這種合并方式不會產(chǎn)生任何困擾情況宰睡,甚至git都不會去檢查其他分支版本所包含的沖突內(nèi)容這種方式會拋棄對方分支任何沖突內(nèi)容拆魏。
4.2.2 theirs
正好和ours相反。
theirs和ours參數(shù)都適用于合并二進(jìn)制文件沖突的情況雪猪。
4.2.2 patience
在這種參數(shù)下栏尚,git merge-recursive
花費(fèi)一些額外的時間來避免錯過合并一些不重要的行(如函數(shù)的括號)。如果當(dāng)前分支和對方分支的版本分支分離非常大時只恨,建議采用這種合并方式译仗。
4.2.3diff-algorithm=[patience|minimal|histogram|myers]
告知git merge-recursive
使用不同的比較算法。
4.2.4 ignore-space-change
, ignore-all-space
, ignore-space-at-eol
根據(jù)指定的參數(shù)來對待空格沖突官觅。
- 如果對方的版本僅僅添加了空格的變化纵菌,那么沖突合并時采用我們自己的版本
- 如果我們的版本含有空格,但是對方的版本包含大量的變化休涤,那么沖突合并時采用對方的版本
- 采用正常的處理過程
4.2.5 no-renames
關(guān)閉重命名檢測咱圆。
4.2.6subtree[=<path>]
該選項是subtree合并策略的高級形式,將會猜測兩顆節(jié)點樹在合并的過程中如何移動功氨。不同的是序苏,指定的路徑將在合并開始時除去,以使得其他路徑能夠在尋找子樹的時候進(jìn)行匹配捷凄。(關(guān)于subtree合并策略詳見下文)
4.3octopus
這種合并方式用于兩個以上的分支忱详,但是在遇到?jīng)_突需要手動合并時會拒絕合并。這種合并方式更適合于將多個分支捆綁在一起的情況跺涤,也是多分支合并的默認(rèn)合并策略匈睁。
4.4ours
這種方式可以合并任意數(shù)量的分支,但是節(jié)點樹的合并結(jié)果總是當(dāng)前分支所沖突的部分桶错。這種方式能夠在替代舊版本時具有很高的效率航唆。請注意,這種方式和recursive策略下的ours參數(shù)是不同的牛曹。
4.5subtree
subtree是修改版的recursive策略佛点。當(dāng)合并樹A和樹B時,如果B是A的子樹,B首先調(diào)整至匹配A的樹結(jié)構(gòu)超营,而不是讀取相同的節(jié)點鸳玩。
4.5總結(jié)
在使用三路合并的策略時(指默認(rèn)的recursive策略),如果一個文件(或一行代碼)在當(dāng)前分支和對方分支都產(chǎn)生變化演闭,但是稍后又在其中一個分支回退不跟,那么這種回退的變化將會在結(jié)果中體現(xiàn)。這一點可能會使一些人感到困惑米碰。這是由于在合并的過程中窝革,git僅僅關(guān)注共同祖先節(jié)點以及兩個分支的HEAD節(jié)點,而不是兩個分支的所有節(jié)點吕座。因此虐译,合并算法將會把被回退的部分認(rèn)為成沒有變化,這樣吴趴,合并后的結(jié)果就會變?yōu)榱硪粋€分支中變化的部分漆诽。
5.關(guān)于Git使用的一些個人看法
本人一直認(rèn)為Git是一款非常優(yōu)秀的版本控制工具,但是在公司中很多人覺得Git很難使用锣枝。這種情況很大一部分原因是之前使用subversion時帶來的使用慣性對接受新技術(shù)造成了影響厢拭;另一方面,很多人僅僅通過GUI客戶端去使用Git撇叁。很久以來供鸠,大部分人認(rèn)為使用GUI是一種較為便捷的入門方式,其實這是值得商榷的陨闹。依我個人的經(jīng)驗來說楞捂,使用GUI會形成惰性,往往點擊幾個按鈕就能完成操作趋厉,使得很多人認(rèn)為學(xué)習(xí)Git的命令是一種浪費(fèi)時間和精力的行為泡一。但是事實上,在沒有理解清楚Git命令和思想的情況下觅廓,使用那些簡單的按鈕其實會帶來很大的困擾:很多人根本不知道點擊按鈕后會發(fā)生什么鼻忠,GUI的過于智能讓同一個按鈕的點擊事件可能對應(yīng)著不同參數(shù)的命令。最后真正受到傷害的是可憐的使用者們杈绸,因為他們根本不知道問題出在哪里帖蔓。
綜合全文的內(nèi)容,這里總結(jié)一些個人使用Git時所遵守的約定瞳脓。所謂約定塑娇,即非強(qiáng)迫性的,自愿的行為劫侧。不遵守這些約定并不會帶來什么缺陷埋酬,但是遵守這些約定可能會減輕在使用Git時帶來的困難哨啃,提高效率。
- 多提交写妥,少推送拳球。多人協(xié)作時,推送會頻繁地帶來合并沖突的問題珍特,影響效率祝峻。因此,盡量多使用提交命令扎筒,減少合并的使用莱找,這樣會節(jié)省很多時間。
- 使用Git流(Git Flow)嗜桌,詳見我的另一篇文章:一個成功的Git分支模型
- 使用分支奥溺,保持主分支的整潔。這是我強(qiáng)烈推薦的一點骨宠,在分支進(jìn)行提交谚赎,然后切到主分支更新(git pull —rebase),再合并分支诱篷、推送。這樣的流程會避免交叉合并的情況出現(xiàn)(不會出現(xiàn)共同祖先節(jié)點為多個的情況)雳灵。事實上棕所,git合并操作讓很多人感到不知所措的原因就是各種原因所產(chǎn)生的交叉合并問題,從而造成在合并的過程中丟失某些代碼悯辙。保持主分支的整潔能夠避免交叉合并的情況出現(xiàn)琳省。
- 禁用fast-forward模式。在拉取代碼的時候使用rebase參數(shù)(前提是保持主分支的整潔)躲撰、合并的時候使用—no-ff參數(shù)禁用fast-forward模式针贬,這樣做既能保證節(jié)點的清晰,又避免了交叉合并的情況出現(xiàn)拢蛋。