?????上篇文章我們主要簡(jiǎn)單的介紹了有關(guān)git的一些基本常識(shí)和一些簡(jiǎn)單的命令。但那終究是皮毛件炉,我們使用git最主要的目的還是管理我們的項(xiàng)目,多人協(xié)作。本篇文章主要涉及以下兩個(gè)大模塊:
- 分支的概念及原理
- 遠(yuǎn)程倉庫的使用
一册着、分支
?????在介紹分支之前,我們首先先考慮為什么需要引入分支這個(gè)概念脾歧,究竟有哪些無法解決的問題甲捏,需要我們引入新的概念。
在沒有分支這個(gè)概念之前鞭执,我們對(duì)于一個(gè)項(xiàng)目的開發(fā)只有一個(gè)進(jìn)度司顿,但是一旦發(fā)現(xiàn)項(xiàng)目的之前版本的某個(gè)節(jié)點(diǎn)出現(xiàn)bug,難道放棄到目前為止的所有開發(fā)兄纺,回退到bug節(jié)點(diǎn)進(jìn)行修復(fù)嗎大溜?這是第一個(gè)亟待解決的問題。
對(duì)于我們軟件業(yè)來說估脆,一個(gè)軟件肯定有不止一個(gè)版本钦奋,那么你不能要求所有用戶全部升級(jí)到最新版本。那么對(duì)于同一個(gè)項(xiàng)目,難道我們放棄那些仍使用舊版本的用戶付材,直接在原項(xiàng)目中開發(fā)新功能嗎朦拖?這也是一個(gè)未解決的問題。
下面我們從解決上述問題出發(fā)厌衔,引出分支的概念璧帝。
我們沿著一條路進(jìn)行開發(fā),head指向當(dāng)前最新一次commit富寿,整條線路我們管它叫做分支(branch)睬隶,但是我們發(fā)現(xiàn)之前的某次提交中出現(xiàn)bug,我們當(dāng)然可以使用reset指令回退版本作喘,但會(huì)丟失掉很大一部分代碼理疙。
針對(duì)這種情況,我們可以創(chuàng)建一個(gè)分支用于修復(fù)bug泞坦,而主分支繼續(xù)開發(fā)窖贤,等bug修復(fù)完成之后,兩分支合并即可贰锁。
對(duì)于上述的第二種問題赃梧,版本維護(hù)的問題。
這樣在不同分支上的開發(fā)豌熄,兩個(gè)分支完全不相互影響授嘀。一條分支維護(hù)這舊版本,另一條分支開發(fā)著新功能锣险,等到舊版本不再需要維護(hù)時(shí)蹄皱,刪除該分支即可。那下面我們開始介紹分支的的相關(guān)命令芯肤。
?????1巷折、git branch
?????和branch相關(guān)的命令主要有四個(gè)。
git branch:顯示當(dāng)前版本庫中所有分支
git branch <branchname>:創(chuàng)建一個(gè)分支
我們都知道崖咨,版本庫中有一個(gè)head指針锻拘,它指向的是當(dāng)前分支的最新提交,而我們的上述命令只負(fù)責(zé)創(chuàng)建一個(gè)分支击蹲,但是不會(huì)將head指針移動(dòng)到該分支上署拟,也就是說head指針還是指向原分支。
git branch -d <branchname>歌豺;嘗試刪除某個(gè)分支
git branch -D <branchname>:強(qiáng)制刪除某個(gè)分支
在執(zhí)行分支刪除命令的時(shí)候推穷,如果該分支沒有合并到其他分支中,git會(huì)拒絕刪除类咧,這是為了防誤刪馒铃。但是如果你實(shí)在不滿意對(duì)新分支的開發(fā)也可以強(qiáng)制刪除谴咸。
下面兩個(gè)命令主要用于修改分支的名稱。
git branch -m <oldbranchname> <newbranchname>:嘗試修改
git branch -M <oldbranchname> <newbranchname>:強(qiáng)制修改
如果重命名的分支名已經(jīng)存在的話將會(huì)被拒絕骗露。那么強(qiáng)制修改分支名稱將會(huì)覆蓋被同名的分支,所以所有強(qiáng)制操作一定要慎重血巍。
?????2萧锉、git merge
?????要分支就必然需要合并,否則新分支上的所有開發(fā)都無法影響到主分支述寡,這是沒有意義的柿隙。所以我們往往在新分支開發(fā)結(jié)束之后往主分支上合并。下面我們首先看一種快進(jìn)式(Fast Forwarld)的合并方式鲫凶。
快進(jìn)式的合并就是直接將head指針快進(jìn)到較遠(yuǎn)的一個(gè)分支的最新提交禀崖,也就是說,快進(jìn)式合并的兩個(gè)分支是一種從屬關(guān)系螟炫,像這樣的:
當(dāng)前head指針是指向master分支的波附,而當(dāng)我們對(duì)newBranch分支進(jìn)行合并的時(shí)候,git將會(huì)直接把head指針移動(dòng)到newBranch的最新提交上昼钻,但是head指針依然是指向master的掸屡。
我們?cè)谶M(jìn)行分支合并的時(shí)候,最常遇到的問題就是合并沖突然评,但是我們快進(jìn)式合并是不會(huì)出現(xiàn)沖突的仅财,因?yàn)閮蓚€(gè)分支是一種從屬關(guān)系,進(jìn)度慢的是進(jìn)度快的一部分碗淌。下面我們看看合并時(shí)遇到?jīng)_突該如何解決盏求。
分支合并的沖突指的是,兩個(gè)不同的分支在各自開發(fā)過程中對(duì)相同文件進(jìn)行了修改亿眠,那么git在合并分支的時(shí)候?qū)⒉恢肋x擇哪個(gè)分支上的修改作為該文件的修改碎罚,這樣就產(chǎn)生沖突了。例如缕探,我們?cè)诠ぷ鲄^(qū)創(chuàng)建兩個(gè)分支魂莫,在兩個(gè)分支上分別對(duì)文件test進(jìn)行修改,然后再合并兩分支爹耗。
我們打開導(dǎo)致兩個(gè)分支合并沖突的文件耙考,
git為我們向其中添加了一些符號(hào),其中"<<<<<<< HEAD"表示的是當(dāng)前的master分支潭兽,">>>>>>> newbranch"表示的是我們創(chuàng)建的新分支倦始,而位于他們之間的"======="用于分隔兩個(gè)分支的內(nèi)容。從中我們很容易的看出來山卦,master分支中此次的提交增加了以下信息鞋邑,newbranch分支上也做了一次提交并增加了以上信息诵次,所以兩個(gè)分支沖突的地方就是在這里。
為了解決這種沖突情況枚碗,我們可以選擇刪除導(dǎo)致沖突的任意一方的修改逾一,例如我們刪除分支newbranch上的提交。
然后我們可以add肮雨,提交到當(dāng)前分支即可完成沖突的解決遵堵。也就是說當(dāng)我們執(zhí)行merge指令來合并兩個(gè)分支的時(shí)候,git會(huì)盡量去合并怨规,但是如果遇到?jīng)_突陌宿,git也會(huì)呈現(xiàn)出兩個(gè)文件之間的差異,要求我們手動(dòng)的去解決它波丰。還有一些關(guān)于遠(yuǎn)程分支的內(nèi)容壳坪,我們將在下一節(jié)遠(yuǎn)程倉庫中介紹。
2掰烟、遠(yuǎn)程倉庫
?????Git作為分布式的版本控制系統(tǒng)爽蝴,你是你本地倉庫的主人,但是想要實(shí)現(xiàn)多人的協(xié)作開發(fā)纫骑,你就要將你本地的開發(fā)推送到遠(yuǎn)程共享倉庫中供大家下載霜瘪,本篇主要以github作為遠(yuǎn)程服務(wù)器來介紹有關(guān)遠(yuǎn)程倉庫這塊內(nèi)容。
作為我們的服務(wù)器惧磺,并不能讓任何人向我們的git服務(wù)器上推送代碼颖对,只能讓有憑證的人向服務(wù)器推送。git本地和github服務(wù)器之間是通過ssh對(duì)稱秘鑰來完成兩者的身份確認(rèn)的磨隘,至于ssh是什么缤底,不了解的同學(xué)可以自行學(xué)習(xí)下,簡(jiǎn)單來說番捂,它就是一個(gè)通訊加密協(xié)議个唧。下面我們先生成一對(duì)ssh秘鑰,執(zhí)行以下代碼:
$ ssh-keygen -t rsa -C "youremail@example.com"
然后一路回車即可设预,等生成成功之后徙歼,我們打開這個(gè).ssh文件夾(這個(gè)文件夾的保存路徑git已經(jīng)給出,每個(gè)人都不一樣)鳖枕,這里就是一對(duì)秘鑰魄梯,一個(gè)是公鑰,一個(gè)是私鑰宾符。公鑰可以泄露出去酿秸,私鑰一定保存好。接著魏烫,我們將公鑰添加到github上辣苏,
這樣我們本地的提交肝箱,github服務(wù)器就可以用列表中的公鑰來識(shí)別提交者的身份,對(duì)于不認(rèn)識(shí)的提交者服務(wù)器將予以拒絕稀蟋。接下來我們看如何將本地的倉庫關(guān)聯(lián)服務(wù)器上的某個(gè)倉庫煌张。首先,我們?cè)诜?wù)器上創(chuàng)建一個(gè)git倉庫退客,
然后我們執(zhí)行以下這條命令來為本地git庫關(guān)聯(lián)遠(yuǎn)程倉庫唱矛,
$ git remote add origin git@github.com:Programer-yang/TestGit.git
上述這條命令不是絕對(duì)的,讀者要根據(jù)自己的github賬戶和創(chuàng)建的遠(yuǎn)程倉庫做適當(dāng)?shù)母膭?dòng)井辜。執(zhí)行成功之后,git是沒有任何提示的管闷,只有出現(xiàn)錯(cuò)誤才會(huì)有所提示粥脚。這里的遠(yuǎn)程倉庫名字,我們默認(rèn)為origin包个,當(dāng)然也是可以修改的刷允,這個(gè)遠(yuǎn)程倉庫的簡(jiǎn)稱是為了簡(jiǎn)單替代長串的URL,在以后的推送和拉取中就可以使用這個(gè)簡(jiǎn)稱來簡(jiǎn)化命令了碧囊。下面我們將介紹兩個(gè)命令树灶,一個(gè)用于將本地分支推送合并到遠(yuǎn)程倉庫中,一個(gè)用于從遠(yuǎn)程倉庫拉取最新分支糯而。
?????1天通、git push
?????該命令用于將本地分支提交到遠(yuǎn)程分支上,它的完整命令格式為:
$ git push <遠(yuǎn)程主機(jī)名> <本地分支名>:<遠(yuǎn)程分支名>
例如我們向在本地分支新建一個(gè)test文件熄驼,然后向github推送像寒。
然后我們打開github賬戶,可以明顯看到我們創(chuàng)建的倉庫收到一次提交瓜贾,時(shí)間顯示幾分鐘之前诺祸,而我們本地新建的文件也隨著提交被創(chuàng)建在服務(wù)器上。
?????2祭芦、git pull
?????該命令主要用于拉取位于服務(wù)器上的最新分支到本地并合并筷笨,它等效于 git fetch + git merge。命令git fetch 會(huì)拉取服務(wù)器上的分支并保存在版本庫的某個(gè)文件夾下龟劲,命令git merge則會(huì)將拉取下來的版本庫與本地版本庫進(jìn)行合并胃夏。而我們的git pull命令就是兩個(gè)命令的結(jié)合。它的格式如下:
git pull <遠(yuǎn)程主機(jī)名> <遠(yuǎn)程分支名>:<本地分支名>
基本格式和上述介紹的push 命令類似昌跌,下面我們?cè)诜?wù)器上新建一個(gè)文件index构订,模擬他人對(duì)倉庫的提交,這樣服務(wù)器上的分支就比本地的分支上游一次提交避矢,我們?cè)诒镜乩》?wù)器上最新分支悼瘾。
打開我們工作目錄囊榜,即可看到拉取下來的index文件,此時(shí)我們的本地版本庫就和服務(wù)器上的倉庫一模一樣亥宿。
至此卸勺,我們簡(jiǎn)單的介紹了git中較為強(qiáng)大的兩部分內(nèi)容,分支的遠(yuǎn)程倉庫烫扼。很多命令都有其簡(jiǎn)寫的方式曙求,以及使用參數(shù)和選項(xiàng)來簡(jiǎn)化操作,這里我們并沒有介紹映企,在后續(xù)更加深入的文章中悟狱,這里的某些命令可能還會(huì)出現(xiàn)⊙呙ィ總體上來說挤渐,本篇介紹的內(nèi)容還算簡(jiǎn)單,總結(jié)不到之處双絮,望指出浴麻,下一篇我們將介紹強(qiáng)大的檢出和重置命令。