Git版本控制之多人協作

     上篇文章我們主要簡單的介紹了有關git的一些基本常識和一些簡單的命令。但那終究是皮毛,我們使用git最主要的目的還是管理我們的項目,多人協作。本篇文章主要涉及以下兩個大模塊:

  • 分支的概念及原理
  • 遠程倉庫的使用

一、分支
     在介紹分支之前,我們首先先考慮爲什麼需要引入分支這個概念,究竟有哪些無法解決的問題,需要我們引入新的概念。

在沒有分支這個概念之前,我們對於一個項目的開發只有一個進度,但是一旦發現項目的之前版本的某個節點出現bug,難道放棄到目前爲止的所有開發,回退到bug節點進行修復嗎?這是第一個亟待解決的問題。

對於我們軟件業來說,一個軟件肯定有不止一個版本,那麼你不能要求所有用戶全部升級到最新版本。那麼對於同一個項目,難道我們放棄那些仍使用舊版本的用戶,直接在原項目中開發新功能嗎?這也是一個未解決的問題。

下面我們從解決上述問題出發,引出分支的概念。

這裏寫圖片描述

我們沿着一條路進行開發,head指向當前最新一次commit,整條線路我們管它叫做分支(branch),但是我們發現之前的某次提交中出現bug,我們當然可以使用reset指令回退版本,但會丟失掉很大一部分代碼。

針對這種情況,我們可以創建一個分支用於修復bug,而主分支繼續開發,等bug修復完成之後,兩分支合併即可。

這裏寫圖片描述

對於上述的第二種問題,版本維護的問題。

這裏寫圖片描述

這樣在不同分支上的開發,兩個分支完全不相互影響。一條分支維護這舊版本,另一條分支開發着新功能,等到舊版本不再需要維護時,刪除該分支即可。那下面我們開始介紹分支的的相關命令。

     1、git branch
     和branch相關的命令主要有四個。

git branch:顯示當前版本庫中所有分支
git branch <branchname>:創建一個分支

我們都知道,版本庫中有一個head指針,它指向的是當前分支的最新提交,而我們的上述命令只負責創建一個分支,但是不會將head指針移動到該分支上,也就是說head指針還是指向原分支。

git branch -d <branchname>;嘗試刪除某個分支
git branch -D <branchname>:強制刪除某個分支

在執行分支刪除命令的時候,如果該分支沒有合併到其他分支中,git會拒絕刪除,這是爲了防誤刪。但是如果你實在不滿意對新分支的開發也可以強制刪除。

這裏寫圖片描述

下面兩個命令主要用於修改分支的名稱。

git branch -m <oldbranchname> <newbranchname>:嘗試修改
git branch -M <oldbranchname> <newbranchname>:強制修改

如果重命名的分支名已經存在的話將會被拒絕。那麼強制修改分支名稱將會覆蓋被同名的分支,所以所有強制操作一定要慎重。

     2、git merge
     要分支就必然需要合併,否則新分支上的所有開發都無法影響到主分支,這是沒有意義的。所以我們往往在新分支開發結束之後往主分支上合併。下面我們首先看一種快進式(Fast Forwarld)的合併方式。

快進式的合併就是直接將head指針快進到較遠的一個分支的最新提交,也就是說,快進式合併的兩個分支是一種從屬關係,像這樣的:

這裏寫圖片描述

當前head指針是指向master分支的,而當我們對newBranch分支進行合併的時候,git將會直接把head指針移動到newBranch的最新提交上,但是head指針依然是指向master的。

這裏寫圖片描述

我們在進行分支合併的時候,最常遇到的問題就是合併衝突,但是我們快進式合併是不會出現衝突的,因爲兩個分支是一種從屬關係,進度慢的是進度快的一部分。下面我們看看合併時遇到衝突該如何解決。

分支合併的衝突指的是,兩個不同的分支在各自開發過程中對相同文件進行了修改,那麼git在合併分支的時候將不知道選擇哪個分支上的修改作爲該文件的修改,這樣就產生衝突了。例如,我們在工作區創建兩個分支,在兩個分支上分別對文件test進行修改,然後再合併兩分支。

這裏寫圖片描述

我們打開導致兩個分支合併衝突的文件,

這裏寫圖片描述

git爲我們向其中添加了一些符號,其中”<<<<<<< HEAD”表示的是當前的master分支,”>>>>>>> newbranch”表示的是我們創建的新分支,而位於他們之間的”=======”用於分隔兩個分支的內容。從中我們很容易的看出來,master分支中此次的提交增加了以下信息,newbranch分支上也做了一次提交併增加了以上信息,所以兩個分支衝突的地方就是在這裏。

