推薦學習:《》
Git是一款開源的分散式版本控制系統,可以有效,高速處理從很小到非常大的專案版本管理。 Git是通過C語言開發實現的。
Git和SVN是兩種截然不同的版本控制系統,Git是分散式版本控制系統,而SVN則是集中式版本控制系統。要想比較Git和SVN的區別,首先需要了解分散式版本控制系統和集中式版本控制系統的基本概念。
集中式版本控制系統:一個顯著的特徵是版本庫是存放在中央伺服器上的,由中央伺服器統一管理專案的版本資訊和分支資訊。團隊中的每個成員在工作時都需要先從中央伺服器上拉取最新的程式碼,然後開始幹活。幹完活之後再將程式碼提交到中央伺服器上。集中式版本伺服器有兩個弊端:
集中式版本控制系統的網路拓撲圖如下圖所示:
可以看出團隊中所有成員的工作電腦都只與中央伺服器打交道。如果把版本庫比做書庫的話,那麼每個人(每個電腦)都需要先從書庫借到書(拉取最新的程式碼),閱讀完之後然後還給書庫(修改之後提交到中央伺服器)
分散式版本控制系統: 與集中式版本控制系統最大的不同是團隊中所有成員的工作電腦上都有一個完整的版本庫,並且沒有中央伺服器。,這就相當於團隊中每個成員都有一個自己的小書庫(版本庫),成員之間可以互相交換自己書庫中的圖書(將自己的修改提交給對方)。這裡完全不需要中央伺服器來管理協調管理。
在實際使用分散式版本控制系統時,其實很少在兩人之間的電腦上進行版本庫推播,這是因為有時候你們不在同一個區域網內,或者你同事的電腦關機了。因此,分散式版本控制系統通常也有一臺充當「中央伺服器」的電腦,但這個伺服器的作用僅僅是用來方便「交換」大家的修改,沒有它大家也一樣幹活,只是交換修改不方便而已。這臺充當「中央伺服器」的電腦上的版本庫稱之為遠端版本庫,其他成員電腦上的版本庫稱之為本地版本庫。後面會詳細介紹。
分散式版本控制系統的網路拓撲圖如下圖所示:
分散式版本控制系統剔除了中央伺服器,這充分體現了分散式的核心概念,就是去中心化。這樣帶來的好處有兩點:
系統 | 版本 |
---|---|
Windows | Windows10 |
Linux | Ubuntu16.04 |
說完了Git的基本概念,接下來還是安裝個Git使用者端下來耍一耍。這裡分不同的作業系統簡單的介紹一下Git使用者端的安裝。
首先通過git --version
命令檢視電腦上是否已經安裝了Git使用者端。
如果已經安裝了就可以跳過此章節。如果沒有安裝的話就接著往下面看:
Linux系統有不同的發行版本,可以通過cat /proc/version
命令檢視Linux的版本。
sudo apt-get install git
yum install git -y
如果找不到yum命令的話,則需要先安裝yum工具。可以參考下面命令
#刪除yum.repos.d目錄下所有檔案rm -f /etc/yum.repos.d/*#然後重新下載阿里的yum源wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo#清除快取yun clean all
Git的官方下載地址是:Git的下載地址
下載好安裝包之後,一直點選下一步即可安裝。再次就不在贅述。
Windows下安裝好Git之後會出現Git Bash 和Git GUI兩個應用程式,其中Git Bash是Git的命令列工具,而Git GUI則是Git的視覺化工具(一般很少用)。
建立本地版本庫分為兩步:
第一步是建立一個空資料夾,命名為: git_learn。
第二步就是在該資料夾下執行git init
命令將該資料夾變成git可以管理的版本庫。
執行第二步之後,在 git_learn目錄下會出現一個名為.git的隱藏資料夾,該資料夾就是git的版本庫。切記不要手動修改.git資料夾下的任何內容,以免本地版本庫不可用。
本地版本庫建好之後就可以在git_learn資料夾下建立一個檔案進行測試了。這裡建立了一個名為readme.txt的檔案。
新增到暫存區
通過git add readme.txt
命令可以將readme.txt檔案提交到暫存區(關於暫存區的概念後面會詳細介紹)。如果有多個檔案需要新增的話,可以執行git add .
命令。
提交到版本庫
因為git的本地都是有完整版本庫的,所以還需要將前面建立的readme.txt檔案提交到本地版本庫的當前分支,預設是master。命令格式是git commit -m '<message>'
,其中寫入你的提交備註。
這裡有兩個很重要的概念,一個是工作區,另一個是暫存區(Git特有的概念)。
工作區
工作區就是你電腦上能看到的目錄(不包括隱藏檔案),例如:git_learn目錄就是一個工作區。
暫存區
工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫,其中最重要的是暫存區(stage)。
還有Git為我們自動建立的第一個分支叫master,以及指向master的一個指標叫HEAD。
前面提到了工作區,暫存區,git add
命令和git comit
命令。那麼他們之間有啥關係呢?下面就用一張流程圖展示一下:
通過add命令將工作區中ABC資料夾提交到暫存區stage,在通過commit命令將stage中的ABC資料夾提交到當前分支master。
Git管理的是修改而非檔案。這裡的修改指的是對工作區的任何操作,包括新增檔案;刪除檔案;修改檔案等等。哪怕是在檔案中增加一句話或者刪除一個字元都可以算是修改。下面就舉例說明下,還是以readme.txt檔案為例:
git add readme.txt
,並通過命令git status
檢視狀態。git tracks changes
。直接執行git commit -m 'git tracks changes'
命令。然後通過 git status
,可以發現第二次的修改沒有提交。這是因為第二次的修改沒有先提交到暫存區中。
我們的操作過程是第一次修改 -> git add -> 第二次修改 -> git commit
。當使用git add
命令後,在工作區中的第一次修改被放入暫存區中,準備提交,在工作區中的第二次修改沒有被放入暫存區中,所以,git commit
只負責把暫存區中的修改提交到當前分支。所以第二次的修改沒有提交。
也就是說,所有的修改必須先通過git add 提交到暫存區,然後通過git commit 提交到當前分支。。在實際開發中一般是將所有修改合併起來add,然後在一起commit。
當前分支上有一個已經廢棄不用的檔案,該如何刪除呢?比如要刪除一個名為test1.txt檔案。只需要兩行命令。
git rm test1.txtgit commit -m "remove test.txt"
前面介紹了在實際開發中,一般會拿一臺電腦作為「中央倉庫」,充當中央倉庫的電腦需要安裝一個程式碼倉庫軟體,這裡選用開源軟體GitLab,它是基於git實現的線上程式碼倉庫軟體,提供web視覺化管理介面,可以在本地部署。通常用於企業團隊內部共同作業開發。當然,如果你不想搭建私人的git倉庫,那麼也可以直接使用最大的同性交友網站Github(使用與GitLab類似)。
那麼該如何在Ubuntu上安裝GitLab軟體,搭建私有的Git倉庫呢?
#更新apt源sudo apt-get update#安裝依賴包,執行命令sudo apt-get install curl openssh-server ca-certificates postfixsudo apt-get install -y postfix
curl https://packages.gitlab.com/gpg.key 2> /dev/null | sudo apt-key add - &>/dev/null
sudo vi /etc/apt/sources.list.d/gitlab-ce.list
在該檔案中寫入如下程式碼
deb https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu xenial main
sudo apt-get updatesudo apt-get install gitlab-ce
安裝gitlab-ce成功之後。
5. 修改外部url
在gitlab組態檔/etc/gitlab/gitlab.rb中修改外部url,改為自己的ip地址或者域名。
sudo vi /etc/gitlab/gitlab.rb
找到external_url,修改其預設的地址,這裡改成了我本機區域網IP:192.168.40.138
external_url 'http://192.168.40.138/' ## 本機的區域網ip地址為192.168.41.128
sudo gitlab-ctl reconfigure
sudo gitlab-ctl start
可以通過ps -ef|grep gitlab
命令檢視GitLab是否啟動成功。
8. 進行瀏覽器存取
GitLab成功啟動之後就可以通過瀏覽器存取GitLab的主頁了。在瀏覽器上輸入http://192.168.40.138/
;
預設輸入的使用者名稱是root使用者,輸入的密碼是root的賬戶密碼。
至此GitLab的安裝就全部結束,我們也成功的搭建了屬於自己的Git倉庫。
點選設定按鈕,進入設定欄,選中Users->New User
進入新增使用者頁面。
輸入姓名,使用者名稱,和郵箱即可註冊新增新使用者。
使用者新增好之後,就是將使用者新增到團隊中,GitLab中預設會有一個名為GitLab Instance的團隊,你也可以新增自己的團隊,這裡我新增了一個名為ai_edu的團隊。並在團隊中新增了兩個成員。
選中要新增成員的團隊,在右側會出現一個新增Add user(s) to the group的欄目。再此欄目中所有使用者並新增到團隊中。使用者的角色有遊客,測試人員,開發人員,管理者,擁有者等幾個不同的角色。
說完了使用者和團隊的設定後,現在就進入了重點了,如何新建一個遠端倉庫。同樣也是比較方便。操作步驟是:Project->Your projects->New project
這裡新建了一個名為git_test的遠端倉庫,倉庫的所有這是屬於ai_edu團隊。
這裡倉庫的許可權等級有三個等級,分別是:Private(只有你團隊的人才能拉取和推播程式碼),Internal(除了黑名單之外的使用者可以拉取和推播程式碼)。Public (所有的使用者都可以拉取)。
為啥要設定SSH key呢?這是因為GitLab與你的電腦是通過SSH協定來通訊的。說白了,如果你沒有設定SSH key的話,則你不能推播程式碼到遠端庫。這裡首先在你本地生成公鑰和私鑰檔案,然後把公鑰檔案的內容複製到GitLab上。
git config --global user.name 「username」
git config --global user.email [email protected]
[email protected]替換成你實際的郵箱地址。不需要加單引號。
4. 生成公鑰和私鑰
ssh-keygen -C 'you email [email protected]' -t rsa
如果簡單些的話可以直接填寫ssh-keygen
命令。郵箱地址填寫前面設定的郵箱地址。有提示的話一直按Enter鍵。正確執行後會輸入如下資訊
2 找到公鑰檔案id_rsa.pub,複製公鑰內容到GitLab
分支的概念:分支就是每次提交建立的點所連線成的時間線。這條時間線就是一個分支,預設的話只有一個主分支master分支。HEAD嚴格來說不是指向提交,而是指向master,master才是指向提交,HEAD指向的就是當前分支。
一開始的時候,master分支就是一條線,Git用master指向最新的提交,再用HEAD指向master,就能夠確定當前的分支以及當前分支的提交點。
每次提交,master分支都會向前進移動一步,這樣隨著你不斷提交,master分支的線也會越來越長。其結構如下圖所示:
當我們新建立一個分支dev時,Git會建立一個指標dev指向master分支當前的提交點。當切換到dev分支後,HEAD指標會指向dev。也就是說HEAD始終是指向當前分支的。
git checkout -b dev
git checkout 加上-b參數列示建立並切換到dev分支上,相當於下面兩條命令。
$ git branch dev $ git checkout dev
執行該上面的命令之後的git的提交時間線如下圖所示:
當在dev分支上提交程式碼(未改變master分支)之後,dev分支會不斷的向後推進。而master指標的指向則不會變。git checkout
命令是一個比較特殊的命令,傳入不同的引數會有截然不同的效果。例如:git checkout -- file
命令,表示的意思是復原file檔案中所有的修改。所以Git還提供了git switch
命令用於建立和切換分支。
## 建立並切換到新的dev分支git switch -c dev## 切換到已有的master分支git switch master
分支建立好之後,可以通過git branch
命令進行檢視。
當團隊成員在dev分支上開發完畢之後,就可以將dev分支上的內容合併到master分支上,合併分支的原理就是將master指標指向dev的當前提交。Git合併分支只是改了下指標,工作區的內容沒有改變。
其合併的命令分兩步,第一步是切換到master分支,第二步是合併dev分支
#切換到master分支git checkout master#合併dev分支git merge dev
git branch -d dev
在團隊共同作業過程中,難免會碰到各種修改衝突。那麼該如何解決這些衝突呢? 例如:你和你同事分別修改了readme.txt檔案,那麼當你們同時提交時就會出現衝突。又或者在你在master分支和feature1分支上分別修改了readme.txt檔案。那麼當你合併feature1分支到master分支時就會出現衝突。舉個栗子吧:
處理衝突
。然後提交到feature1分支。衝突處理 master有衝突
然後提交到master分支上。
3. 將feature1分支合併到master分支,此時就會出現合併衝突。如下圖所示:
衝突之後,Git用<<<<<<<,=======,>>>>>>>標記出不同分支的內容。如下圖所示:
處理衝突的方式就是編輯衝突內容。然後重新提交。
$ git add README.md $ git commit -m "解決衝突"
git diff 36e4fd7 b55da38
git diff HEAD
通常情況下,Git在合併分支時,會使用Fast forward模式。但是,這種模式下,刪除分支後,會丟掉分支資訊。如下圖所示,刪除dev分支之後,分支的資訊也就就丟失了
如果要強制禁用Fast forward模式,Git會在merge時生成一個新的commit。當刪除分支時就不會丟失分支資訊。其命令是git merge --no-ff -m "merge with no-ff" dev
準備合併dev分支,其中--no-ff
引數,表示禁用Fast forward,因為本次合併要建立一個新的commit,所以加上-m
引數。把commit描述寫進去。
當你接到一個修復代號為01的bug的任務時,很自然地,你會建立一個分支issue-01來修復它,但是,如果這是你正在dev分支上進行的工作還沒有提交,提交吧,可是你在dev上的工作只進行了一般,還沒法提交,預計完成還需1天的時間。但是,現在必須要在兩個小時內修復代號01的bug。這時候該怎麼辦呢?你不是期望有一個功能可以隱藏你當前在dev上未提交的工作,然後,切換到issue-01分支修改bug呢。
通過stash功能可以滿足你的願望,將當前工作現場隱藏起來。如下圖所示:執行git stash
命令之後,新建的hello.html檔案就從工作區中消失了。
git stash
git stash命令可以將當前未提交的工作隱藏起來。讓你的工作區變的乾淨清爽。
git stash list 可以檢視當前倉庫所有已經儲存的工作現場。
git stash list
現在代號為01的bug已經修復好了,你可以繼續切換到dev分支上進行開發了。那麼這時候你需要做的第一件事就是恢復之前儲存的工作現場。恢復工作現場的命令是:
git stash apply
通過git stash apply
命令可以恢復工作現場。但是,恢復之後工作現場還在。那麼這時候我們還需要一個命令來刪除工作現場。其命令是:
git stash drop
恢復工作現場一條命令,刪除工作現場又是一條命令。未免有點繁瑣了吧。有沒有將兩者合二為一的命令呢?答案是有的:通過下面的命令就可以實現:
git stash pop
在master分支上修復了bug後,我們想一想,dev分支是早期從master分支分出來的,所以,這個bug其實在當前dev分支上也存在。那怎麼在dev分支上修復同樣的bug?重複操作一次,提交不就行了?這種方法也不是不行,如果該BUG涉及的修改過多,這樣的方式就顯得有點捉襟見肘了。那麼我們能不能把修改BUG做的提交複製到當前的dev分支呢?答案是有的:
git cherry-pick 821ea4d
通過git cherry-pick
命令可以將單個的提交複製到當前分支。可以通過 git log 檢視提交的提交的版本號。
新增一個新功能時,你肯定不希望因為一些實驗性質的程式碼,把主分支搞亂了,所以,每新增一個新功能,最好新建一個feature分支,在上面開發,完成後,合併,最後,刪除該feature分支。
前面介紹可以通過git branch -d branchname
命令刪除分支。但是,如果被刪除的分支還沒有合併到主分支的話,用該命令刪除的話分支的話,Git會丟擲一個錯誤提示並不能刪除該分支。如下:要刪除一個名為feature-01的分支。但是該分支還沒有被merge。這時候就需要強制刪除分支的命令了。
git branch -D feature-01
其中feature-01為待刪除的分支名。其實就是將-d
引數換成-D
引數。
前面說了那麼多,好像都是一個人在本地操作,沒有涉及到多人共同作業的情況。這在團隊開發中肯定是不可能的啦,因為我們是一個team。那麼多人共同作業的情況涉及哪些操作呢?
git remote add origin http://192.168.40.138/ai-edu/git-demo.git
或者,推薦使用下面這種,因為前面設定了SSH公鑰和私鑰
git remote add origin [email protected]:jayxiang31/python_learn.git
git pull --rebase origin master
前面第三章已經搭好了私有的Git倉庫管理器GitLab。同時也建立了一個名為git_test的倉庫。現在要做的就是將遠端倉庫克隆下來。克隆的命令是git clone
git clone http://192.168.40.138/ai-edu/git_test.git
其中http://192.168.40.138/ai-edu/git_test.git
是遠端倉庫的地址。
當然也可以在IDEA上直接通過圖形介面操作,還省去了匯入專案的過程。其操作步驟是:
File->New->Project from Version Control->Git
。如下圖所示:git remote rm origin
通過git remote
命令可以檢視遠端倉庫,origin表示遠端主機。
通過git remote -v
命令可以檢視遠端倉庫詳細的資訊,包括遠端倉庫的地址。
$ git remote -v origin http://192.168.40.138/ai-edu/git_test.git (fetch)origin http://192.168.40.138/ai-edu/git_test.git (push)
上面顯示了可以抓取和推播的origin的地址。如果沒有推播許可權,就看不到push的地址。
現在將遠端倉庫克隆下來了,那麼該如何將當前分支上所有的本地提交推播到遠端庫呢?答案是通過git push
命令,其語法結構是git push <remote branch> <local branch>
其中<remote branch>
表示遠端分支名,<local branch>
表示本地分支名。
git push origin master
該語句表示將原生的master分支推播到遠端的origin分支上。在實際應用中會在git push
命令後面加上-u
引數,就像git push -u origin master
這樣。這是因為如果當前分支與多個主機存在追蹤關係,則可以使用 -u 引數指定一個預設主機,這樣後面就可以不加任何引數使用git push。那麼哪些分支該與遠端分支保持一致呢?一般認為:
通過git push
命令還能建立遠端分支。
git push origin dev
假設你本地已經有了dev分支。通過上面的命令可以將dev分支推播到遠端庫,並建立遠端的dev分支。
通過git pull
命令可以拉取遠端倉庫的資料和分支資訊。假設如下這個場景:你同事在他本地建立了一個dev分支,並提交到了遠端庫。同時你也在本地建立了一個dev庫,當你push時會推播失敗。結果如下圖所示:
因為你同事的最新提交和你試圖推播的的提交有衝突。解決的辦法就是根據Git的提示,先用git pull
把最新的提交從origin/dev
抓下來,然後,在本地合併,解決衝突後,在推播。
$ git pull There is no tracking information for the current branch. Please specify which branch you want to merge with. See git-pull(1) for details. git pull <remote> <branch>If you wish to set tracking information for this branch you can do so with: git branch --set-upstream-to=origin/<branch> dev
git pull
也失敗了。原因是沒有指定本地dev分支與遠端origin/dev分支的連結,根據提示,設定dev和origin/dev的連結:
$ git branch --set-upstream-to=origin/dev dev Branch 'dev' set up to track remote branch 'dev' from 'origin'.
關聯好本地分支和遠端分支之後,在pull就能成功了。這回git pull
成功,但是合併有衝突,需要手動解決,解決的方式也是在本地手動處理衝突檔案,解決後,提交,在push。
通過
git push origin :dev
命令可以刪除遠端dev分支。但是這時候原生的dev分支還是存在的。所以還需要通過git branch -d dev
刪除原生的dev分支。
通過git branch
可以檢視本地分支
通過git branch -a
可以檢視本地分支和遠端分支。
在實際開發中我們經常會碰到這樣一個場景,比如:你誤提交了一段有問題的程式碼,導致其他同事更新程式碼之後專案啟動不了,這時候該怎麼辦呢?我們首先想到的就是將版本回退。回退到之前那個沒有問題的版本。
git log
命令找到當前的倉庫所有的提交紀錄檔。然後,找到你需要回退到的版本。如下圖所示:git reset HEAD
git reset commitId
其中commitId是指定版本的版本號,比如這裡將版本資訊回退到b50c9bdcbf9641d33e4b531bd96dc1f27d4bf602
這個版本。那麼命令就是:git reset b50c9bdcbf9641d33e4b531bd96dc1f27d4bf602
回退之後,再次通過git log
檢視,則最新的提交紀錄檔已經變成了hello 提交
這個版本了。
當然,通過IDEA來回退則更加的簡單。直接在Version Control->Log
在待回退到的版本上右鍵,選中Reset Current Branch to Here
即可。
其實回退操作的本質,就是將HEAD指標的指向要回退的那個版本上。
git branch -m oldname newname
標籤管理比較簡單,再此只是簡單描述一下。
#建立標籤 v1.0git tag v1.0#檢視標籤git tag#刪除標籤v1.0git tag -d v0.1#推播標籤git push origin --tags#刪除遠端標籤git push origin :refs/tags/v1.0
這張圖清晰的表明了Git的基本流程。
推薦學習:《》
以上就是完全掌握Git倉庫的搭建以及分支管理的詳細內容,更多請關注TW511.COM其它相關文章!