一、概述
1.??? Git與SVN比較
目前用到最廣泛的版本控制軟件就是SVN和Git,那么這兩者之間有什么不同之處呢?
1)? ? ?SVN(Subversion)是集中式管理的版本控制器,而Git是分布式管理的版本控制器!
2)???? SVN只有一個(gè)單一的集中管理的服務(wù)器,保存所有文件的修訂版本,而協(xié)同工作的人們都通過(guò)客戶(hù)端連到這臺(tái)服務(wù)器,取出最新的文件或者提交更新。
3)????
Git每一個(gè)終端都是一個(gè)倉(cāng)庫(kù),客戶(hù)端并不只提取最新版本的文件快照,而是把原始的代碼倉(cāng)庫(kù)完整地鏡像下來(lái)。每一次的提取操作,實(shí)際上都是一次對(duì)代碼倉(cāng)庫(kù)的完整備份。
4)???? Git具備強(qiáng)大的分支管理功能,SVN實(shí)際上不具備。
?
2.??? 為什么選擇Git
SVN的優(yōu)點(diǎn):
1)? ? ?管理方便,邏輯明確,符合一般人思維習(xí)慣。
2)???? 易于管理,集中式服務(wù)器更能保證安全性。
3)???? 代碼一致性高。
SVN的缺點(diǎn):
1)????? 提交并非每次都能夠成功。如果有其他人先于你提交,會(huì)提示“改動(dòng)基于過(guò)時(shí)的版本,先更新再提交”… 諸如此類(lèi);
2)???? 沖突解決是一個(gè)提交速度的競(jìng)賽:手快者,先提交,平安無(wú)事;手慢者,后提交,可能遇到麻煩的沖突解決。
Git更適合分布式開(kāi)發(fā),離線(xiàn)工作,強(qiáng)調(diào)個(gè)體,任意兩個(gè)開(kāi)發(fā)者之間可以很容易的解決沖突。最重要的是Git具備強(qiáng)大的分支管理功能,非常適合產(chǎn)品開(kāi)發(fā)。
?
二、基本操作
1.??? 獲取幫助
通過(guò)git命令可以查看所有命令的介紹
?
??
2.??? 倉(cāng)庫(kù)的克隆
git獲取倉(cāng)庫(kù)的命令是clone而不是checkout,從這就可以看出Git和SVN的區(qū)別。
Git獲取的是整個(gè)庫(kù)的信息,可以查看所有日志信息。
???
3.??? 提交代碼
在文件夾下運(yùn)行commit命令,將文件提交到本地版本庫(kù)。
由于本地倉(cāng)庫(kù)只有你一個(gè)人在使用,所以請(qǐng)放心提交,不需要考慮BUG等因素。PUSH時(shí)就要小心了。
有些文件是不需要提交到版本管理的,比如 .vs 文件夾、bin、obj文件夾等,應(yīng)該將其加入忽略列表中。
Git提交時(shí)要求輸入關(guān)于本次提交的說(shuō)明,請(qǐng)認(rèn)真填寫(xiě),這樣就不用維護(hù)額外的版本修改日志了。對(duì)于確實(shí)無(wú)關(guān)緊要的提交,可以團(tuán)隊(duì)約定輸入一個(gè)字符,如“#”。
?
?? ?
4.??? 同步倉(cāng)庫(kù)
同步操作有兩種:
1、 PULL:將遠(yuǎn)程服務(wù)器代碼同步到本地
2、 PUSH:將本地代碼同步到遠(yuǎn)程服務(wù)器
具體的操作流程應(yīng)該如下:
1、??????? commit的操作應(yīng)該是頻繁進(jìn)行的,和遠(yuǎn)程庫(kù)無(wú)關(guān);
2、??????? 執(zhí)行PULL操作獲取團(tuán)隊(duì)最新代碼;
3、??????? 本地確認(rèn)編譯成功后PUSH到遠(yuǎn)程庫(kù),以便分享個(gè)人代碼。PUSH前應(yīng)該確認(rèn)個(gè)人版本是可以編譯通過(guò)的。
模擬一個(gè)操作場(chǎng)景:
1)??????? A用戶(hù)早上PULL了最新版本,然后在此版本基礎(chǔ)上進(jìn)行了一天的開(kāi)發(fā),下班時(shí)進(jìn)行了PUSH操作,沒(méi)有發(fā)生任何問(wèn)題;(應(yīng)該先PULL再PUSH)
2)???????
B用戶(hù)早上也PULL最新版本,開(kāi)發(fā)了一天,此時(shí)B進(jìn)行PUSH會(huì)報(bào)錯(cuò)(本地庫(kù)版本和遠(yuǎn)程庫(kù)不一致),必須先進(jìn)行PULL獲得最新版本后才能進(jìn)行PUSH。(PUSH前應(yīng)保證版本可以編譯)
3)??????? 如果兩個(gè)用戶(hù)修改了同一個(gè)文件,當(dāng)B用戶(hù)在進(jìn)行PULL時(shí)會(huì)進(jìn)行合并,一般不會(huì)發(fā)生沖突。A用戶(hù)會(huì)在下次PULL時(shí)獲得合并后的版本。
4)?????? 如果兩個(gè)用戶(hù)修改了同一個(gè)文件的兩個(gè)地方就會(huì)引起沖突。
?
5.??? 解決沖突
版本沖突在兩個(gè)用戶(hù)修改同一個(gè)文件的同一個(gè)位置時(shí)發(fā)生。修改同一個(gè)文件的不同的位置會(huì)自動(dòng)合并,不會(huì)沖突。二進(jìn)制文件沒(méi)有合并功能,任何同時(shí)修改都會(huì)沖突。
一個(gè)沖突解決的示例:
這是代碼的原始版本:
? ??????static void Main(string[] args)
??????? {
??????????? Console.WriteLine("Hello");
??? ?????
??????????? Console.ReadLine();
??????? }
A用戶(hù)修改后:
??????? static void Main(string[] args)
??????? {
??????????? Console.WriteLine("Hello");
??? ????? ??Console.WriteLine("Hello:I'm Good Boy!");
??????????? Console.ReadLine();
??????? }
B用戶(hù)修改后:
??????? static void Main(string[] args)
??????? {
??????????? Console.WriteLine("Hello");
??? ????? ??Console.WriteLine("Hello:I'm BAD Boy!");
??????????? Console.ReadLine();
??????? }
首先A用戶(hù)率先進(jìn)行了commit 和 PUSH,成功。B用戶(hù)此時(shí)也準(zhǔn)備提交,提交前,要進(jìn)行一次PULL,此時(shí)發(fā)生沖突:自動(dòng)合并失?。?br>
CONFLICT (content): Merge conflict in ConsoleApp1/ConsoleApp1/Program.cs
Automatic merge failed; fix conflicts and then commit the result.
打開(kāi)沖突文件,可以看到:
??????? static void Main(string[] args)
??????? {
??????????? Console.WriteLine("Hello");
<<<<<<< HEAD
??? ??? ????Console.WriteLine("Hello:I'm BAD Boy!");
=======
??? ??? ????Console.WriteLine("Hello:I'm Good Boy!");
>>>>>>> 129dfb44dd2978700d82493d9fa966e598b85535
??????????? Console.ReadLine();
??????? }
??? }
可以看到?jīng)_突內(nèi)容包含在<<<<<<<與>>>>>>>之間,通過(guò)======隔開(kāi),前面是本地版本,后面是遠(yuǎn)程版本。
處理辦法:直接修改這個(gè)文件,然后commit、PULL、PUSH即可。
還有一種沖突是版本庫(kù)刪除了一個(gè)文件,本地還進(jìn)行了修改,這也形成沖突。
AA.txt deleted in 777b20bb5a04b3c3489318c5e7d6723d5d38d50f and modified in
HEAD. Version HEAD of DOC/AA.txt left in tree.
處理辦法:先將沖突文件移開(kāi),commit后再PULL就可以成功,如果還需要這個(gè)文件,再重新commit即可。
?
三、進(jìn)階操作
1.??? 版本標(biāo)記
為了合并、回退等操作方便,我們會(huì)對(duì)重要版本進(jìn)行標(biāo)記。在log界面找到指定版本,右鍵選擇:“create tag at this version…”。
?
2.??? 恢復(fù)誤刪除的文件
如果文件(或文件夾)被誤刪除,并且已經(jīng)清空回收站,可以從本地版本庫(kù)取得最新提交的文件,注意:只有提交過(guò)的版本才能恢復(fù),沒(méi)有提交的內(nèi)容是不可能找回的,所以要經(jīng)常提交。
首先通過(guò)日志找到刪除之前的某個(gè)版本,在其文件上右鍵選擇“Revert to this
version”即可,對(duì)于不想要的文件,如果想恢復(fù)到之前版本,也可以通過(guò)這個(gè)方法處理。
???
3.??? 獲取指定版本庫(kù)
可能近期寫(xiě)的代碼一團(tuán)糟,已經(jīng)無(wú)法走上正軌了,希望恢復(fù)到某個(gè)穩(wěn)定的版本重新開(kāi)發(fā),這就需要重置版本。首先在日志窗口找到要恢復(fù)的點(diǎn),右鍵選擇:”reset XXX
to this version…”
重置類(lèi)型選擇“Hard”:
??
Hard表示強(qiáng)制恢復(fù)到指定版本,Mixed表示保留修改的文件。
如果在回退前沒(méi)有PUSH過(guò)版本,回退后需要PUSH的話(huà)直接PUSH就可以了,如果回退的版本早于最后一次PUSH的版本,則需要進(jìn)行強(qiáng)制PUSH(Hard)。
需要說(shuō)明的是,遠(yuǎn)程版本回退應(yīng)該是一個(gè)集體行為,不存在項(xiàng)目組某個(gè)人進(jìn)行版本回退,但其他人繼續(xù)使用當(dāng)前版本的情況,回退點(diǎn)之后的版本是要拋棄掉的。
?
四、分支管理
1.??? 分支管理概述
一般來(lái)說(shuō)主線(xiàn)版本(master)是不會(huì)用來(lái)開(kāi)發(fā)的,只用來(lái)進(jìn)行版本發(fā)布,如果一個(gè)項(xiàng)目采用master單線(xiàn)版本進(jìn)行開(kāi)發(fā),建議不要采用Git進(jìn)行版本管理,采用SVN會(huì)更加方便一點(diǎn)。
下面介紹一下版本分支管理的主要流程與意圖:
某公司1號(hào)發(fā)布了產(chǎn)品版本V1.0,15號(hào)開(kāi)發(fā)人員在開(kāi)發(fā)V1.1過(guò)程中接到客戶(hù)反饋,發(fā)現(xiàn)重大BUG需要緊急修復(fù),假設(shè)采用單分支開(kāi)發(fā),就必須在當(dāng)前分支進(jìn)行修復(fù)并發(fā)布,造成的問(wèn)題是本次發(fā)布的版本包含未經(jīng)驗(yàn)證的V1.1版本的內(nèi)容。
正確的做法應(yīng)該是:master主分支發(fā)布V1.0版本后,創(chuàng)建分支V1.1進(jìn)行下一個(gè)版本開(kāi)發(fā),當(dāng)收到用戶(hù)BUG反饋時(shí),創(chuàng)建V1.0_DEBUG分支進(jìn)行修復(fù),并發(fā)布。當(dāng)V1.1版本開(kāi)發(fā)完成并驗(yàn)證通過(guò)后,將V1.1分支合并到master分支,同時(shí)合并V1.0_DEBUG分支修復(fù)的BUG。
版本合并后,繼續(xù)創(chuàng)建V1.2版本進(jìn)行下一個(gè)版本開(kāi)發(fā)。V1.1版本發(fā)現(xiàn)的BUG可以繼續(xù)在原來(lái)V1.1分支上進(jìn)行修復(fù),V1.0_DEBUG版本可以不用繼續(xù)維護(hù)了,之前發(fā)出的版本如果發(fā)現(xiàn)問(wèn)題,可以在V1.1版本進(jìn)行修改,并將客戶(hù)版本升級(jí)到V1.1
。
?
2.??? 創(chuàng)建分支
一般通過(guò)Git管理平臺(tái)創(chuàng)建分支,并為分支設(shè)置權(quán)限,也可以在本地創(chuàng)建分支,然后Push到遠(yuǎn)程服務(wù)器。如果要在某個(gè)時(shí)間點(diǎn)創(chuàng)建分支,在日志窗口找到指定的時(shí)間點(diǎn),右鍵選擇“Create
Branch at this version…”即可。本地創(chuàng)建分支后,需要切換到該分支并執(zhí)行PUSH操作才能將分支同步到服務(wù)器。
?
3.??? 在某分支上進(jìn)行開(kāi)發(fā)
在固定的某個(gè)分支上進(jìn)行開(kāi)發(fā),參照本文第二、第三部分的描述即可。本地克隆了版本庫(kù)之后,立即切換到開(kāi)發(fā)分支,第一次切換時(shí)會(huì)在本地建立相同名稱(chēng)的本地分支。
?
4.??? 分支的合并
通過(guò)Fetch命令獲取其他分支內(nèi)容。Fetch命令把遠(yuǎn)程服務(wù)器上所有版本同步到本地,但不做進(jìn)一步操作。
通過(guò)Merge命令進(jìn)行版本合并,合并時(shí)需要選擇對(duì)方分支的名稱(chēng)。
?
??
5.??? Fetch與Pull的區(qū)別
Pull命令相當(dāng)于 Fetch + Merge ,就是把遠(yuǎn)程庫(kù)同步到本地并自動(dòng)進(jìn)行合并。如果要合并其他分支,Pull時(shí)需要選擇其他遠(yuǎn)程分支的名稱(chēng)。
???
采用PULL或Fetch +
Merge沒(méi)有本質(zhì)區(qū)別,唯一的區(qū)別就是在進(jìn)行分支合并時(shí)Fetch后可以先觀(guān)察一些修改的內(nèi)容在進(jìn)行合并。建議在同一個(gè)分支工作時(shí)就采用Pull,在分支之間進(jìn)行合并時(shí),采用Fetch
+ Merge。
?
6.??? 分支沖突
合并版本后,對(duì)所有沖突進(jìn)行手動(dòng)修改,修改完成后Commit、PUSH即可。
需要注意幾點(diǎn):
1、 永遠(yuǎn)以master分支為發(fā)布分支;
2、 master會(huì)合并develop和fixbug版本,develop也會(huì)合并fixbug版本,不要有其他方向的合并;
3、 master版本合并其他版本后,通過(guò)新建分支的方式繼續(xù)開(kāi)發(fā),原來(lái)其他分支可以刪除掉。
4、
如果develop合并fixbug時(shí)有沖突,master在合并develop和fixbug時(shí)可能任然會(huì)沖突,如果develop版本已經(jīng)合并了所有fixbug,那么master版本在合并develop后可以不用重復(fù)合并fixbug。
?
五、Git版本管理最佳實(shí)踐
以下是一個(gè)常見(jiàn)的版本管理的流程:
?
??具體流程描述如下:
1)? ? ? ?首先建立版本庫(kù),自動(dòng)創(chuàng)建master版本,在master版本上持續(xù)開(kāi)發(fā),直到發(fā)布V1.0版本;
2)? ? ?
?V1.0版本發(fā)布后同時(shí)面臨兩個(gè)任務(wù):V1.1版本開(kāi)發(fā)和V1.0版本的Bug修復(fù)。此時(shí)創(chuàng)建V1.1_develop分支和V1.0_bugfix兩個(gè)分支,相關(guān)的開(kāi)發(fā)團(tuán)隊(duì)?wèi)?yīng)該立即Fetch庫(kù)后Switch到各自的庫(kù)上開(kāi)展工作;
3)? ? ?
?新版本V1.1_develop研發(fā)完成并驗(yàn)證后,合并到master庫(kù),同時(shí)master庫(kù)合并V1.0_bugfix分支,經(jīng)驗(yàn)證后發(fā)布V1.1版本;
4)?????? 刪除V1.1_develop和V1.0_bugfix分支;
5)? ? ? ?創(chuàng)建新分支,循環(huán)以上過(guò)程。
?
需要注意幾點(diǎn):
1)??????? 如果更嚴(yán)謹(jǐn)一些的話(huà),應(yīng)該還要具備測(cè)試分支,測(cè)試分支從develop分支創(chuàng)建,測(cè)試通過(guò)后合并到主分支。
2)???????
以上第三個(gè)過(guò)程的操作,可以更積極一點(diǎn),master版本可以更頻繁地合并兩個(gè)版本以及時(shí)處理沖突,develop分支也可以積極合并fixbug分支,但fixbug分支不能合并其他分支。
3)??????? 穩(wěn)定版本發(fā)布后即可刪除所有臨時(shí)分支。
?
熱門(mén)工具 換一換
