git總結

Git 誕生

linux之父Linus爲了更好的管理他本身的開源項目linux系統而本身開發了一個軟件,這個軟件能夠幫助Linux更好的進行開源開發,名字就叫Git。linux

它是個分佈式版本控制系統,Git是最當前流行的分佈式版本控制系統,尤爲是2008年,GitHub網站上線了,它爲開源項目免費提供Git存儲,無數開源項目開始遷移至GitHub,包括jQuery,PHP,Ruby等等。git

安裝Git

ubuntu下:

sudo apt-get install gi

能夠直接經過源碼安裝,先從Git官網下載源碼,而後解壓,以後:

./config
make
sudo make install

建立版本庫

什麼是版本庫呢?版本庫又名倉庫,英文名repository,你能夠簡單理解成一個目錄,這個目錄裏面的全部文件均可以被Git管理起來,每一個文件的修改、刪除,Git都能跟蹤,以便任什麼時候刻均可以追蹤歷史,或者在未來某個時刻能夠「還原」github

建立本地倉庫的兩種方法:

  • 從服務器上克隆倉庫:git clone git@github.com:slaming/Markdown.git
  • 在工做區初始化倉庫: git init

建立完版本庫,當前路徑裏就會發現一個.git的文件夾,這個就是Git的版本庫。Git版本庫裏面有一個稱爲stage(或者叫index)的暫存區,和還有Git爲咱們自動建立的第一個分支master,以及指向master的第一個指針HEAD,示意圖以下:算法

image

將工做區的更改加入本地倉庫

咱們把文件往Git版本庫裏添加的時候,是分兩步執行的:

(1) 用 git add 命令把變化加入到暫存區

  • git add .
  • git add 文件名

image

(2)用 git commit 將緩存區的全部內容提交到當前分支,因爲咱們建立Git版本庫時,Git自動爲咱們建立了惟一一個master分支,因此,如今,git commit就是往master分支上提交更改。

  • git commit -m "提交描述"

image

一旦提交後,若是你又沒有對工做區作任何修改,那麼工做區就是「乾淨」的,利用git status查看:

$ git status
On branch master
nothing to commit, working tree clean

關聯遠程倉庫

(1)與github遠程倉庫關聯

$ git remote add origin git@github.com:slaming/learngit.git

添加後,遠程庫的名字就是origin,這是Git默認的叫法,也能夠改爲別的,可是origin這個名字一看就知道是遠程庫。ubuntu

(2)本地倉庫向遠程倉庫提交

$ git push -u origin master

若是遠程庫是空的,咱們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在之後的推送或者拉取時就能夠簡化命令。緩存

本地建立新的分支

(1)經常使用命令

建立新的分支:服務器

$ git branch dev

切換到dev分支:分佈式

$ git checkout dev

爲了簡單,經常使用下面命令,建立新的分支dev,而且切換到dev分支:工具

$ git checkout -b dev

查看版本庫有什麼分支,git branch命令會列出全部分支,當前分支前面會標一個*號:佈局

$ git branch
* dev
master

合併分支:

$ git merge dev

(2)建立與合併分支

每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來講不是指向提交,而是指向master,master纔是指向提交的,因此,HEAD指向的就是當前分支。

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能肯定當前分支,以及當前分支的提交點,每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也愈來愈長:

image

當咱們建立新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:

image

從如今開始,對工做區的修改和提交就是針對dev分支了,好比新提交一次後,dev指針往前移動一步,而master指針不變:

image

假如咱們在dev上的工做完成了,就能夠把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是切換到master分支,直接把master指向dev的當前提交,這樣就完成了合併:

image

(3) 分支合併的衝突

假如開闢了新的分支features1

$ git checkout -b feature1

修改readme.txt最後一行,改成:

Creating a new branch is quick AND simple.

提交:

$ git add readme.txt

$ git commit -m "AND simple"

切換到master分支:

$ git checkout master

在master分支上把readme.txt文件的最後一行改成:

Creating a new branch is quick & simple.

提交:

$ git add readme.txt

$ git commit -m "& simple"

image

合併:

$ git merge feature1

這時Git不能自動合併,會出現衝突。

git merge 的原理

三路合併

三路合併就是先找出一個基準,而後以基準爲Base 進行合併,若是2個文件相對基準(base)都發生了改變 那git 就報衝突,而後讓你人工決斷。不然,git將取相對於基準(base)變化的那個爲最終結果。

image

Base 表明上一個版本,即公共祖先
Mine 表明你本地修改
Theirs 表明其餘人修改
這樣當git進行合併的時候,git就知道是其餘人修改了,本地沒有更改,git就會自動把最終結果變成以下,這個結構也是大多merge 工具的常見佈局。

image

若是換成下面的這樣,就須要人工解決了:

image

上面就是git merge 最基本的原理 「三路合併」。

下面的合併就是咱們常見的分支graph,結合具體分析

image

上面①~⑨表明一個個修改集合(commit)每一個commit都有一個惟一7位SHA-1惟一表示。
①,②,④,⑦修改集串聯起來就是一個鏈,此時用master指向這個集合就表明master分支,分支本質是一個快照,其實類比C中指針
一樣dev分支也是由一個個commit組成
如今在dev分支上因爲各類緣由要運行git merge master須要把master分支的更新合併到dev分支上,本質上就是合併修改集 ⑦(Mine) 和 ⑧(Theirs) ,此時咱們要 利用DAG(有向無環圖)相關算法找到咱們公共的祖先 ②(Base)而後進行三方合併,最後合併生成 ⑨。

多人協做

你從遠程倉庫克隆到本地,就能夠開始你的開發了。

要查看遠程庫的信息,用git remote:

$ git remote
origin

或者,用git remote -v顯示更詳細的信息:

$ git remote -v
origin  git@github.com:slaming/learngit.git (fetch)
origin  git@github.com:slaming/learngit.git (push)

上面顯示了能夠抓取和推送的origin的地址。若是沒有推送權限,就看不到push的地址。

把分支上的全部本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上:

$ git push origin dev

可是,並非必定要把本地分支往遠程推送,那麼,哪些分支須要推送,哪些不須要呢?

  • master分支是主分支,所以要時刻與遠程同步;

  • dev分支是開發分支,團隊全部成員都須要在上面工做,因此也須要與遠程同步;
  • bug分支只用於在本地修復bug,就不必推到遠程了,除非老闆要看看你每週到底修復了幾個bug;
  • feature分支是否推到遠程,取決於你是否和你的小夥伴合做在上面開發。

在實際開發中,咱們應該按照幾個基本原則進行分支管理:

首先,master分支應該是很是穩定的,也就是僅用來發布新版本,平時不能在上面幹活;

那在哪幹活呢?幹活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,好比1.0版本發佈時,再把dev分支合併到master上,在master分支發佈1.0版本;

你和你的小夥伴們每一個人都在dev分支上幹活,每一個人都有本身的分支,時不時地往dev分支上合併就能夠了。

因此,團隊合做的分支看起來就像這樣:

image

抓取分支

多人協做時,你們都會往master和dev分支上推送各自的修改。

當你的小夥伴已經向origin/dev分支推送了他的提交,而碰巧你也對一樣的地方做了修改,並試圖推送:

$ git push origin dev

推送會失敗,由於你的小夥伴的最新提交和你試圖推送的提交有衝突,和merge相似。這時須要手動改寫。

相關文章
相關標籤/搜索