1. 程式人生 > >Git分布式版本控制系統

Git分布式版本控制系統

change inux epo bug 意思 成功 user ack resp

1.linux 安裝git

sudo apt-get install git

創建版本庫(當前文件夾為工作空間)

$ git init
Initialized empty Git repository in d:/localresporty/.git/

版本庫(Repository)

工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。具體參考http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013745374151782eb658c5a5ca454eaa451661275886c6000

Git的版本庫裏存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動創建的第一個分支master

,以及指向master的一個指針叫HEAD

技術分享

在當前文件夾下創建文件

$ touch a.txt

第一步,用命令git add告訴Git,把文件修改添加到暫存區

$ git add a.txt

第二步,用命令git commit告訴Git,把暫存區的所有內容提交到當前分支:Git自動為我們創建了唯一一個master分支

$ git commit -m "zhu shi 1"

第三步

$ git push origin brandon.ma

完成

二:版本回退

1 . 查看當前倉庫當前的狀態

$ git status

2. 查看文件作了什麽修改(且沒有add到倉庫

$ git diff a.txt
diff --git a/a.txt b/a.txt index 9ac30bc..8c9534b 100644 --- a/a.txt +++ b/a.txt @@ -1 +1 @@ -this is two . +this is tw .^M

3.顯示從最近到最遠的提交日誌

$ git log
commit 04853c688c41d72e2efcb34f59b163bdaae6b17c
Author: Brandon Ma <[email protected]>
Date:   Sat Jul 15 15:37:46 2017 +0800

    zhu shi 3

commit 05b8bcec10435f2d688c536ffc10a74df7cd25c7
Author: Brandon Ma 
<[email protected]> Date: Sat Jul 15 15:33:54 2017 +0800 zhu shi 2 commit 4080700e24a3714edba71deb34072d754a48245f Author: Brandon Ma <[email protected]> Date: Sat Jul 15 15:28:23 2017 +0800 zhu shi 1
$ git log --pretty=oneline   只顯示 commit id
04853c688c41d72e2efcb34f59b163bdaae6b17c zhu shi 3
05b8bcec10435f2d688c536ffc10a74df7cd25c7 zhu shi 2
4080700e24a3714edba71deb34072d754a48245f zhu shi 1

在Git中,用HEAD表示當前版本,也就是最新的提交3628164...882e1e0(註意我的提交ID和你的肯定不一樣),上一個版本就是HEAD^,上上一個版本就是HEAD^^,當然往上100個版本寫100個^比較容易數不過來,所以寫成HEAD~100。回到上一個版本

,也可寫commit id技術分享

$ git reset --hard HEAD^
HEAD is now at 05b8bce zhu shi 2

$ cat a.txt    文件以回到上個版本
this is two .

後悔了若要回到新的版本

$ git reflog   查找所有的記錄
05b8bce HEAD@{0}: reset: moving to HEAD^
04853c6 HEAD@{1}: commit: zhu shi 3
05b8bce HEAD@{2}: commit: zhu shi 2
4080700 HEAD@{3}: commit (initial): zhu shi 1
$ git reset --hard 4080700   回到新的版本
HEAD is now at 4080700 zhu shi 1

丟棄工作區的修改

$ git checkout -- a.txt

命令git checkout -- readme.txt意思就是,把readme.txt文件在工作區的修改全部撤銷,

場景1:當你改亂了工作區某個文件的內容,想直接丟棄工作區的修改時,用命令git checkout -- file

場景2:當你不但改亂了工作區某個文件的內容,還添加到了暫存區時,想丟棄修改,分兩步,第一步用命令git reset HEAD file,就回到了場景1,第二步按場景1操作。

場景3:已經提交了不合適的修改到版本庫時,想要撤銷本次提交,參考版本回退一節,不過前提是沒有推送到遠程庫。

沒有--,就變成了“切換到另一個分支”的命令

4. 刪除文件

$ rm  a.txt

$ git rm a.txt   確實要從版本庫中刪除該文件

$ git commit -m "buxiang yao le " 提交

誤刪的話 ,相當於修改後後悔 , 返回版本庫操作

$ git checkout --file

三 ,遠程倉庫操作

第1步:創建SSH Key。在用戶主目錄下,看看有沒有.ssh目錄,如果有,再看看這個目錄下有沒有id_rsaid_rsa.pub這兩個文件,如果已經有了,可直接跳到下一步。如果沒有,打開Shell(Windows下打開Git Bash),創建SSH Key:

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

在用戶主目錄裏找到.ssh目錄,裏面有id_rsaid_rsa.pub兩個文件,這兩個就是SSH Key的秘鑰對,id_rsa是私鑰,不能泄露出去,id_rsa.pub是公鑰,可以放心地告訴任何人。

第2步:登陸GitHub,打開“Account settings”,“SSH Keys”頁面:

然後,點“Add SSH Key”,填上任意Title,在Key文本框裏粘貼id_rsa.pub文件的內容:

技術分享

關聯遠程庫並推送本地庫

$ git remote add origin [email protected]:maxingzheng/mxz.git
推送master分支的所有內容
$ git push -u origin master
從遠程克隆一個本地庫
$ git clone [email protected]:maxingzheng/mxz.git

四.分支管理

技術分享

當前在dev分支上

技術分享

假如我們在dev上的工作完成了,就可以合並

1.創建dev分支

$ git branch brandon  創建分支

[email protected] /D/mxz (master)
$ git checkout brandon  切換分支
Switched to branch brandon

[email protected] /D/mxz (brandon)

git checkout命令加上-b參數表示創建並切換

當在dev分支上進行一系列操作後,可以切換到master進行合並

$ git merge dev

合並完後刪除dev分支
$ git branch -d dev

沖突

master分支和feature1分支各自都分別有新的提交,變成了這樣:

技術分享

必須首先解決沖突。解決沖突後,再提交,合並完成。

git log --graph命令可以看到分支合並圖。

分支管理策略

閱讀: 473979

通常,合並分支時,如果可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。

如果要強制禁用Fast forward模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就可以看出分支信息。

下面我們實戰一下--no-ff方式的git merge

首先,仍然創建並切換dev分支:

$ git checkout -b dev
Switched to a new branch ‘dev‘

修改readme.txt文件,並提交一個新的commit:

$ git add readme.txt 
$ git commit -m "add merge"
[dev 6224937] add merge
 1 file changed, 1 insertion(+)

現在,我們切換回master

$ git checkout master
Switched to branch ‘master‘

準備合並dev分支,請註意--no-ff參數,表示禁用Fast forward

$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the ‘recursive‘ strategy.
 readme.txt |    1 +
 1 file changed, 1 insertion(+)

因為本次合並要創建一個新的commit,所以加上-m參數,把commit描述寫進去。

合並後,我們用git log看看分支歷史:

$ git log --graph --pretty=oneline --abbrev-commit
*   7825a50 merge with no-ff
|| * 6224937 add merge
|/
*   59bc1cb conflict fixed
...

可以看到,不使用Fast forward模式,merge後就像這樣:

技術分享


分支策略

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

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

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

你和你的小夥伴們每個人都在dev分支上幹活,每個人都有自己的分支,時不時地往dev分支上合並就可以了。

所以,團隊合作的分支看起來就像這樣:

技術分享

修復bug時,我們會通過創建新的bug分支進行修復,然後合並,最後刪除;

當手頭工作沒有完成時,先把工作現場git stash一下,然後去修復bug,修復後,再git stash pop,回到工作現場。

刪除未合並的分支

開發一個新feature,最好新建一個分支;

如果要丟棄一個沒有被合並過的分支,可以通過git branch -D <name>強行刪除

多人協作

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

$ git remote -v
origin  [email protected]:maxingzheng/mxz.git (fetch)
origin  [email protected]:maxingzheng/mxz.git (push)

多人協作

閱讀: 499364

當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,並且,遠程倉庫的默認名稱是origin

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

$ git remote
origin

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

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

上面顯示了可以抓取和推送的origin的地址。如果沒有推送權限,就看不到push的地址。

推送分支

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

$ git push origin 分支名

抓取分支

當你的小夥伴從遠程庫clone時,默認情況下,只能看到本地的master分支。git branch命令看看:

$ git branch
* master

要在dev分支上開發,就必須創建遠程origindev分支到本地,於是他用這個命令創建本地dev分支:

$ git checkout -b dev origin/dev

現在,他就可以在dev上繼續修改,然後,時不時地把dev分支push到遠程:

$ git push origin 分支名

  1. 首先,可以試圖用git push origin branch-name推送自己的修改;

  2. 如果推送失敗,則因為遠程分支比你的本地更新,需要先用git pull試圖合並;

  3. 如果合並有沖突,則解決沖突,並在本地提交;

  4. 沒有沖突或者解決掉沖突後,再用git push origin branch-name推送就能成功!

如果git pull提示“no tracking information”,則說明本地分支和遠程分支的鏈接關系沒有創建,用命令git branch --set-upstream branch-name origin/branch-name

  • 命令git tag <name>用於新建一個標簽,默認為HEAD,也可以指定一個commit id;

  • git tag -a <tagname> -m "blablabla..."可以指定標簽信息;

  • git tag -s <tagname> -m "blablabla..."可以用PGP簽名標簽;

  • 命令git tag可以查看所有標簽。

    • 命令git push origin <tagname>可以推送一個本地標簽;

    • 命令git push origin --tags可以推送全部未推送過的本地標簽;

    • 命令git tag -d <tagname>可以刪除一個本地標簽;

    • 命令git push origin :refs/tags/<tagname>可以刪除一個遠程標簽。

標簽

給當前分支打上標簽 默認標簽是打在最新提交的commit上的

$ git tag v1.0 (commitid)

讓Git顯示顏色,會讓命令輸出看起來更醒目:

$ git config --global color.ui true
  • 忽略某些文件時,需要編寫.gitignore

  • .gitignore文件本身要放到版本庫裏,並且可以對.gitignore做版本管理

搭建Git服務器

第一步,安裝git

$ sudo apt-get install git

第二步,創建一個git用戶,用來運行git服務:

$ sudo adduser git

第三步,創建證書登錄:

收集所有需要登錄的用戶的公鑰,就是他們自己的id_rsa.pub文件,把所有公鑰導入到/home/git/.ssh/authorized_keys文件裏,一行一個。

第四步,初始化Git倉庫:

先選定一個目錄作為Git倉庫,假定是/srv/sample.git,在/srv目錄下輸入命令:

$ sudo git init --bare sample.git

Git就會創建一個裸倉庫,裸倉庫沒有工作區,因為服務器上的Git倉庫純粹是為了共享,所以不讓用戶直接登錄到服務器上去改工作區,並且服務器上的Git倉庫通常都以.git結尾。然後,把owner改為git

$ sudo chown -R git:git sample.git

第五步,禁用shell登錄:

出於安全考慮,第二步創建的git用戶不允許登錄shell,這可以通過編輯/etc/passwd文件完成。找到類似下面的一行:

git:x:1001:1001:,,,:/home/git:/bin/bash

改為:

git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

這樣,git用戶可以正常通過ssh使用git,但無法登錄shell,因為我們為git用戶指定的git-shell每次一登錄就自動退出。

第六步,克隆遠程倉庫:

現在,可以通過git clone命令克隆遠程倉庫了,在各自的電腦上運行:

$ git clone git@server:/srv/sample.git
Cloning into ‘sample‘...
warning: You appear to have cloned an empty repository.

剩下的推送就簡單了。

管理公鑰

如果團隊很小,把每個人的公鑰收集起來放到服務器的/home/git/.ssh/authorized_keys文件裏就是可行的。如果團隊有幾百號人,就沒法這麽玩了,這時,可以用Gitosis來管理公鑰。

這裏我們不介紹怎麽玩Gitosis了,幾百號人的團隊基本都在500強了,相信找個高水平的Linux管理員問題不大。

管理權限

有很多不但視源代碼如生命,而且視員工為竊賊的公司,會在版本控制系統裏設置一套完善的權限控制,每個人是否有讀寫權限會精確到每個分支甚至每個目錄下。因為Git是為Linux源代碼托管而開發的,所以Git也繼承了開源社區的精神,不支持權限控制。不過,因為Git支持鉤子(hook),所以,可以在服務器端編寫一系列腳本來控制提交等操作,達到權限控制的目的。Gitolite就是這個工具。

這裏我們也不介紹Gitolite了,不要把有限的生命浪費到權限鬥爭中。

參考:廖學鋒 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

Git分布式版本控制系統