分佈式版本控制系統Git的安裝與使用

做業要求

1.(本次做業要求來自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2103java

2.  個人Github遠程倉庫地址: https://github.com/llgeill/llg-centos-git--testlinux

3.  個人Github遠程倉庫地址截圖android

做業內容

1.Git的由來

不少人都知道,Linus在1991年建立了開源的Linux,今後,Linux系統不斷髮展,已經成爲最大的服務器系統軟件了。git

Linus雖然建立了Linux,但Linux的壯大是靠全世界熱心的志願者參與的,這麼多人在世界各地爲Linux編寫代碼,那Linux的代碼是如何管理的呢?github

事實是,在2002年之前,世界各地的志願者把源代碼文件經過diff的方式發給Linus,而後由Linus本人經過手工方式合併代碼!web

你也許會想,爲何Linus不把Linux代碼放到版本控制系統裏呢?不是有CVS、SVN這些免費的版本控制系統嗎?由於Linus堅決地反對CVS和SVN,這些集中式的版本控制系統不但速度慢,並且必須聯網才能使用。有一些商用的版本控制系統,雖然比CVS、SVN好用,但那是付費的,和Linux的開源精神不符。spring

不過,到了2002年,Linux系統已經發展了十年了,代碼庫之大讓Linus很難繼續經過手工方式管理了,社區的弟兄們也對這種方式表達了強烈不滿,因而Linus選擇了一個商業的版本控制系統BitKeeper,BitKeeper的東家BitMover公司出於人道主義精神,受權Linux社區無償使用這個版本控制系統。shell

安定團結的大好局面在2005年就被打破了,緣由是Linux社區牛人彙集,難免沾染了一些梁山好漢的江湖習氣。開發Samba的Andrew試圖破解BitKeeper的協議(這麼幹的其實也不僅他一個),被BitMover公司發現了(監控工做作得不錯!),因而BitMover公司怒了,要收回Linux社區的無償使用權。數據庫

Linus能夠向BitMover公司道個歉,保證之後嚴格管教弟兄們,嗯,這是不可能的。實際狀況是這樣的:bootstrap

Linus花了兩週時間本身用C寫了一個分佈式版本控制系統,這就是Git!一個月以內,Linux系統的源碼已經由Git管理了!牛是怎麼定義的呢?你們能夠體會一下。

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

歷史就是這麼偶然,若是不是當年BitMover公司威脅Linux社區,可能如今咱們就沒有免費而超級好用的Git了。

2.什麼是Git

  • 從定義上來講Git就是一個分佈式版本控制系統
  • 從做用上來講Git就是管理一些文本或者代碼的版本更新,例如內容的改動
  • 從管理的對象來講,全部的版本控制都只能針對文本內容,像word這樣的二進制內容,所謂版本,就是文件快照,不能比較差別,只能算帶備份的網盤

3.爲何git叫作分佈式版本控制系統

若是要想了解分佈式是什麼意思,那麼咱們得先去了解它的對立面集中式

集中式版本控制系統

  • 工具:CVS及SVN都是集中式的版本控制系統
  • 內容:集中式版本控制系統集中存放在中央服務器的,而幹活的時候,用的都是本身的電腦,因此要先從中央服務器取得最新的版本,而後開始幹活,幹完活了,再把本身的活推送給中央服務器。中央服務器就比如是一個圖書館,你要改一本書,必須先從圖書館借出來,而後回到家本身改,改完了,再放回圖書館。
  • 缺點:集中式版本控制系統最大的毛病就是必須聯網才能工做,若是在局域網內還好,帶寬夠大,速度夠快,可若是在互聯網上,遇到網速慢的話,可能提交一個10M的文件就須要5分鐘,這還不得把人給憋死啊。

central-repo

 

分佈式版本控制系統

工具:git

內容:布式版本控制系統沒有「中央服務器」,每一個人的電腦上都是一個完整的版本庫,這樣,你工做的時候,就不須要聯網了,由於版本庫就在你本身的電腦上。既然每一個人電腦上都有一個完整的版本庫,那多我的如何協做呢?比方說你在本身電腦上改了文件A,你的同事也在他的電腦上改了文件A,這時,大家倆之間只需把各自的修改推送給對方,就能夠互相看到對方的修改了。

優勢:和集中式版本控制系統相比,分佈式版本控制系統的安全性要高不少,由於每一個人電腦裏都有完整的版本庫,某一我的的電腦壞掉了沒關係,隨便從其餘人那裏複製一個就能夠了。而集中式版本控制系統的中央服務器要是出了問題,全部人都無法幹活了。在實際使用分佈式版本控制系統的時候,其實不多在兩人之間的電腦上推送版本庫的修改,由於可能大家倆不在一個局域網內,兩臺電腦互相訪問不了,也可能今天你的同事病了,他的電腦壓根沒有開機。所以,分佈式版本控制系統一般也有一臺充當「中央服務器」的電腦,但這個服務器的做用僅僅是用來方便「交換」你們的修改,沒有它你們也同樣幹活,只是交換修改不方便而已。固然,Git的優點不單是沒必要聯網這麼簡單,後面咱們還會看到Git極其強大的分支管理,把SVN等遠遠拋在了後面(svn其實也有分支功能,不過是在服務器上的分支)

distributed-repo

 

集中式與分佈式的差別性

  1. 分佈式在每個用戶上都有一個版本控制而集中式沒有
  2. 因爲每個用戶都有本身的版本控制工具,因此服務器壓力幾乎沒有,而集中式版本工具的壓力全在服務器上,因此在協做人數上面分佈式版本工具更勝一籌

4.開始安裝Git

Git安裝

能夠直接從官網下載相應操做系統的Git而後進行安裝,固然也能夠使用命令行的方式

  • 例如在使用Centos操做系統的時候,能夠使用以下命令快速安裝
  • yum install -y git
  • 或着不想使用命令行方式就直接去官網下載壓縮包
https://git-scm.com/

Git bash配置

用戶名和郵箱地址的做用

  1. 用戶名和郵箱地址是本地git客戶端的一個變量,不隨git庫而改變。
  2. 每次commit都會用用戶名和郵箱紀錄。
  3. github的contributions統計就是按郵箱來統計的。

修改用戶名和郵箱地址

  • $ git config --global user.name "username"
  • $ git config --global user.email  "email"

查看用戶名和郵箱地址

  • $ git config user.name
  • $ git config user.email

5.開始使用Git(版本庫)

如下全部操做都在centos上操做完成

什麼是版本庫

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

開始建立版本庫

首先,選擇一個合適的地方,建立一個空目錄

#建立一個文件件
[llg@localhost 桌面]$ mkdir llg-test-git
#進入文件夾目錄
[llg@localhost 桌面]$ cd llg-test-git/
#顯示當前文件夾路徑
[llg@localhost llg-test-git]$ pwd

接着,最重要的一步 經過git init 的命令將當前文件夾變成一個版本庫

[llg@localhost llg-test-git]$ git init
初始化空的 Git 版本庫於 /home/llg/桌面/llg-test-git/.git/
[llg@localhost llg-test-git]$

最後,經過ls -al 命令,發現多了個git文件夾。這個目錄是Git來跟蹤管理版本庫的,沒事千萬不要手動修改這個目錄裏面的文件,否則改亂了,就把Git倉庫給破壞了。

[llg@localhost llg-test-git]$ ls -al
總用量 4 
drwxrwsr-x 3 llg llg 18 9月 14 19:48 . 
drwsrwsrwt. 13 llg llg 4096 9月 14 19:44 ..
drwxrwsr-x 7 llg llg 119 9月 14 19:48 .git
[llg@localhost llg-test-git]$

 

開始添加文件到版本庫

首先須要注意的是版本管理的受衆範圍

  • 首先這裏再明確一下,全部的版本控制系統,其實只能跟蹤文本文件的改動,好比TXT文件,網頁,全部的程序代碼等等,Git也不例外。版本控制系統能夠告訴你每次的改動,好比在第5行加了一個單詞「Linux」,在第8行刪了一個單詞「Windows」。而圖片、視頻這些二進制文件,雖然也能由版本控制系統管理,但無法跟蹤文件的變化,只能把二進制文件每次改動串起來,也就是隻知道圖片從100KB改爲了120KB,但到底改了啥,版本控制系統不知道,也無法知道。
  • 不幸的是,Microsoft的Word格式是二進制格式,所以,版本控制系統是無法跟蹤Word文件的改動的,前面咱們舉的例子只是爲了演示,若是要真正使用版本控制系統,就要以純文本方式編寫文件。
  • 由於文本是有編碼的,好比中文有經常使用的GBK編碼,日文有Shift_JIS編碼,若是沒有歷史遺留問題,強烈建議使用標準的UTF-8編碼,全部語言使用同一種編碼,既沒有衝突,又被全部平臺所支持。
  • 使用Windows的童鞋要特別注意:千萬不要使用Windows自帶的記事本編輯任何文本文件。緣由是Microsoft開發記事本的團隊使用了一個很是弱智的行爲來保存UTF-8編碼的文件,他們自做聰明地在每一個文件開頭添加了0xefbbbf(十六進制)的字符,你會遇到不少難以想象的問題,好比,網頁第一行可能會顯示一個「?」,明明正確的程序一編譯就報語法錯誤,等等,都是由記事本的弱智行爲帶來的。建議你下載Notepad++代替記事本,不但功能強大,並且免費!記得把Notepad++的默認編碼設置爲UTF-8 without BOM便可:

首先,使用vi建立一個文件而且添加一些內容。確保此文件必須在這個版本倉庫裏面也就是咱們惡毒llg-test-git文件夾,否則放在其餘地方是不能被版本控制的。

[llg@localhost llg-test-git]$ vi llg.txt
[llg@localhost llg-test-git]$

接着,將文件顯示的經過git add命令添加到版本庫裏面,不過在這以前咱們使用git status 來查看一下還沒使用git add命令時候的狀態和使用git add以後的狀態,比較一下不一樣。經過比較,咱們發現了當使用git add 命令的時候實際上是創建起了文件跟蹤的功能,以後使用git status 就能夠看到有一個新文件

[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 
# 初始提交 
# 
# 未跟蹤的文件: 
# (使用 "git add <file>..." 以包含要提交的內容) 
# 
# llg.txt 
提交爲空,可是存在還沒有跟蹤的文件(使用 "git add" 創建跟蹤) 
[llg@localhost llg-test-git]$
[llg@localhost llg-test-git]$ git add llg.txt
[llg@localhost llg-test-git]$ git status
# 位於分支 master 
# 
# 初始提交 
# 
# 要提交的變動: 
# (使用 "git rm --cached <file>..." 撤出暫存區) 
# 
# 新文件: llg.txt 
# 
[llg@localhost llg-test-git]$

 

最後,使用git commit -m告訴Git,把文件提交到倉庫。-m是提交的一些說明信息,必需要寫,能夠方便本身和他人瞭解此次提交了什麼東西。

 

 

[llg@localhost llg-test-git]$ git commit -m "git練習測試" 
[master(根提交) abde635] git練習測試 
1 file changed, 1 insertion(+) 
create mode 100644 llg.txt 
[llg@localhost llg-test-git]$

 

疑問:爲何Git添加文件須要addcommit一共兩步呢?

由於commit能夠一次提交不少文件,因此你能夠屢次add不一樣的文件,好比下圖,能夠跟蹤多個文件而後所有一次性提交到版本庫裏面.

[llg@localhost llg-test-git]$ vi one.txt 
[llg@localhost llg-test-git]$ vi two.txt 
[llg@localhost llg-test-git]$ vi three.txt 
[llg@localhost llg-test-git]$ git add one.txt 
[llg@localhost llg-test-git]$ git add two.txt 
[llg@localhost llg-test-git]$ git add three.txt 
[llg@localhost llg-test-git]$ git commit -m "此次測試一次提交三個文件" 
[master 44449dc] 此次測試一次提交三個文件 
3 files changed, 4 insertions(+) 
create mode 100644 one.txt 
create mode 100644 three.txt 
create mode 100644 two.txt 
[llg@localhost llg-test-git]$
[llg@localhost llg-test-git]$ git status 
# 位於分支 master 
無文件要提交,乾淨的工做區 
[llg@localhost llg-test-git]$

 

6.Git版本回退

在學習版本回退以前咱們線來了解下兩個經常使用的命令git status和git diff

git status

剛剛在建立版本庫的時候咱們已經使用了,用來查看git的狀態,通常能夠拿來查看咱們作的某些操做以後的狀態,例如修改文件,添加文件等等

例如咱們修改一個文件而後使用git status查看,發現了提示llg.txt是修改過的文件

 


[llg@localhost llg-test-git]$ vi llg.txt 
[llg@localhost llg-test-git]$ git status 
# 位於分支 master 
# 還沒有暫存以備提交的變動:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工做區的改動) 
# 
# 修改: llg.txt 
# 
修改還沒有加入提交(使用 "git add" 和/或 "git commit -a") 
[llg@localhost llg-test-git]$

 

 

git sdiff

因爲文件修改事後,咱們有時候可能想知道具體修改了什麼內容,位置在那裏,區別是什麼等等。,因此咱們須要git sdiff命令來得到這個修改先後的對照信息

[llg@localhost llg-test-git]$ git diff 
diff --git a/llg.txt b/llg.txt 
index f77faef..2f3d837 100644 
--- a/llg.txt 
+++ b/llg.txt 
@@ -1 +1 @@ 
-my name is liliguang 
+My name is liliguang.I created three files a moment ago. 
[llg@localhost llg-test-git]$

 

以後繼續測試,修改其餘兩個文件內容
[llg@localhost llg-test-git]$ vi one.txt 
[llg@localhost llg-test-git]$ vi two.txt 
[llg@localhost llg-test-git]$ git diff
diff --git a/llg.txt b/llg.txt
index f77faef..2f3d837 100644
--- a/llg.txt
+++ b/llg.txt
@@ -1 +1 @@
-my name is liliguang
+My name is liliguang.I created three files a moment ago.
diff --git a/one.txt b/one.txt
index 25ab921..34144e1 100644
--- a/one.txt
+++ b/one.txt
@@ -1 +1,2 @@
this is one
+llg
diff --git a/two.txt b/two.txt
index 42b3fbc..0f62931 100644
--- a/two.txt
+++ b/two.txt
@@ -1,2 +1,2 @@
this is two
-
+llg
[llg@localhost llg-test-git]$

 

[llg@localhost llg-test-git]$ vi two.txt
[llg@localhost llg-test-git]$ git diff
diff --git a/llg.txt b/llg.txt
index f77faef..2f3d837 100644
--- a/llg.txt
+++ b/llg.txt
@@ -1 +1 @@
-my name is liliguang
+My name is liliguang.I created three files a moment ago.
diff --git a/one.txt b/one.txt
index 25ab921..34144e1 100644
--- a/one.txt
+++ b/one.txt
@@ -1 +1,2 @@
this is one
+llg
diff --git a/two.txt b/two.txt
index 42b3fbc..e730358 100644
--- a/two.txt
+++ b/two.txt
@@ -1,2 +1,6 @@
this is two
-
+llg
+sss
+aaa
+bbb
+wef
[llg@localhost llg-test-git]$

 

 

開始使用版本回退的前提

版本回退的意思就是回退到某一次commit那裏,這優勢相似與打通關遊戲,你能夠在任意經過的關卡中來往穿梭

git log

首先,咱們須要使用git log 命令來找出咱們以前的commit信息。從下圖能夠看到提交順序是按照最新日期排序的,最新的在最頂部,commit 後面的就是commit ID 了,後面的版本回退都靠它

 

[llg@localhost llg-test-git]$ git log
commit 3956cc36e1017c14e79d9de0944bb9baa6d2ff51
Author: llg <903857227@qq.com>
Date: Fri Sep 14 20:35:26 2018 +0800

測試兩個文件提交留一個文件不提交

commit 44449dc5261b8a66bac14ce302519f26895d0163 
Author: llg <903857227@qq.com>
Date: Fri Sep 14 20:11:22 2018 +0800
 
 
此次測試一次提交三個文件
 
 
commit abde635c93434ac4172caa4e0c6383e9dfc3d522
Author: llg <903857227@qq.com>
Date: Fri Sep 14 20:07:31 2018 +0800
 
 
git練習測試
 
[llg@localhost llg-test-git]$

 

若是嫌輸出信息太多,看得眼花繚亂的,能夠試試加上 --pretty=oneline參數

 

 

[llg@localhost llg-test-git]$ git log --pretty=oneline
3956cc36e1017c14e79d9de0944bb9baa6d2ff51 測試兩個文件提交留一個文件不提交 
44449dc5261b8a66bac14ce302519f26895d0163 此次測試一次提交三個文件 
abde635c93434ac4172caa4e0c6383e9dfc3d522 git練習測試 
[llg@localhost llg-test-git]$

 

 

開始使用版本回退

首先,Git必須知道當前版本是哪一個版本,在Git中,用HEAD表示當前版本,也就是最新的提交3956cc...(注意個人提交ID和你的確定不同),上一個版本就是HEAD^,上上一個版本就是HEAD^^,固然往上100個版本寫100個^比較容易數不過來,因此寫成HEAD~100

git reset

咱們要把當前版本<測試兩個文件提交留一個文件不提交>回退到上一個版本<此次測試一次提交三個文件>,就能夠使用git reset命令:

從下圖咱們能夠分析出,其實HEAD表明的是頭指針,畢竟這個git使用c語言寫的,咱們對C應該也是不陌生的,因此這是一個雙向鏈表,能夠向前也能夠向後,只要咱們知道commit ID。

 

[llg@localhost llg-test-git]$ git reset --hard HEAD
HEAD 如今位於 3956cc3 測試兩個文件提交留一個文件不提交
[llg@localhost llg-test-git]$ git reset --hard HEAD^
HEAD 如今位於 44449dc 此次測試一次提交三個文件
[llg@localhost llg-test-git]$ git reset --hard HEAD^
HEAD 如今位於 abde635 git練習測試
[llg@localhost llg-test-git]$
 

 

git-headgit-head-move

 

當咱們跳的比較遠的時候,也能夠直接指定commit ID 來跳轉 

 

[llg@localhost llg-test-git]$ git reset --hard 3956cc3
HEAD 如今位於 3956cc3 測試兩個文件提交留一個文件不提交
[llg@localhost llg-test-git]$

 

當咱們想要回到以前最新的版本的時候,咱們會想到用git log,可是很不幸咱們發現以前的版本信息都沒有了。因此咱們還有一個命令用來找回以前的commit ID ,就是git reflog命令了。

 

[llg@localhost llg-test-git]$ git log
commit abde635c93434ac4172caa4e0c6383e9dfc3d522
Author: llg <903857227@qq.com>
Date: Fri Sep 14 20:07:31 2018 +0800
git練習測試
[llg@localhost llg-test-git]$

 

 

 

 

git reflog

能夠拿到全部的操做記錄

從下面咱們能夠找到帶有commit字樣的就是咱們以前建立的版本,可是隻提供了ID的七爲數,可是不要緊,git會自動識別出來

 

 
[llg@localhost llg-test-git]$ git reflog
abde635 HEAD@{0}: reset: moving to HEAD^
44449dc HEAD@{1}: reset: moving to HEAD^
3956cc3 HEAD@{2}: commit: 測試兩個文件提交留一個文件不提交
44449dc HEAD@{3}: commit: 此次測試一次提交三個文件
abde635 HEAD@{4}: commit (initial): git練習測試
[llg@localhost llg-test-git]$ git reset --hard 3956cc3
HEAD 如今位於 3956cc3 測試兩個文件提交留一個文件不提交
[llg@localhost llg-test-git]$

 

 

 

 

 

7.git的工做區和暫存區

首先是官圖解釋,從下圖能夠看出若是咱們想直接提交文件到master分支上,那麼直接使用 git commit -a便可

接着再看看其他大佬繪製的圖

版本庫(Repository)

工做區有一個隱藏目錄.git,這個不算工做區,而是Git的版本庫。

Git的版本庫裏存了不少東西,其中最重要的就是稱爲stage(或者叫index)的暫存區,還有Git爲咱們自動建立的第一個分支master,以及指向master的一個指針叫HEAD

git-repo

 

假如咱們在commit以後沒有任何操做,那麼咱們暫存區就是空的

git-stage-after-commit

當咱們添加了文件或者修改了文件,而且使用了add命令那麼暫存區stage就又有了文件

git-stage

 

當咱們使用commit提交以後,那麼早存區又變成了空

git-stage-after-commit

 

關於git diff 與暫存區的關係

  • git diff 比較的是工做區文件與暫存區文件的區別(上次git add 的內容)
  • git diff --cached 比較的是暫存區的文件與倉庫分支裏(上次git commit 後的內容)的區別

8.Git如何撤回修改的操做

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

首先修改工做區的文件,不執行add操做

檢查git狀態,發現提示使用git checkout -- file 命令撤回操做 ,執行以後發現已經成功撤回

 
[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 還沒有暫存以備提交的變動:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工做區的改動)
#
# 修改: one.txt
#
修改還沒有加入提交(使用 "git add" 和/或 "git commit -a")
[llg@localhost llg-test-git]$
[llg@localhost llg-test-git]$ git checkout -- one.txt
[llg@localhost llg-test-git]$

 

 

 

 

 

 

 

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

首先修改文件而且經過add放到暫存區 

 

[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 要提交的變動:
# (使用 "git reset HEAD <file>..." 撤出暫存區)
#
# 修改: one.txt
#
[llg@localhost llg-test-git]$

 

 

 

 

根據提示使用git reset HEAD <file> 撤出暫存區,執行成功 

 

 
[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 要提交的變動:
# (使用 "git reset HEAD <file>..." 撤出暫存區)
#
# 修改: one.txt
#
[llg@localhost llg-test-git]$ git reset HEAD one.txt
重置後撤出暫存區的變動:
M one.txt
[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 還沒有暫存以備提交的變動:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工做區的改動)
#
# 修改: one.txt
#
修改還沒有加入提交(使用 "git add" 和/或 "git commit -a")
[llg@localhost llg-test-git]$

 

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

9.Git如何刪除文件

此處的刪除文件是指當一個文件提交到版本庫後,也就是master分支。若是在工做區刪除這個文件,那麼將會使工做區文件與版本庫文件不對應,在這裏須要分清兩種使用狀況。

工做區刪除了文件而且確實要從版本庫中也刪除該文件

那麼就應該使用git rm 命令

 
[llg@localhost llg-test-git]$ rm delete.txt
[llg@localhost llg-test-git]$ git rm -- delete.txt
rm 'delete.txt'
[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 要提交的變動:
# (使用 "git reset HEAD <file>..." 撤出暫存區)
#
# 刪除: delete.txt
#
[llg@localhost llg-test-git]$

 

 

 

固然咱們經過git status 命令能夠看出這一操做只是保留在了暫存區,因此咱們還須要commit命令提交這一更改,其實能夠把這一命令想象成修改的命令

 

[llg@localhost llg-test-git]$ git commit -m "正式從版本庫中刪除該文件"
[master ad66495] 正式從版本庫中刪除該文件
1 file changed, 1 deletion(-)
delete mode 100644 delete.txt
[llg@localhost llg-test-git]$ git status
# 位於分支 master
無文件要提交,乾淨的工做區
[llg@localhost llg-test-git]$

 

 

工做區誤刪了某些文件,須要從版本庫中從新弄回來

根據git status 提示的方法,咱們能夠從版本庫中checkout中某些文件

[llg@localhost llg-test-git]$ git checkout -- delete.txt

另一個一個簡單的方法就是從新把版本庫更新回來,可是這個前提是你得保證只有這麼一個刪除文件,若是有其餘文件修改了而且未放到暫存區,那麼就很是可怕了。

 

[llg@localhost llg-test-git]$ git reset --hard HEAD^
HEAD 如今位於 eda17f9 這是一個將要被刪除的文件
[llg@localhost llg-test-git]$ ls -al 
總用量 24 
drwxrwsr-x 3 llg llg 98 9月 15 19:56 .
drwsrwsrwt. 13 llg llg 4096 9月 14 19:44 .. 
-rw-rw-r-- 1 llg llg 34 9月 15 19:56 delete.txt 
drwxrwsr-x 8 llg llg 183 9月 15 19:56 .git 
-rw-rw-r-- 1 llg llg 57 9月 14 21:06 llg.txt 
-rw-rw-r-- 1 llg llg 16 9月 14 22:05 one.txt 
-rw-rw-r-- 1 llg llg 14 9月 14 21:06 three.txt
-rw-rw-r-- 1 llg llg 13 9月 14 21:06 two.txt 
[llg@localhost llg-test-git]$

 

10.初識遠程倉庫

既然git的其中一個目的就是爲了協做開發,那麼遠程倉庫就是爲了這一個目的的。經過將倉庫放在一個遠程的服務器上,讓全部人均可以訪問這個倉庫,能夠一塊兒更新和提交。

實際狀況每每是這樣,找一臺電腦充當服務器的角色,天天24小時開機,其餘每一個人都從這個「服務器」倉庫克隆一份到本身的電腦上,而且各自把各自的提交推送到服務器倉庫裏,也從服務器倉庫中拉取別人的提交。

徹底能夠本身搭建一臺運行Git的服務器,不過現階段,爲了學Git先搭個服務器絕對是小題大做。好在這個世界上有個叫GitHub的神奇的網站,從名字就能夠看出,這個網站就是提供Git倉庫託管服務的,因此,只要註冊一個GitHub帳號,就能夠免費得到Git遠程倉庫。

在繼續閱讀後續內容前,請自行註冊GitHub帳號。因爲你的本地Git倉庫和GitHub倉庫之間的傳輸是經過SSH加密的,因此,須要一點設置:

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

[llg@localhost ~]$ ssh-keygen -t rsa -C "903857227@qq.com"

若是一切順利的話,能夠在用戶主目錄裏找到.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文件的內容:

[llg@localhost ~]$ cd .ssh/

 

[llg@localhost .ssh]$ ls -al 
總用量 16 
drwsrwsrwt. 2 llg llg 57 9月 15 20:28 .
drwsrwsrwt. 39 llg llg 4096 9月 15 19:59 ..
-rw------- 1 llg llg 1679 9月 15 20:29 id_rsa 
-rw-r--r-- 1 llg llg 398 9月 15 20:29 id_rsa.pub 
-rw-r--r-- 1 llg llg 175 4月 27 20:05 known_hosts 
[llg@localhost .ssh]$ vi id_rsa.pub

 

爲何GitHub須要SSH Key呢?由於GitHub須要識別出你推送的提交確實是你推送的,而不是別人冒充的,而Git支持SSH協議,因此,GitHub只要知道了你的公鑰,就能夠確認只有你本身才能推送。

固然,GitHub容許你添加多個Key。假定你有若干電腦,你一下子在公司提交,一下子在家裏提交,只要把每臺電腦的Key都添加到GitHub,就能夠在每臺電腦上往GitHub推送了。

最後友情提示,在GitHub上免費託管的Git倉庫,任何人均可以看到喔(但只有你本身才能改)。因此,不要把敏感信息放進去。

若是你不想讓別人看到Git庫,有兩個辦法,一個是交點保護費,讓GitHub把公開的倉庫變成私有的,這樣別人就看不見了(不可讀更不可寫)。另外一個辦法是本身動手,搭一個Git服務器,由於是你本身的Git服務器,因此別人也是看不見的。這個方法咱們後面會講到的,至關簡單,公司內部開發必備。

確保你擁有一個GitHub帳號後,咱們就即將開始遠程倉庫的學習。

11.從github上添加一個遠程倉庫

首先咱們github上登錄本身賬號後建立一個倉庫

接着咱們能夠看到建立完倉庫後給咱們的提示

從本地的已有倉庫直接推送到遠程倉庫上

根據上邊提示輸入命令

 

[llg@localhost llg-test-git]$ git remote add origin https://github.com/llgeill/llg-centos-git--test.git
[llg@localhost llg-test-git]$ git push -u origin master 
Username for 'https://github.com': 903857227@qq.com
Password for 'https://903857227@qq.com@github.com': 
Counting objects: 12, done.
Delta compression using up to 4 threads. 
Compressing objects: 100% (6/6), done.
Writing objects: 100% (12/12), 1.01 KiB | 0 bytes/s, done. 
Total 12 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'master' on GitHub by visiting:
remote: https://github.com/llgeill/llg-centos-git--test/pull/new/master
remote:
To https://github.com/llgeill/llg-centos-git--test.git
* [new branch] master -> master
分支 master 設置爲跟蹤來自 origin 的遠程分支 master。

 

 

發現文件已經推送完畢 

 

Git遠程倉庫的優勢 

  • 要關聯一個遠程庫,使用命令git remote add origin git@server-name:path/repo-name.git
  • 關聯後,使用命令git push -u origin master第一次推送master分支的全部內容;
  • 此後,每次本地提交後,只要有必要,就能夠使用命令git push origin master推送最新修改;
  • 分佈式版本系統的最大好處之一是在本地工做徹底不須要考慮遠程庫的存在,也就是有沒有聯網均可以正常工做,而SVN在沒有聯網的時候是拒絕幹活的!當有網絡的時候,再把本地提交推送一下就完成了同步,真是太方便了!

12.從遠程倉庫克隆一個已有倉庫

首先咱們從github上建立一個遠程倉庫

首先在github上找到能夠克隆的地址

下一步是用命令git clone克隆一個本地庫,咱們能夠發現項目已經克隆下來

 

 
[llg@localhost 桌面]$ git clone git@github.com:llgeill/llg-centos-git-test-1.git
正克隆到 'llg-centos-git-test-1'...
The authenticity of host 'github.com (192.30.253.112)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
RSA key fingerprint is MD5:16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.253.112' (RSA) to the list of known hosts. 
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
接收對象中: 100% (3/3), done.
[llg@localhost 桌面]$ ls -al
總用量 40
drwsrwsrwt. 14 llg llg 4096 9月 15 21:10 .
drwsrwsrwt. 39 llg llg 4096 9月 15 20:39 ..
drwxr-xr-x 11 llg llg 196 9月 2 17:11 1-Brixton版教程示例
drwxr-xr-x 34 llg llg 4096 9月 2 15:57 2-Dalston版教程示例
-rw-r--r-- 1 root root 12288 4月 23 20:58 .android-studio.desktop.swp
drwxrwxr-x 10 llg llg 302 9月 13 22:23 dist
-rwsrwsrwt 1 llg llg 1968 5月 2 08:27 .keystore
drwxrwsr-x 5 llg llg 118 9月 14 08:38 llg
drwxrwsr-x 3 llg llg 35 9月 15 21:10 llg-centos-git-test-1
drwxrwsr-x 3 llg llg 80 9月 15 20:01 llg-test-git
drwxrwsr-x 5 llg llg 131 9月 7 20:13 llg-user-gateway
drwxrwsr-x 6 llg llg 151 9月 14 08:51 llg-web-springboot-class
drwxr-xr-x 39 llg llg 4096 9月 2 19:41 SpringCloudBook-master
drwx------ 14 llg llg 315 9月 3 07:46 spring-cloud-llg
drwxrwsr-x 5 llg llg 61 9月 5 18:53 untitled
drwxr-xr-x 12 llg llg 4096 6月 29 2016 計算機組成原理201407

 

測試從本地倉庫推送回遠程倉庫

[llg@localhost llg-centos-git-test-1]$ vi llg.txt
[llg@localhost llg-centos-git-test-1]$ git add llg.txt
[llg@localhost llg-centos-git-test-1]$ git commit -m "測試"
[master 4bdb6c4] 測試
1 file changed, 1 insertion(+)
create mode 100644 llg.txt
[llg@localhost llg-centos-git-test-1]$ git status
# 位於分支 master
# 您的分支領先 'origin/master'1 個提交。
# (使用 "git push" 來發布您的本地提交)
#
無文件要提交,乾淨的工做區
[llg@localhost llg-centos-git-test-1]$ git push -u origin masterWarning: Permanently added the RSA host key for IP address '192.30.253.113' to the list of known hosts.
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 274 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:llgeill/llg-centos-git-test-1.git
07b4bcc..4bdb6c4 master -> master
分支 master 設置爲跟蹤來自 origin 的遠程分支 master。

 

13.Git的分支管理

分支就是科幻電影裏面的平行宇宙,當你正在電腦前努力學習Git的時候,另外一個你正在另外一個平行宇宙裏努力學習SVN。

若是兩個平行宇宙互不干擾,那對如今的你也沒啥影響。不過,在某個時間點,兩個平行宇宙合併了,結果,你既學會了Git又學會了SVN!

learn-branches

分支在實際中有什麼用呢?假設你準備開發一個新功能,可是須要兩週才能完成,第一週你寫了50%的代碼,若是馬上提交,因爲代碼還沒寫完,不完整的代碼庫會致使別人不能幹活了。若是等代碼所有寫完再一次提交,又存在丟失天天進度的巨大風險。

如今有了分支,就不用怕了。你建立了一個屬於你本身的分支,別人看不到,還繼續在原來的分支上正常工做,而你在本身的分支上幹活,想提交就提交,直到開發完畢後,再一次性合併到原來的分支上,這樣,既安全,又不影響別人工做。

其餘版本控制系統如SVN等都有分支管理,可是用過以後你會發現,這些版本控制系統建立和切換分支比蝸牛還慢,簡直讓人沒法忍受,結果分支功能成了擺設,你們都不去用。

但Git的分支是不同凡響的,不管建立、切換和刪除分支,Git在1秒鐘以內就能完成!不管你的版本庫是1個文件仍是1萬個文件。

14.建立與合併分支管理

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

原理解析

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能肯定當前分支,以及當前分支的提交點:

git-br-initial

 

建立新分支 

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

git-br-create

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

 

[llg@localhost llg-test-git]$ git checkout -b dev
切換到一個新分支 'dev'
[llg@localhost llg-test-git]$

 

上面的命令等價與下面兩條命令的結合

 

[llg@localhost llg-test-git]$ git branch dev
[llg@localhost llg-test-git]$ git checkout dev
切換到分支 'dev'

 

咱們能夠使用git branch 查看當前分支的狀況 

 

[llg@localhost llg-test-git]$ git branch
* dev
master

 

 你看,Git建立一個分支很快,由於除了增長一個dev指針,改改HEAD的指向,工做區的文件都沒有任何變化!

新分支上提交版本庫

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

git-br-dev-fd

 

 
[llg@localhost llg-test-git]$ vi one.txt
[llg@localhost llg-test-git]$ git add one.txt
[llg@localhost llg-test-git]$ git commit -m "在分支上提交版本信息"
[dev 8c8117b] 在分支上提交版本信息
1 file changed, 2 insertions(+)
[llg@localhost llg-test-git]$ git status
# 位於分支 dev
無文件要提交,乾淨的工做區
[llg@localhost llg-test-git]$

 

當咱們從新切換到master分支時候發現one.txt根本沒有變化,由於咱們commit的是dev分支

 

[llg@localhost llg-test-git]$ git checkout master
切換到分支 'master'
[llg@localhost llg-test-git]$ vi one.txt
[llg@localhost llg-test-git]$ git checkout dev
切換到分支 'dev'
[llg@localhost llg-test-git]$ vi one.txt

 

合併分支

假如咱們在dev上的工做完成了,就能夠把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併 。注意下面的Fast-forwar 信息,Git告訴咱們此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。固然,也不是每次合併都能Fast-forward,咱們後面會講其餘方式的合併。

git-br-ff-merge

 

 
[llg@localhost llg-test-git]$ git checkout master
切換到分支 'master'
[llg@localhost llg-test-git]$ git merge dev
更新 3956cc3..8c8117b
Fast-forward
one.txt | 2 ++
1 file changed, 2 insertions(+)

 

刪除分支

合併完分支後,甚至能夠刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,咱們就剩下了一條master分支

git-br-rm

 

 
[llg@localhost llg-test-git]$ git branch
dev
* master
[llg@localhost llg-test-git]$ vi one.txt
[llg@localhost llg-test-git]$ git branch -d dev
已刪除分支 dev(曾爲 8c8117b)。
[llg@localhost llg-test-git]$ git branch
* master

 

 小結

由於建立、合併和刪除分支很是快,因此Git鼓勵你使用分支完成某個任務,合併後再刪掉分支,這和直接在master分支上工做效果是同樣的,但過程更安全。

  • 查看分支:git branch
  • 建立分支:git branch <name>
  • 切換分支:git checkout <name>
  • 建立+切換分支:git checkout -b <name>
  • 合併某分支到當前分支:git merge <name>
  • 刪除分支:git branch -d <name>

 

15.解決分支的衝突問題

首先建立一個分支而且提交了一次版本倉庫,主分支也提交了一次版本倉庫,如圖所示

git-br-feature1

這種狀況下,Git沒法執行「快速合併」,只能試圖把各自的修改合併起來,但這種合併就可能會有衝突

 

[llg@localhost llg-test-git]$ git merge fantasy
自動合併 dele
衝突(內容):合併衝突於 dele
自動合併失敗,修正衝忽然後提交修正的結果。

 

果真衝突了!Git告訴咱們,readme.txt文件存在衝突,必須手動解決衝突後再提交。git status也能夠告訴咱們衝突的文件

 

[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 您的分支領先 'origin/master'7 個提交。
# (使用 "git push" 來發布您的本地提交)
#
# 您有還沒有合併的路徑。
# (解決衝突並運行 "git commit")
#
# 未合併的路徑:
# (使用 "git add <file>..." 標記解決方案)
#
# 雙方修改: dele
#
修改還沒有加入提交(使用 "git add" 和/或 "git commit -a"

 

手工修改衝突 

咱們能夠直接查看dele的內容,Git用<<<<<<<=======>>>>>>>標記出不一樣分支的內容

咱們手動修改衝突位置,以後提交文件到暫存區而且commit

 

[llg@localhost llg-test-git]$ git add dele
[llg@localhost llg-test-git]$ git commit -m "cscs"
[master b1dd3cc] cscs

 

如今,master分支和feature1分支變成了下圖所示

git-br-conflict-merged

查看分支合併狀況 

用帶參數的git log --graph 也能夠看到分支的合併狀況

 

* commit b1dd3cc1e90369e4fe2fc93f5a75b46a8918973f 
|\ Merge: 478f0bc 43149ab 
| | Author: llg <903857227@qq.com> 
| | Date: Sun Sep 16 15:10:03 2018 +0800 
| | 
| | cscs 
| | 
| * commit 43149abf7f5724e74f64b394521778ceaded39b1 
| | Author: llg <903857227@qq.com> 
| | Date: Sun Sep 16 15:01:24 2018 +0800 
| | 
| | ccc 
| | 
* | commit 478f0bc2b144ac6fce457e05c9e596e314bd1f11 
| | Author: llg <903857227@qq.com> 
| | Date: Sun Sep 16 15:02:12 2018 +0800 
| | 
| | ss 
| | 
* | commit a22d668c065ad42c38232850fad8082250aa63a2 
|\ \ Merge: 57e8b85 1575642 
| |/ Author: llg <903857227@qq.com> 
| | Date: Sun Sep 16 14:55:13 2018 +0800 
| |
| | Merge branch 'fantasy' 
| | 
| | ceshi 
| |
 
 

 

 

16.分支管理策略

一般,合併分支時,若是可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。

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

下面咱們實戰一下--no-ff(禁用Fast forward)方式的git merge,一些前提條件略過  

 

[llg@localhost llg-test-git]$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
dele | 1 +
1 file changed, 1 insertion(+)
合併分支時,加上--no-ff參數就能夠用普通模式合併,合併後的歷史有分支,能看出來曾經作過合併,而fast forward合併就看不出來曾經作過合併。
[llg@localhost llg-test-git]$ git log --graph --pretty=oneline --abbrev-commit
* 3a5456c merge with no-ff
|\
| * b68ba37 add merge
|/
* 0ed0fe3 測試
* b1dd3cc cscs
|\
| * 43149ab ccc
* | 478f0bc ss
* | a22d668 Merge branch 'fantasy'
|\ \
| |/
| * 1575642 xx
* | 57e8b85 Merge branch 'fantasy'
|\ \
| |/
| * 87bc5d7 ss
* | 709521d 版本衝突
* | 8c8117b 在分支上提交版本信息
|/
* 3956cc3 測試兩個文件提交留一個文件不提交
* 44449dc 此次測試一次提交三個文件
* abde635 git練習測試

 

咱們來看看不適用no-ff下的策略,發現會直接合並,分支信息不能再找到

 

[llg@localhost llg-test-git]$ git log --graph --pretty=oneline --abbrev-commit
* 8699b49 dele
* 3a5456c merge with no-ff
|\
| * b68ba37 add merge
|/
* 0ed0fe3 測試
* b1dd3cc cscs
|\
| * 43149ab ccc
* | 478f0bc ss
* | a22d668 Merge branch 'fantasy'
|\ \
| |/
| * 1575642 xx
* | 57e8b85 Merge branch 'fantasy'
|\ \
| |/
| * 87bc5d7 ss
* | 709521d 版本衝突
* | 8c8117b 在分支上提交版本信息
|/
* 3956cc3 測試兩個文件提交留一個文件不提交
* 44449dc 此次測試一次提交三個文件
* abde635 git練習測試
 
能夠看到,不使用 Fast forward模式,merge後就像這樣。

 

git-no-ff-mode

分支策略

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

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

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

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

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

git-br-policy

 

17.解決Bug的臨時分支 

軟件開發中,bug就像屢見不鮮同樣。有了bug就須要修復,在Git中,因爲分支是如此的強大,因此,每一個bug均可以經過一個新的臨時分支來修復,修復後,合併分支,而後將臨時分支刪除。

當你接到一個修復一個代號101的bug的任務時,很天然地,你想建立一個分支issue-101來修復它,可是,等等,當前正在dev上進行的工做尚未提交:

 

 
[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 您的分支領先 'origin/master'15 個提交。
# (使用 "git push" 來發布您的本地提交)
#
# 還沒有暫存以備提交的變動:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工做區的改動)
#
# 修改: dele
#
修改還沒有加入提交(使用 "git add" 和/或 "git commit -a"

 

 

並非你不想提交,而是工做只進行到一半,還無法提交,預計完成還需1天時間。可是,必須在兩個小時內修復該bug,怎麼辦?

封鎖現場

幸虧,Git還提供了一個stash功能,能夠把當前工做現場「儲藏」起來,等之後恢復現場後繼續工做,再經過git status 查看發現工做區已經乾淨。 

 

[llg@localhost llg-test-git]$ git stash
Saved working directory and index state WIP on master: 7dec792 ss
HEAD 如今位於 7dec792 ss
[llg@localhost llg-test-git]$ git status
# 位於分支 master
# 您的分支領先 'origin/master'15 個提交。
# (使用 "git push" 來發布您的本地提交)
#
無文件要提交,乾淨的工做區
首先肯定要在哪一個分支上修復bug,假定須要在 master分支上修復,就從 master建立臨時分支

 

 

[llg@localhost llg-test-git]$ git checkout -b issue-101
切換到一個新分支 'issue-101'

 

如今修復bug,咱們經過修改文件模擬這一個過程

 

[llg@localhost llg-test-git]$ vi delete.txt
[llg@localhost llg-test-git]$ git add delete.txt
[llg@localhost llg-test-git]$ git commit -m "ss"
[issue-101 e0b9de9] ss
1 file changed, 1 insertion(+)

 

修復完成後,切換到master分支,並完成合並,最後刪除issue-101分支

 

[llg@localhost llg-test-git]$ git checkout master
切換到分支 'master'
您的分支領先 'origin/master'15 個提交。
(使用 "git push" 來發布您的本地提交)
[llg@localhost llg-test-git]$ git merge --no-ff -m "merge bug fix 101" issue-101
Merge made by the 'recursive' strategy.
delete.txt | 1 +
1 file changed, 1 insertion(+)
 

 

還原現場 

太棒了,原計劃兩個小時的bug修復只花了5分鐘!

如今,是時候接着回到dev分支幹活了,切換到dev分支而後用git stash list命令看看

 

[llg@localhost llg-test-git]$ git stash list
stash@{0}: WIP on master: 7dec792 ss

 

工做現場還在,Git把stash內容存在某個地方了,可是須要恢復一下,有兩個辦法:

一是用git stash apply恢復,可是恢復後,stash內容並不刪除,你須要用git stash drop來刪除;

另外一種方式是用git stash pop,恢復的同時把stash內容也刪了: 

 

[llg@localhost llg-test-git]$ git stash pop
# 位於分支 master
# 您的分支領先 'origin/master'17 個提交。
# (使用 "git push" 來發布您的本地提交)
#
# 還沒有暫存以備提交的變動:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工做區的改動)
#
# 修改: dele
#
修改還沒有加入提交(使用 "git add" 和/或 "git commit -a")
丟棄了 refs/stash@{0} (fa2bbbe411ba20c94501e912ec120fa944c06b92)
再用 git stash list查看,就看不到任何stash內容了 

 

 

[llg@localhost llg-test-git]$ git stash list
[llg@localhost llg-test-git]$

 

小結

  • 修復bug時,咱們會經過建立新的bug分支進行修復,而後合併,最後刪除;
  • 當手頭工做沒有完成時,先把工做現場git stash一下,而後去修復bug,修復後,再git stash pop,回到工做現場

 

18.強制刪除分支

當須要開發一個新功能的時候,最好建立一個新的分支進行代碼編輯,可是由於一些狀況不須要這個分支了,可是這個分支歷來沒有合併過,因此要使用 git branch -D 的方式強制刪除

 

[llg@localhost llg-test-git]$ vi feichuan.txt.swp
[llg@localhost llg-test-git]$ git add feichuan.txt.swp
[llg@localhost llg-test-git]$ git commit -m "ss"
[feature-vulcan 4cd8736] ss
1 file changed, 1 insertion(+)
create mode 100644 feichuan.txt.swp
[llg@localhost llg-test-git]$ git checkout master
M dele
切換到分支 'master'
您的分支領先 'origin/master'17 個提交。
(使用 "git push" 來發布您的本地提交)
[llg@localhost llg-test-git]$ git branch -D feature-vulcan
已刪除分支 feature-vulcan(曾爲 4cd8736)。

 

19.rebease整理分叉歷史

在上一節咱們看到了,多人在同一個分支上協做時,很容易出現衝突。即便沒有衝突,後push的童鞋不得不先pull,在本地合併,而後才能push成功。

每次合併再push後,分支變成了這樣

總之看上去很亂,有強迫症的童鞋會問:爲何Git的提交歷史不能是一條幹淨的直線?

實際上是能夠作到的!

Git有一種稱爲rebase的操做,有人把它翻譯成「變基」。

rebase

先不要隨意展開想象。咱們仍是從實際問題出發,看看怎麼把分叉的提交變成直線。

在和遠程分支同步後,咱們對hello.py這個文件作了兩次提交。用git log命令看看:

 

 
$ git log --graph --pretty=oneline --abbrev-commit
* 582d922 (HEAD -> master) add author
* 8875536 add comment
* d1be385 (origin/master) init hello 
* e5e69f1 Merge branch 'dev' 
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
...

 

注意到Git用(HEAD -> master)(origin/master)標識出當前分支的HEAD和遠程origin的位置分別是582d922 add authord1be385 init hello,本地分支比遠程分支快兩個提交。

如今咱們嘗試推送本地分支:

 

$ git push origin master
To github.com:michaelliao/learngit.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

 

很不幸,失敗了,這說明有人先於咱們推送了遠程分支。按照經驗,先pull一下: 

 

$ git pull
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
d1be385..f005ed4 master -> origin/master
* [new tag] v1.0 -> v1.0
Auto-merging hello.py
Merge made by the 'recursive' strategy.
hello.py | 1 +
1 file changed, 1 insertion(+)

 

再用git status看看狀態:

 

 
$ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
(use "git push" to publish your local commits)
 
nothing to commit, working tree clean

 

加上剛纔合併的提交,如今咱們本地分支比遠程分支超前3個提交。

git log看看:

 

$ git log --graph --pretty=oneline --abbrev-commit
* e0ea545 (HEAD -> master) Merge branch 'master' of github.com:michaelliao/learngit
|\
| * f005ed4 (origin/master) set exit=1
* | 582d922 add author
* | 8875536 add comment
|/
* d1be385 init hello
...

 

對強迫症童鞋來講,如今事情有點不對頭,提交歷史分叉了。若是如今把本地分支push到遠程,有沒有問題?

有!

什麼問題?

很差看!

有沒有解決方法?

有!

這個時候,rebase就派上了用場。咱們輸入命令git rebase試試:

 

 
$ git rebase
First, rewinding head to replay your work on top of it...
Applying: add comment
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge..
Auto-merging hello.py
Applying: add author
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py

 

 

 

 

輸出了一大堆操做,究竟是啥效果?再用git log看看:

 

 

 

$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello

 

本來分叉的提交如今變成一條直線了!這種神奇的操做是怎麼實現的?其實原理很是簡單。咱們注意觀察,發現Git把咱們本地的提交「挪動」了位置,放到了f005ed4 (origin/master) set exit=1以後,這樣,整個提交歷史就成了一條直線。rebase操做先後,最終的提交內容是一致的,可是,咱們本地的commit修改內容已經變化了,它們的修改再也不基於d1be385 init hello,而是基於f005ed4 (origin/master) set exit=1,但最後的提交7e61ed4內容是一致的。

這就是rebase操做的特色:把分叉的提交歷史「整理」成一條直線,看上去更直觀。缺點是本地的分叉提交已經被修改過了。

最後,經過push操做把本地分支推送到遠程:

 

 
Mac:~/learngit michael$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To github.com:michaelliao/learngit.git
f005ed4..7e61ed4 master -> master

 

再用git log看看效果:

$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master, origin/master) add author
* 3611cfe add comment
* f005ed4 set exit=1
* d1be385 init hello

 

 

 

遠程分支的提交歷史也是一條直線。

 

總結 

  • rebase操做能夠把本地未push的分叉提交歷史整理成直線;

  • rebase的目的是使得咱們在查看歷史提交的變化時更容易,由於分叉的提交須要三方對比。

20.什麼是標籤管理

發佈一個版本時,咱們一般先在版本庫中打一個標籤(tag),這樣,就惟一肯定了打標籤時刻的版本。未來不管何時,取某個標籤的版本,就是把那個打標籤的時刻的歷史版本取出來。因此,標籤也是版本庫的一個快照。

Git的標籤雖然是版本庫的快照,但其實它就是指向某個commit的指針(跟分支很像對不對?可是分支能夠移動,標籤不能移動),因此,建立和刪除標籤都是瞬間完成的。

Git有commit,爲何還要引入tag?

「請把上週一的那個版本打包發佈,commit號是6a5819e...」

「一串亂七八糟的數字很差找!」

若是換一個辦法:

「請把上週一的那個版本打包發佈,版本號是v1.2」

「好的,按照tag v1.2查找commit就行!」

因此,tag就是一個讓人容易記住的有意義的名字,它跟某個commit綁在一塊兒。

21.建立Git倉庫版本標籤

在Git中打標籤很是簡單,首先,切換到須要打標籤的分支上

 

 
[llg@localhost llg-test-git]$ git branch
dev
issue-101
* master
[llg@localhost llg-test-git]$ git checkout dev
切換到分支 'dev'

 

建立當前版本標籤

而後,敲命令git tag <name>就能夠打一個新標籤

[llg@localhost llg-test-git]$ git tag v1.0

建立其餘版本標籤

默認標籤是打在最新提交的commit上的。有時候,若是忘了打標籤,好比,如今已是週五了,但應該在週一打的標籤沒有打,怎麼辦?

方法是找到歷史提交的commit id,而後打上就能夠了:

 

[llg@localhost llg-test-git]$ git log --pretty=oneline --abbrev-commit
8699b49 dele
3a5456c merge with no-ff
b68ba37 add merge
0ed0fe3 測試
b1dd3cc cscs
478f0bc ss
43149ab ccc
a22d668 Merge branch 'fantasy'
1575642 xx
57e8b85 Merge branch 'fantasy'
709521d 版本衝突
87bc5d7 ss
8c8117b 在分支上提交版本信息
3956cc3 測試兩個文件提交留一個文件不提交
44449dc 此次測試一次提交三個文件
abde635 git練習測試
[llg@localhost llg-test-git]$ git tag
v1.0
[llg@localhost llg-test-git]$ git tag v0.9 3a5456c
[llg@localhost llg-test-git]$ git tag
v0.9
v1.0

 

查看全部標籤 

 

[llg@localhost llg-test-git]$ git tag
v0.8
v0.9
v1.0

 

查看標籤詳細信息

注意,標籤不是按時間順序列出,而是按字母排序的。能夠用git show <tagname>查看標籤信息

[llg@localhost llg-test-git]$ git show v0.9
commit 3a5456c07d50d99437d01fbf538a41a4556d7504
Merge: 0ed0fe3 b68ba37
Author: llg <903857227@qq.com>
Date: Sun Sep 16 16:04:56 2018 +0800

merge with no-ff
 

建立帶說明文字的標籤

還能夠建立帶有說明的標籤,用-a指定標籤名,-m指定說明文字

 

[llg@localhost llg-test-git]$ git tag -a v0.8 -m "version 0.8 released" b68ba37
[llg@localhost llg-test-git]$ git show v0.8
tag v0.8
Tagger: llg <903857227@qq.com>
Date: Mon Sep 17 09:31:27 2018 +0800
 
 
version 0.8 released
 
 
commit b68ba371b04d5b7b6305454c160d7ef88178ea2d
Author: llg <903857227@qq.com>
Date: Sun Sep 16 16:04:19 2018 +0800
 
 
add merge
 
 
diff --git a/dele b/dele
index 20c0828..a36d773 100644
--- a/dele
+++ b/dele
@@ -10,3 +10,4 @@ sad
end
 
 
1111111111111111111111
+2222222222222222222222

 

22.操做標籤

刪除標籤

若是標籤打錯了,也能夠刪除

 

[llg@localhost llg-test-git]$ git tag -d v0.8
已刪除 tag 'v0.8'(曾爲 658e2ab)

 

推送某個標籤到遠程倉庫 

由於建立的標籤都只存儲在本地,不會自動推送到遠程。因此,打錯的標籤能夠在本地安全刪除。

若是要推送某個標籤到遠程,使用命令git push origin <tagname>

 

[llg@localhost llg-test-git]$ git push origin v1.0
Username for 'https://github.com': 903857227@qq.com
Password for 'https://903857227@qq.com@github.com':
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/llgeill/llg-centos-git--test.git
* [new tag] v1.0 -> v1.0

 

 推送全部標籤到遠程倉庫 

或者,一次性推送所有還沒有推送到遠程的本地標籤:

 

[llg@localhost llg-test-git]$ git push origin --tag
Username for 'https://github.com': 903857227@qq.com
Password for 'https://903857227@qq.com@github.com':
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/llgeill/llg-centos-git--test.git
* [new tag] v0.9 -> v0.9

 

刪除遠程標籤

首先在本地刪除標籤

 

[llg@localhost llg-test-git]$ git tag -d v0.8
已刪除 tag 'v0.9'(曾爲 3a5456c)

 

而後,從遠程刪除。刪除命令是 git push origin :refs/tags/xxx

 

[llg@localhost llg-test-git]$ git push origin :refs/tags/v0.8
Username for 'https://github.com': 903857227@qq.com
Password for 'https://903857227@qq.com@github.com':
To https://github.com/llgeill/llg-centos-git--test.git
- [deleted] v0.8

 

最後去官網github上查看tag是否被刪除,發現確實被刪除了

 

23.如何使用Github

咱們一直用GitHub做爲免費的遠程倉庫,若是是我的的開源項目,放到GitHub上是徹底沒有問題的。其實GitHub仍是一個開源協做社區,經過GitHub,既可讓別人參與你的開源項目,也能夠參與別人的開源項目。

在GitHub出現之前,開源項目開源容易,但讓廣大人民羣衆參與進來比較困難,由於要參與,就要提交代碼,而給每一個想提交代碼的羣衆都開一個帳號那是不現實的,所以,羣衆也僅限於報個bug,即便能改掉bug,也只能把diff文件用郵件發過去,很不方便。

可是在GitHub上,利用Git極其強大的克隆和分支功能,廣大人民羣衆真正能夠第一次自由參與各類開源項目了。

參與別人的開源項目 

如何參與一個開源項目呢?好比人氣極高的bootstrap項目,這是一個很是強大的CSS框架,你能夠訪問它的項目主頁https://github.com/twbs/bootstrap,點「Fork」就在本身的帳號下克隆了一個bootstrap倉庫,而後,從本身的帳號下clone:

  

 

[llg@localhost 桌面]$ git clone git@github.com:llgeill/bootstrap.git
正克隆到 'bootstrap'...
remote: Counting objects: 126027, done.
remote: Compressing objects: 100% (40/40), done.
remote: Total 126027 (delta 44), reused 45 (delta 35), pack-reused 125952
接收對象中: 100% (126027/126027), 123.12 MiB | 4.97 MiB/s, done.
處理 delta 中: 100% (83420/83420), done.

 

必定要從本身的帳號下clone倉庫,這樣你才能推送修改。若是從bootstrap的做者的倉庫地址git@github.com:twbs/bootstrap.git克隆,由於沒有權限,你將不能推送修改。

Bootstrap的官方倉庫twbs/bootstrap、你在GitHub上克隆的倉庫my/bootstrap,以及你本身克隆到本地電腦的倉庫,他們的關係就像下圖顯示的那樣:

github-repos

若是你想修復bootstrap的一個bug,或者新增一個功能,馬上就能夠開始幹活,幹完後,往本身的倉庫推送。

若是你但願bootstrap的官方庫能接受你的修改,你就能夠在GitHub上發起一個pull request。固然,對方是否接受你的pull request就不必定了。

 

23.如何使用碼雲

使用GitHub時,國內的用戶常常遇到的問題是訪問速度太慢,有時候還會出現沒法鏈接的狀況(緣由你懂的)。

若是咱們但願體驗Git飛通常的速度,能夠使用國內的Git託管服務——碼雲gitee.com)。

和GitHub相比,碼雲也提供免費的Git倉庫。此外,還集成了代碼質量檢測、項目演示等功能。對於團隊協做開發,碼雲還提供了項目管理、代碼託管、文檔管理的服務,5人如下小團隊免費。

 碼雲的免費版本也提供私有庫功能,只是有5人的成員上限。

使用碼雲和使用GitHub相似,咱們在碼雲上註冊帳號並登陸後,須要先上傳本身的SSH公鑰。選擇右上角用戶頭像 -> 菜單「修改資料」,而後選擇「SSH公鑰」,填寫一個便於識別的標題,而後把用戶主目錄下的.ssh/id_rsa.pub文件的內容粘貼進去:

 

已有本地倉庫關聯遠程倉庫 

若是咱們已經有了一個本地的git倉庫(例如,一個名爲learngit的本地庫),如何把它關聯到碼雲的遠程庫上呢?

首先,咱們在碼雲上建立一個新的項目,選擇右上角用戶頭像 -> 菜單「控制面板」,而後點擊「建立項目」:

建立遠程倉庫

關聯遠程倉庫

因爲剛纔已經關聯了github,若是用同一個tag orgin的話將會關聯失敗,因此我用了orgins 關聯碼雲

 

[llg@localhost llg-test-git]$ git remote add origin git@gitee.com:eill/llg-test-git.git
fatal: 遠程 origin 已經存在。
[llg@localhost llg-test-git]$ git push -u origin master
Username for 'https://github.com': 903857227@qq .com
Password for 'https://903857227@qq.com@github.com':
分支 master 設置爲跟蹤來自 origin 的遠程分支 master。
Everything up-to-date

這樣一來,咱們的本地庫就能夠同時與多個遠程庫互相同步:

刪除關聯

[llg@localhost llg-test-git]$ git remote rm origin
[llg@localhost llg-test-git]$ git remote -v
origins git@gitee.com:eill/centos-git-gitee-test.git (fetch)
origins git@gitee.com:eill/centos-git-gitee-test.git (push)

碼雲也一樣提供了Pull request功能,可讓其餘小夥伴參與到開源項目中來。你能夠經過Fork個人倉庫:https://gitee.com/liaoxuefeng/learngit,建立一個your-gitee-id.txt的文本文件, 寫點本身學習Git的心得,而後推送一個pull request給我,這個倉庫會在碼雲和GitHub作雙向同步。

24.自定義Git配置

安裝Git一節中,咱們已經配置了user.nameuser.email,實際上,Git還有不少可配置項。

開啓命令行顏色

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

[llg@localhost llg-test-git]$ git config --global color.ui true 

忽略特殊文件

有些時候,你必須把某些文件放到Git工做目錄中,但又不能提交它們,好比保存了數據庫密碼的配置文件啦,等等,每次git status都會顯示Untracked files ...,有強迫症的童鞋內心確定不爽。

好在Git考慮到了你們的感覺,這個問題解決起來也很簡單,在Git工做區的根目錄下建立一個特殊的.gitignore文件,而後把要忽略的文件名填進去,Git就會自動忽略這些文件。

不須要從頭寫.gitignore文件,GitHub已經爲咱們準備了各類配置文件,只須要組合一下就能夠使用了。全部配置文件能夠直接在線瀏覽:https://github.com/github/gitignore

忽略文件的原則是:

  1. 忽略操做系統自動生成的文件,好比縮略圖等;
  2. 忽略編譯生成的中間文件、可執行文件等,也就是若是一個文件是經過另外一個文件自動生成的,那自動生成的文件就不必放進版本庫,好比Java編譯產生的.class文件;
  3. 忽略你本身的帶有敏感信息的配置文件,好比存放口令的配置文件。

舉個例子:

假設你在Windows下進行Python開發,Windows會自動在有圖片的目錄下生成隱藏的縮略圖文件,若是有自定義目錄,目錄下就會有Desktop.ini文件,所以你須要忽略Windows自動生成的垃圾文件:

# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini

而後,繼續忽略Python編譯產生的.pyc.pyodist等文件或目錄:

# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build

加上你本身定義的文件,最終獲得一個完整的.gitignore文件,內容以下:

 
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
 
# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
 
 
# My configurations:
db.ini
deploy_key_rsa

最後一步就是把.gitignore也提交到Git,就完成了!固然檢驗.gitignore的標準是git status命令是否是說working directory clean

使用Windows的童鞋注意了,若是你在資源管理器裏新建一個.gitignore文件,它會很是弱智地提示你必須輸入文件名,可是在文本編輯器裏「保存」或者「另存爲」就能夠把文件保存爲.gitignore了。

有些時候,你想添加一個文件到Git,但發現添加不了,緣由是這個文件被.gitignore忽略了:

 
$ git add App.class
The following paths are ignored by one of your .gitignore files:
App.class
Use -f if you really want to add them.

若是你確實想添加該文件,能夠用-f強制添加到Git:

$ git add -f App.class

或者你發現,多是.gitignore寫得有問題,須要找出來到底哪一個規則寫錯了,能夠用git check-ignore命令檢查:

$ git check-ignore -v App.class
.gitignore:3:*.class App.class

Git會告訴咱們,.gitignore的第3行規則忽略了該文件,因而咱們就能夠知道應該修訂哪一個規則。

小結

  • 忽略某些文件時,須要編寫.gitignore

  • .gitignore文件自己要放到版本庫裏,而且能夠對.gitignore作版本管理!

配置別名

有沒有常常敲錯命令?好比git statusstatus這個單詞真心很差記。

若是敲git st就表示git status那就簡單多了,固然這種偷懶的辦法咱們是極力同意的。

咱們只須要敲一行命令,告訴Git,之後st就表示status(這個功能在linux上也有)

[llg@localhost llg-test-git]$ git config --global alias.st status
[llg@localhost llg-test-git]$ git st
# 位於分支 dev
# 還沒有暫存以備提交的變動:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工做區的改動)
#
# 修改: dele
#
修改還沒有加入提交(使用 "git add" 和/或 "git commit -a"

配置文件

配置Git的時候,加上--global是針對當前用戶起做用的,若是不加,那隻針對當前的倉庫起做用。

配置文件放哪了?每一個倉庫的Git配置文件都放在.git/config文件中:

 
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1

別名就在[alias]後面,要刪除別名,直接把對應的行刪掉便可。

而當前用戶的Git配置文件放在用戶主目錄下的一個隱藏文件.gitconfig中: 

$ cat .gitconfig
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com
配置別名也能夠直接修改這個文件,若是改錯了,能夠刪掉文件從新經過命令配置。

小結

給Git配置好別名,就能夠輸入命令時偷個懶。咱們鼓勵偷懶。

25.搭建Git服務器

遠程倉庫一節中,咱們講了遠程倉庫實際上和本地倉庫沒啥不一樣,純粹爲了7x24小時開機並交換你們的修改。

GitHub就是一個免費託管開源代碼的遠程倉庫。可是對於某些視源代碼如生命的商業公司來講,既不想公開源代碼,又捨不得給GitHub交保護費,那就只能本身搭建一臺Git服務器做爲私有倉庫使用。

搭建Git服務器須要準備一臺運行Linux的機器,強烈推薦用Ubuntu或Debian,這樣,經過幾條簡單的apt命令就能夠完成安裝。

假設你已經有sudo權限的用戶帳號,下面,正式開始安裝。(在這裏我使用的是Centos)

第一步,安裝git

[llg@localhost llg-test-git]$ sudo yum install git

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

[llg@localhost llg-test-git]$ sudo adduser git

第三步,建立證書登陸:

收集全部須要登陸的用戶的公鑰,就是他們本身的id_rsa.pub文件,把全部公鑰導入到/home/git/.ssh/authorized_keys文件裏,一行一個。

第四步,初始化Git倉庫:

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

[llg@localhost llg-test-git]$ sudo git init --bare sample.git
初始化空的 Git 版本庫於 /home/llg/桌面/llg-test-git/sample.git/

Git就會建立一個裸倉庫,裸倉庫沒有工做區,由於服務器上的Git倉庫純粹是爲了共享,因此不讓用戶直接登陸到服務器上去改工做區,而且服務器上的Git倉庫一般都以.git結尾。而後,把owner改成git(用戶權限)

[llg@localhost llg-test-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命令克隆遠程倉庫了,在各自的電腦上運行:

 
[llg@localhost llg-test-git]$ git clone git@127.0.0.1:/llg-test-git/sample.git/

剩下的推送就簡單了。

管理公鑰

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

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

管理權限

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

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

小結

  • 搭建Git服務器很是簡單,一般10分鐘便可完成;

  • 要方便管理公鑰,用Gitosis

  • 要像SVN那樣變態地控制權限,用Gitolite

26.總結

通過兩天的學習,站在巨人的肩膀上,我把命令都執行了一遍,大概有了個印象。

Git雖然極其強大,命令繁多,但經常使用的就那麼十來個,掌握好這十幾個經常使用命令,你已經能夠駕輕就熟地使用Git了。

友情附贈國外網友製做的Git Cheat Sheet,建議打印出來備用:

Git Cheat Sheet

Git的官方網站:http://git-scm.com

 

 

 

 

 

 


做者:廖雪峯
連接:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000來源:廖雪峯的官方網站

相關文章
相關標籤/搜索