爲了解決這種衝突情況,我們可以選擇刪除導致衝突的任意一方的修改,例如我們刪除分支newbranch上的提交。

這裏寫圖片描述

然後我們可以add,提交到當前分支即可完成衝突的解決。也就是說當我們執行merge指令來合併兩個分支的時候,git會盡量去合併,但是如果遇到衝突,git也會呈現出兩個文件之間的差異,要求我們手動的去解決它。還有一些關於遠程分支的內容,我們將在下一節遠程倉庫中介紹。

2、遠程倉庫
     Git作爲分佈式的版本控制系統,你是你本地倉庫的主人,但是想要實現多人的協作開發,你就要將你本地的開發推送到遠程共享倉庫中供大家下載,本篇主要以github作爲遠程服務器來介紹有關遠程倉庫這塊內容。

作爲我們的服務器,並不能讓任何人向我們的git服務器上推送代碼,只能讓有憑證的人向服務器推送。git本地和github服務器之間是通過ssh對稱祕鑰來完成兩者的身份確認的,至於ssh是什麼,不瞭解的同學可以自行學習下,簡單來說,它就是一個通訊加密協議。下面我們先生成一對ssh祕鑰,執行以下代碼:

$ ssh-keygen -t rsa -C "[email protected]"

然後一路回車即可,等生成成功之後,我們打開這個.ssh文件夾(這個文件夾的保存路徑git已經給出,每個人都不一樣),這裏就是一對祕鑰,一個是公鑰,一個是私鑰。公鑰可以泄露出去,私鑰一定保存好。接着,我們將公鑰添加到github上,

這裏寫圖片描述

這樣我們本地的提交,github服務器就可以用列表中的公鑰來識別提交者的身份,對於不認識的提交者服務器將予以拒絕。接下來我們看如何將本地的倉庫關聯服務器上的某個倉庫。首先,我們在服務器上創建一個git倉庫,

這裏寫圖片描述

然後我們執行以下這條命令來爲本地git庫關聯遠程倉庫,

$ git remote add origin git@github.com:Programer-yang/TestGit.git

上述這條命令不是絕對的,讀者要根據自己的github賬戶和創建的遠程倉庫做適當的改動。執行成功之後,git是沒有任何提示的,只有出現錯誤纔會有所提示。這裏的遠程倉庫名字,我們默認爲origin,當然也是可以修改的,這個遠程倉庫的簡稱是爲了簡單替代長串的URL,在以後的推送和拉取中就可以使用這個簡稱來簡化命令了。下面我們將介紹兩個命令,一個用於將本地分支推送合併到遠程倉庫中,一個用於從遠程倉庫拉取最新分支。

     1、git push
     該命令用於將本地分支提交到遠程分支上,它的完整命令格式爲:

$ git push <遠程主機名> <本地分支名>:<遠程分支名>

例如我們向在本地分支新建一個test文件,然後向github推送。

這裏寫圖片描述

然後我們打開github賬戶,可以明顯看到我們創建的倉庫收到一次提交,時間顯示幾分鐘之前,而我們本地新建的文件也隨着提交被創建在服務器上。

這裏寫圖片描述

     2、git pull
     該命令主要用於拉取位於服務器上的最新分支到本地併合並,它等效於 git fetch + git merge。命令git fetch 會拉取服務器上的分支並保存在版本庫的某個文件夾下,命令git merge則會將拉取下來的版本庫與本地版本庫進行合併。而我們的git pull命令就是兩個命令的結合。它的格式如下:

git pull  <遠程主機名> <遠程分支名>:<本地分支名>

基本格式和上述介紹的push 命令類似,下面我們在服務器上新建一個文件index,模擬他人對倉庫的提交,這樣服務器上的分支就比本地的分支上游一次提交,我們在本地拉取服務器上最新分支。

這裏寫圖片描述

這裏寫圖片描述

打開我們工作目錄,即可看到拉取下來的index文件,此時我們的本地版本庫就和服務器上的倉庫一模一樣。

至此,我們簡單的介紹了git中較爲強大的兩部分內容,分支的遠程倉庫。很多命令都有其簡寫的方式,以及使用參數和選項來簡化操作,這裏我們並沒有介紹,在後續更加深入的文章中,這裏的某些命令可能還會出現。總體上來說,本篇介紹的內容還算簡單,總結不到之處,望指出,下一篇我們將介紹強大的檢出和重置命令。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章