Git不只是一款開源的分佈式版本控制系統,並且有其獨特的功能特性,例如大多數的分佈式版本控制系統只會記錄每次文件的變化,說白了就是隻會關心文件的內容變化差別,而Git則是關注於文件數據總體的變化,直接會將文件提交時的數據保存成快照,而非僅記錄差別內容,而且使用SHA-1加密算法保證數據的完整性。linux
Git的三種重要模式,分別是已提交、已修改和已暫存:c++
已提交(committed):表示數據文件已經順利提交到Git數據庫中。git
已修改(modified):表示數據文件已經被修改,但未被保存到Git數據庫中。算法
已暫存(staged):表示數據文件已經被修改,並會在下次提交時提交到Git數據庫中。數據庫
提交前的數據文件可能會被隨意修改或丟失,但只要把文件快照順利提交到Git數據庫中,那就能夠徹底放心了,流程爲:編程
1.在工做目錄中修改數據文件。vim
2.將文件的快照放入暫存區域。安全
3.將暫存區域的文件快照提交到Git倉庫中。服務器
下面咱們開始安裝git服務程序。yum -y install git編輯器
首次安裝Git服務程序後須要設置下用戶名稱、郵件信息和編輯器,這些信息會隨着文件每次都提交到Git數據庫中,用於記錄提交者的信息,而Git服務程序的配置文檔一般會有三份,針對當前用戶和指定倉庫的配置文件優先級最高:
配置文件 | 做用 |
/etc/gitconfig | 保存着系統中每一個用戶及倉庫通用配置信息。 |
~/.gitconfig ~/.config/git/config |
針對於當前用戶的配置信息。 |
工做目錄/.git/config | 針對於當前倉庫數據的配置信息。 |
第一個要配置的是你我的的用戶名稱和電子郵件地址,這兩條配置很重要,每次 Git 提交時都會引用這兩條信息,記錄是誰提交了文件,而且會隨更新內容一塊兒被永久歸入歷史記錄:
Git 提供了一個叫作 git config
的工具(譯註:實際是 git-config
命令,只不過能夠經過 git
加一個名字來呼叫此命令。),專門用來配置或讀取相應的工做環境變量。而正是由這些環境變量,決定了 Git 在各個環節的具體工做方式和行爲。這些變量能夠存放在如下三個不一樣的地方
/etc/gitconfig
文件:系統中對全部用戶都廣泛適用的配置。若使用 git config
時用 --system
選項,讀寫的就是這個文件。~/.gitconfig
文件:用戶目錄下的配置文件只適用於該用戶。若使用 git config
時用 --global
選項,讀寫的就是這個文件。.git/config
文件):這裏的配置僅僅針對當前項目有效。每個級別的配置都會覆蓋上層的相同配置,因此 .git/config
裏的配置會覆蓋 /etc/gitconfig
中的同名變量。在 Windows 系統上,Git 會找尋用戶主目錄下的 .gitconfig
文件。主目錄即 $HOME
變量指定的目錄,通常都是 C:\Documents and Settings\$USER
。此外,Git 還會嘗試找尋 /etc/gitconfig
文件,只不過看當初 Git 裝在什麼目錄,就以此做爲根目錄來定位。
第一個要配置的是你我的的用戶名稱和電子郵件地址,這兩條配置很重要,每次 Git 提交時都會引用這兩條信息,記錄是誰提交了文件,而且會隨更新內容一塊兒被永久歸入歷史記錄:
若是用了 --lobal
選項,那麼更改的配置文件就是位於你用戶主目錄下的那個,之後你全部的項目都會默認使用這裏配置的用戶信息。若是要在某個特定的項目中使用其餘名字或者電郵,只要去掉 --global
選項從新配置便可,新的設定保存在當前項目的 .git/config
文件裏。
接下來要設置的是默認使用的文本編輯器。Git 須要你輸入一些額外消息的時候,會自動調用一個外部文本編輯器給你用。默認會使用操做系統指定的默認編輯器,通常可能會是 Vi 或者 Vim。若是你有其餘偏好,好比 Emacs 的話,能夠從新設置:
還有一個比較經常使用的是,在解決合併衝突時使用哪一種差別分析工具。好比要改用 vimdiff 的話:
要檢查已有的配置信息,可使用 git config --list
命令:
-----------------------------------------------------------------------------------------------------------------------
提交數據
接下來咱們進行提交數據
咱們能夠簡單的把工做目錄理解成是一個被Git服務程序管理的目錄,Git會時刻的追蹤目錄內文件的改動,另外在安裝好了Git服務程序後,默認就會建立好了一個叫作master的分支,咱們直接能夠提交數據到主線了。
建立本地的工做目錄:
而後用git init將該目錄初始化轉成Git的工做目錄:
Git只能追蹤相似於txt文件、網頁、程序源碼等文本文件的內容變化,而不能判斷圖片、視頻、可執行命令等這些二進制文件的內容變化,因此先來嘗試往裏面寫入一個新文件吧。
將該文件添加到暫存區:
添加到暫存區後再次修改文件的內容:
將暫存區的文件提交到Git版本倉庫,命令格式爲「git commit -m "提交說明」:
查看當前工做目錄的狀態(咦,爲何文件仍是提示被修改了?):
由於提交操做只是將文件在暫存區中的快照版本提交到Git版本數據庫,因此當你將文件添加到暫存區後,若是又對文件作了修改,請必定要再將文件添加到暫存區後提交到Git版本數據庫:
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
查看當前文件內容與Git版本數據庫中的差異:
那麼如今把文件提交到Git版本數據庫吧:
再來查看下當前Git版本倉庫的狀態:
有些時候工做目錄內的文件會比較多,懶的把文件一個個提交到暫存區,能夠先設置下要忽略上傳的文件(寫入到"工做目錄/.gitignore"文件中),而後使用"git add ."命令來將當前工做目錄內的全部文件都一塊兒添加到暫存區域。
//忽略全部以.a爲後綴的文件。
*.a
//可是lib.a這個文件除外,依然會被提交。
!lib.a
//忽略build目錄內的全部文件。
build/
//忽略build目錄內以txt爲後綴的文件。
build/*.txt
//指定忽略名字爲git.c的文件。
git.c
先在工做目錄中建立一個名字爲git.c的文件:
而後建立忽略文件列表:
添加將當前工做目錄中的全部文件快照上傳到暫存區:
通過剛剛的實驗,你們必定發現「添加到暫存區」真是個很麻煩的步驟,雖然使用暫存區的方式可讓提交文件更加的準確,但有時卻略顯繁瑣,若是對要提交的文件徹底有把握,咱們徹底能夠追加-a參數,這樣Git會將之前全部追蹤過的文件添加到暫存區後自動的提交,從而跳過了上傳暫存區的步驟,再來修改下文件:
文件被直接提交到Git數據庫:
好比想把git.c也提交上去,即可以這樣強制添加文件:
而後從新提交一次(即修改上次的提交操做):
移除數據
有些時候會想把已經添加到暫存區的文件移除,但仍然但願文件在工做目錄中不丟失,換句話說,就是把文件從追蹤清單中刪除。
先添加一個新文件,並上傳到暫存區:
查看當前的Git狀態:
將該文件從Git暫存區域的追蹤列表中移除(並不會刪除當前工做目錄內的數據文件):
此時文件已是未追蹤狀態了:
而若是咱們想將文件數據從Git暫存區和工做目錄中一塊兒刪除,能夠這樣操做:
再將database文件提交到Git暫存區:
使用git rm命令能夠直接刪除暫存區內的追蹤信息及工做目錄內的數據文件:
但若是在刪除以前數據文件已經被放入到暫存區域的話,Git會擔憂你勿刪未提交的文件而提示報錯信息,此時可追增強制刪除-f參數。
查看當前Git的狀態:
移動數據
Git不像其餘版本控制系統那樣跟蹤文件的移動操做,若是要修改文件名稱,則須要使用git mv命令:
發現下次提交時會有一個更名操做:
提交文件到Git版本倉庫:
其實咱們還能夠這樣來修改文件名,首先將工做目錄下的數據文件更名:
而後刪除Git版本倉庫內的文件快照:
最後再將新的文件添加進入:
歷史記錄
在完成上面的實驗後,咱們已經不知不覺有了不少次的提交操做了,能夠用git log命令來查看提交歷史記錄:
像上面直接執行git log命令後會看到全部的更新記錄(按時間排序,最近更新的會在上面),歷史記錄會除了保存文件快照,還會詳細的記錄着文件SHA-1校驗和,做者的姓名,郵箱及更新時間,若是隻想看最近幾條記錄,能夠直接這樣操做:
我也經常使用-p參數來展開顯示每次提交的內容差別,例如僅查看最近一次的差別:
咱們還可使用--stat參數來簡要的顯示數據增改行數,這樣就可以看到提交中修改過的內容、對文件添加或移除的行數,並在最後列出全部增減行的概要信息(僅看最近兩次的提交歷史):
還有一個超級經常使用的--pretty參數,它能夠根據不一樣的格式爲咱們展現提交的歷史信息,好比每行顯示一條提交記錄:
以更詳細的模式輸出最近兩次的歷史記錄:
還可使用format參數來指定具體的輸出格式,這樣很是便於後期編程的提取分析,經常使用的格式有:
%s | 提交說明。 |
%cd | 提交日期。 |
%an | 做者的名字。 |
%cn | 提交者的姓名。 |
%ce | 提交者的電子郵件。 |
%H | 提交對象的完整SHA-1哈希字串。 |
%h | 提交對象的簡短SHA-1哈希字串。 |
%T | 樹對象的完整SHA-1哈希字串。 |
%t | 樹對象的簡短SHA-1哈希字串。 |
%P | 父對象的完整SHA-1哈希字串。 |
%p | 父對象的簡短SHA-1哈希字串。 |
%ad | 做者的修訂時間。 |
另外做者和提交者是不一樣的,做者纔是對文件做出實際修改的人,而提交者只是最後將此文件提交到Git版本數據庫的人。
查看當前全部提交記錄的簡短SHA-1哈希字串與提交者的姓名:
還原數據
還原數據是每個版本控制的基本功能,先來隨意修改下文件吧:
而後將文件提交到Git版本數據庫:
此時以爲寫的不妥,想要還原某一次提交的文件快照:
Git服務程序中有一個叫作HEAD的版本指針,當用戶申請還原數據時,其實就是將HEAD指針指向到某個特定的提交版本而已,可是由於Git是分佈式版本控制系統,因此不可能像SVN那樣使用一、二、三、4來定義每一個歷史的提交版本號,爲了不歷史記錄衝突,故使用了SHA-1計算出十六進制的哈希字串來區分每一個提交版本,像剛剛最上面最新的提交版本號就是2377979c14c74ed8f430c04fa667882bfe8906c8,另外默認的HEAD版本指針會指向到最近的一次提交版本記錄哦,而上一個提交版本會叫HEAD^,上上一個版本則會叫作HEAD^^,固然通常會用HEAD~5來表示往上數第五個提交版本哦~。
好啦,既然咱們已經鎖定了要還原的歷史提交版本,就可使用git reset命令來還原數據了:
再來看下文件的內容吧(怎麼樣,內容果真已經還原了吧~):
剛剛的操做實際上就是改變了一下HEAD版本指針的位置,說白了就是你將HEAD指針放在那裏,那麼你的當前工做版本就會定位在那裏,要想把內容再還原到最新提交的版本,先查看下提交版本號吧:
怎麼搞得?居然沒有了Introduction software這個提交版本記錄??
緣由很簡單,由於咱們當前的工做版本是歷史的一個提交點,這個歷史提交點尚未發生過Introduction software更新記錄,因此固然就看不到了,要是想「還原到將來」的歷史更新點,能夠用git reflog命令來查看全部的歷史記錄:
找到歷史還原點的SHA-1值後,就能夠還原文件了,另外SHA-1值沒有必要寫全,Git會自動去匹配:x
如是隻是想把某個文件內容還原,就沒必要這麼麻煩,直接用git checkout命令就能夠的,先隨便寫入一段話:
咱們忽然發現不該該寫一句話的,能夠手工刪除(當內容比較多的時候會很麻煩),還能夠將文件內容從暫存區中恢復:
checkou規則是若是暫存區中有該文件,則直接從暫存區恢復,若是暫存區沒有該文件,則將還原成最近一次文件提交時的快照。
管理標籤
當版本倉庫內的數據有個大的改善或者功能更新,咱們常常會打一個相似於軟件版本號的標籤,這樣經過標籤就能夠將版本庫中的某個歷史版本給記錄下來,方便咱們隨時將特定歷史時期的數據取出來用,另外打標籤其實只是向某個歷史版本作了一個指針,因此通常都是瞬間完成的,感受很方便吧。
在Git中打標籤很是簡單,給最近一次提交的記錄打個標籤:
查看全部的已有標籤:
查看此標籤的詳細信息:
還能夠建立帶有說明的標籤,用-a指定標籤名,-m指定說明文字:
咱們爲同一個提交版本設置了兩次標籤,來把以前的標籤刪除吧:
分支便是平行空間,假設你在爲某個手機系統研發拍照功能,代碼已經完成了80%,但若是將這不完整的代碼直接提交到git倉庫中,又有可能影響到其餘人的工做,此時咱們即可以在該軟件的項目之上建立一個名叫「拍照功能」的分支,這種分支只會屬於你本身,而其餘人看不到,等代碼編寫完成後再與原來的項目主分支合併下便可,這樣即能保證代碼不丟失,又不影響其餘人的工做。
通常在實際的項目開發中,咱們要儘可能保證master分支是很是穩定的,僅用於發佈新版本,平時不要隨便直接修改裏面的數據文件,而工做的時候則能夠新建不一樣的工做分支,等到工做完成後在合併到master分支上面,因此團隊的合做分支看起來會像上面圖那樣。
另外如前面所講,git會將每次的提交操做串成一個時間線,而在前面的實驗中實際都是在對master分支進行操做,Git會在建立分支後默認建立一個叫作Photograph的指針,因此咱們還須要再將HEAD指針切換到「Photograph」的位置才正式使用上了新分支哦,這麼提及來可能比較抽象,趕忙學習下面的實驗吧。
建立分支
首先建立分支:
切換至分支:
查看當前分支的狀況(會列出該倉庫中全部的分支,當前的分支前有*號)
咱們對文件再追加一行字符串吧:
將文件提交到git倉庫:
爲了讓你們更好理解分支的做用,咱們在提交文件後再切換回master分支:
而後查看下文件內容,發現並無新追加的字符串哦:
合併分支
如今,咱們想把laojigit的工做成果合併到master分支上了,則可使用"git merge"命令來將指定的的分支與當前分支合併:
查看合併後的readme.txt文件:
確認合併完成後,就能夠放心地刪除laojigit分支了:
刪除後,查看branch,就只剩下master分支了:(那個laoji開始就有,自動忽略)
內容衝突
可是Git並不能每次都爲咱們自動的合併分支,當遇到了內容衝突比較複雜的狀況,則必須手工將差別內容處理掉,好比這樣的狀況:
建立分支並切換到該分支命令:git checkout -b 分支名稱
建立一個新分支並切換到該分支命令:
修改readme.txt文件內容:
在laojigit分支上提交:
切換到master分支:
在master分支上修改readme.txt文件同一行的內容:
提交至Git版本倉庫:
那麼此時,咱們在master與laojigit分支上都分別對中readme.txt文件進行了修改並提交了,那這種狀況下Git就無法再爲咱們自動的快速合併了,它只能告訴咱們readme.txt文件的內容有衝突,須要手工處理衝突的內容後才能繼續合併:
衝突的內容爲:
Git用< <<<<<<,=======,>>>>>>>分割開了各個分支衝突的內容,咱們須要手工的刪除這些符號,並將內容修改成:
Hello Word c++
what is name
again
Git is a version control system
wahhaha a wa hahaha and simple
解決衝突內容後則可順利的提交:
查看Git歷史提交記錄(能夠看到分支的變化):
最後,放心的刪除laojigit分支吧:
-----------------------------------------------------------------------------------------------------------------------------------------------------
Git是分佈式的版本控制系統,咱們只要有了一個原始Git版本倉庫,就可讓其餘主機克隆走這個原始版本倉庫,從而使得一個Git版本倉庫能夠被同時分佈到不一樣的主機之上,而且每臺主機的版本庫都是同樣的,沒有主次之分,極大的保證了數據安全性,並使得用戶可以自主選擇向那個Git服務器推送文件了,其實部署一個git服務器是很是簡單的事情,咱們須要用到兩臺主機,分別是:
主機名稱 | 操做系統 | IP地址 |
Git服務器 | 紅帽RHEL7操做系統 | 192.168.10.10 |
Git客戶端 | 紅帽RHEL7操做系統 | 192.168.10.20 |
首先咱們分別在Git服務器和客戶機中安裝Git服務程序(剛剛實驗安裝過就不用安裝了):
而後建立Git版本倉庫,通常規範的方式要以.git爲後綴:
修改Git版本倉庫的全部者與全部組:
初始化Git版本倉庫:
其實此時你的Git服務器就已經部署好了,但用戶還不能向你推送數據,也不能克隆你的Git版本倉庫,由於咱們要在服務器上開放至少一種支持Git的協議,好比HTTP/HTTPS/SSH等,如今用的最多的就是HTTPS和SSH,咱們切換至Git客戶機來生成SSH密鑰:
將客戶機的公鑰傳遞給Git服務器:
此時就已經能夠從Git服務器中克隆版本倉庫了(此時目錄內沒有文件是正常的):