原創做者,公衆號【程序員讀書】,歡迎關注公衆號,轉載文章請註明出處哦。git
最近終於把本身負責的一些很古老的項目從SVN
遷移到了Git
,整個項目線均可以從SVN
中解放出來,不須要在SVN
和Git
之間來回切換使用,所以總算能夠靜下心來好好學習一下Git
的用法了。程序員
說到Git
,做爲程序員的你,在項目開發中必定會使用到或未來也必定會使用到的,可是我相信,不少在使用Git
的人,都只是停留一些簡單的操做上,好比提交(commit
)、拉取(pull
)、推送(push
)。github
而對於Git
的工做原理,如何解決Git
的版本衝突以及如何使用Git
進行源碼管理等問題可能並無太深的認識,那麼接下來,咱們從最基礎的開始,一塊兒由淺入深來探討一下。數據庫
Git
目前最流行和最強大的開源分佈式版本控制管理系統。vim
Git
做者是Linus Torvalds
,這個名字是否是聽着很熟,沒錯,是Linus Torvalds
也是Linux
操做系統的做者。安全
Git
的做者由於很討厭集中式版本控制管理系統,因此纔會想開發分佈式版本管理系統,這纔有Git
的誕生。bash
Git
開發的初衷也是爲了方便Linux
社區更好地管理和維護Linux
系統的代碼。服務器
Git
與SVN
之間的比較,也能夠看做是分佈式版本管理系統
與集中式版本管理系統
的比較,Git
是分佈式版本管理系統,而SVN
是集中式版本管理系統。編輯器
對於集中式版本管理系統
而言,版本庫是放在遠程服務器上的,開發人員經過與服務器上的版本庫鏈接進行代碼版本提交,若是沒法鏈接到服務器上,根本沒有辦法進行代碼的版本管理,如:分佈式
而分佈式版本管理系統,代碼提交與版本管理均可以本地進行,沒必要連到服務器就能夠進行各類版本管理操做。
只有當咱們以爲須要與其餘人同步代碼時,才須要連到其餘版本庫進行同步操做,以下圖所示:
Git
雖然很是強大好用,但其學習難度比SVN
大,雖然上手很容易,只須要學習git add
,git commit
,git push
和git pull
,但要真正學會且能很好地應用於複雜的項目開發管理,其學習週期仍是比較長的,而SVN
則相對比較容易掌握。
Git
的版本庫是存儲在咱們的本地,因此會佔用咱們本地的存儲空間,另外,因爲Git
版本庫包含每一個文件的的副本,所以相比集中式的版本控制管理系統,也會佔用更多的存儲空間。
Git
是分佈式版本控制系統,經過Git
提供的工具集,咱們能夠管理本地版本庫,並能夠將代碼提交到遠程版本庫或拉回其餘人提交的版本。
Github
是基於Git
的在線Web
代碼託管服務,咱們能夠在Github
上建立本身的公有或私有的版本庫(私有庫要錢的
),並能夠經過Web
頁面進行管理,而在咱們本地還能夠經過Git
與之交互,將代碼提交到Github
上面的遠程版本庫中與團隊其餘成員共享。
若是咱們對本身的項目源代碼的安全性要求更高呢?這時候咱們須要搭建本身的代碼託管服務,這時候GitLab
即是很好的選擇了。
GitLab
是一套用於搭建咱們本身的私有Web
代碼託管服務項目,經過使用GitLab
,咱們能夠在本身的服務器上搭建與Github
同樣的Web
代碼託管服務器,一樣,GitLab
也提供同樣的Web
頁面管理操做。
若是你完成了Git
的安裝,那麼在使用Git
以前你須要完成一個小小的配置,就是配置用戶信息。
Git
的全部配置使用git config
命令來完成,而用戶信息只須要配置user.name
和user.email
便可,以下:
# 配置用戶名
git config --global user.name '你的用戶名'
# 配置郵箱
git config --global user.email '你的郵箱'
複製代碼
上面git config
命令用參數--global
指定的配置爲全局配置,也就是對全部版本庫都會生效,除了--global
外,git config
命令還能夠經過--local
、-- system
兩個參數來指定配置的級別。
參數 | 說明 |
---|---|
--global | 全局有效 |
--system | 對當前全部登陸的用戶有效 |
--local | 對當前版本庫有效 |
若是有相同的配置,經過--local
指定的配置優先大於--system
,而--system
的優先級大於--global
。
在git config
後面跟上--list
參數能夠查看Git
配置,再指定--global
,--system
,--local
,能夠查看不一樣級別的配置,如:
git config --list --global
複製代碼
git config --list --system
複製代碼
git config --list --local
複製代碼
若是指定--local
時,當前執行命令的目錄必須在一個版本庫下,不然會報如下的錯誤:
fatal: --local can only be used inside a git repository
複製代碼
版本庫是Git
中最重要的概念,在一個版本庫中,包含了當前項目全部的提交。
安好Git
以後,即可以經過Git
提供的命令來建立版本庫了,經過版本庫,將添加到版本庫裏面的文件進行版本管理。
先建立目錄,再建立版本庫
# 建立空目錄
$ mkdir test
# 進入空目錄
$ cd test
# 初始化版本庫
$ git init
複製代碼
咱們也能夠將上面的的步驟簡化爲:
$ git init test
$ cd test
複製代碼
上面咱們經過git init
命令在本地初始化一個版本庫,一種這種稱爲裸庫
,而有時候,咱們會直接經過git clone
命令將遠程的版本庫克隆到本地,如:
git clone https://www.github.com/test/test.git
複製代碼
經過這種方式,咱們能夠將遠程版本庫中項目克隆到本地,當咱們參與一些老的項目時,通常就是採用這種方式來建立本地的版本庫。
經過上面的兩種方式,咱們已經在本地建立好了版本庫,接下來咱們就能夠開始將本身的文件添加到版本庫了。
首先咱們在工做目錄建立名爲test.txt
的文件,內容能夠隨意,好比:
這是我添加到版本庫中的第一個文件
複製代碼
這時候咱們經過git status
命令查看工做目錄的狀態,以下所示:
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
test.txt
nothing added to commit but untracked files present (use "git add" to track)
複製代碼
能夠看到,Git
提示咱們要執行git add <file>
操做,這是將文件到添加Git
的暫存區,咱們執行一下:
# 下面三個命令均可以將test.txt添加到暫存區
git add test.txt
git add .
git add all
複製代碼
再使用git status
查看狀態,以下表示已經添加到暫時區了。
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: test.txt
複製代碼
接下來即是將暫存區中的文件提交到版本庫了,使用git commit
命令,後面的-m
表示提示說明。
git commit -m "添加test.txt文件"
複製代碼
提交後,結果以下:
[master 23811d4] 添加test.txt文件
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.txt
複製代碼
上面結果提示中,23811d4
表示本次的提交的ID
,這個ID
是其實是由40個十進制數字組的SHA1散列值,上面結果中顯示只是這個提交ID的前7位值。
這裏須要明確幾個概念,那就是工做區
、暫存區
、版本庫
,該項目全部目錄,咱們稱爲工做區
,而在該目錄下,會生成一個.git
的隱藏目錄,這個目錄咱們稱爲版本庫
,暫存區(stage)
是Git
獨有的概念,暫存區
是版本庫
的一部分,這三者之間的關係,咱們以下圖所示:
若是想把文件從暫存區移除,可能使用下面的命令:
git rm --cached test.txt
複製代碼
咱們知道在Git
中,每一個提供都會產生一個40
位十六進制數字組成的SHA1
散列值,而由這些值串成的一條時間線,即是分支,在上面的演示中,咱們一直在Git
的master
分支上。
master
是Git
的默認分支,除了master
外,咱們任意建立本身的分支,分支老是向指最新的提交(commit
),而在Git
版本庫中,還保留着一個指針HEAD
,默認指向當前分支,因此分支、HEAD與commit的關係是HEAD
是一個指針,指向當前分支的最新提交(commit
),而且將HEAD
保存在.git/HEAD
文件當中。
經過下面的圖,咱們能夠更好地理解不一樣分支,提交與HEAD
的關係:
在git branch
命令後面跟上分支名
能夠基於當前的分支再建立一個新的分支,如:
git branch deveolp
複製代碼
git branch
複製代碼
執行結果以下:
develop
* master
複製代碼
也可使用下面的方式查看分支列表
$ git show-branch
! [develop] develop
* [master] develop
--
+* [develop] develop
複製代碼
經過git branch
命令建立好分支後,Git
並不會幫咱們檢出該分支,咱們可使用git checkout
命令檢出該分支,這樣即可以在該分支下進行開發了,如:
$ git checkout develop
複製代碼
若是檢出的分支不存在,則會報錯,好比咱們檢出不存在的dev
分支,會報以下所示的錯誤:
error: pathspec 'dev' did not match any file(s) known to git
複製代碼
若是在檢出分支不存在時,想基於當前分支直接建立分支,也能夠在git checkout
跟上參數-b
,如:
git checkout -b dev
複製代碼
這樣即可以直接建立分支了,固然,若是分支已經存在,也會報錯,好比:
git checkout -b develop
複製代碼
因爲咱們建立了develop
,所以會報出如下錯誤:
fatal: A branch named 'develop' already exists.
複製代碼
對於不想的分支,可使用git branch -d
命令進行刪除,如:
git branch -d develop
複製代碼
強制刪除
git branch -D develop
複製代碼
當咱們開發完成後,從develop
合併到master
,這時的操做應該切到master
分支下,在master
執行合併命令。
git merge develop
複製代碼
Git
支持打標籤(tag
)的操做,標籤有時候也稱爲里程碑,當咱們開發到必定階段有必定的成果,咱們能夠在當前分支上打上一個標籤,好比說咱們在開發到某個階段時,在分支打上v1.0
的標籤,表示1.0
版本已經完成。
在打標籤以前,咱們先看一下如何查看全部的標籤,如:
$ git tag
v1.0
v1.1
v1.2
v2.3
複製代碼
上面的命令會簡單顯示全部的一個簡單的標籤列表,若是想查看標籤的說明,能夠這樣
$ git tag -n1
v1.0 develop
v1.1 develop
v1.2 develop
v2.3 develop
複製代碼
使用通配符查看本地標籤
$ git tag -l v1.*
v1.0
v1.1
v1.2
複製代碼
建立標籤有如下幾種方式:
git tag <tag_name> [commit_id]
git tag -a <tag_name> [commit_id]
git tag -m message <tag_name> [commit_id]
git tag -s <tag_name> [commit_id]
git tag -u <key> <tag_name> [commit_id]
複製代碼
不帶commit_id
,建立沒有說明的tag
:
git tag v1.0
複製代碼
使用-a
參數添加標籤說明,這種方式會打一個vim
編輯器讓咱們輸入說明:
git tag -a v1.1
複製代碼
在某個commit
之上打標籤
git tag v1.2 c22be11
複製代碼
Git
標籤不容許修改,若是咱們對某個標籤不滿意,能夠刪除標籤,再從新建立,刪除標籤語句以下:
git tag -d v1.2
複製代碼
在項目開發時,有一些文件咱們不想添加到怎麼版本庫中進行版本控制,好比IDE
自動生成的配置文件、項目數據庫配置文件或者編譯後生成的臨時目錄等等。
這時候咱們能夠在工做目錄中添加.gitignore
文件來指要忽略哪些目錄或文件,並將.gitignore
文件添加到版本庫,由於.gitignore
文件須要進行版本控制。
固然,除了經過.gitignore
文件指定忽略文件外,也能夠經過命令行直接指定。
在工做區根目錄建立.gitignore
文件是最經常使用的方式,這種方式能夠控制整個項目的文件。
在某個子目錄上建立.gitignore
文件來覆蓋上層目錄中.gitignore
的忽略規則對當前目錄的影響。
當咱們在工做區建立忽略文件後,若是咱們經過push
操做把項目推送到遠程版本庫,那麼忽略文件一樣也要推送上去,這裏別的開發者也會獲得一樣的的忽略規則,若是有時候忽略規則只是咱們本地獨有的,不想與別人共享,那咱們能夠經過下面的方式,配置一個全局的
git config --global core.excludesfile ~/.gitignore
複製代碼
在.git/info/exclude
也能夠添加忽略規則,這種方式並不經常使用,與全局.gitignore
文件同樣,這種方式也是本地獨有,並不會與其餘開發者共享。
既然能夠經過這麼多種方式來指定.gitignore
文件,那麼不一樣的.gitignore
就有不一樣的優先級,其優先級由高到低以下所示:
從命令行中讀取可用的忽略規則最高
當前目錄定義的規則
父級目錄定義的規則,依次遞推,直到工做區根目錄
.git/info/exclude
文件中定義的規則
core.excludesfile
中定義的全局規則
#
:#用於註釋說明
*
:通配符,表示任何個字符。
?
:表示一個任何字符。
!
:表示不忽略該文件或目錄
/
:/
位置一行開始位置時,表示忽略這個目錄下的文件,不忽略其餘子目錄的同名文件,若是/
位置一行的最後位置,則表示只忽略目錄,而同名文件不忽略。
[abc]
:可選的字符範圍
示例
# 這是一行註釋
a* #忽略任何以a開頭的文件和目錄
!action # 不忽略action文件
/verdor #忽略根目錄下的verdor文件
複製代碼
忽略文件只對未跟蹤的文件有效果,若是某個文件已經被提交到版本庫了,這時候再把文件添加了忽略文件中,也不會有效果了。
其實,不管你是否是一名程序員,均可以把Git
做爲管理一個本身文檔或代碼的工具,經過使用Git
,咱們能夠更高效地管理和組織本身的項目和文檔,在不斷地修改和變動中,也不懼怕文檔的丟失。
若是你以爲文章不錯,歡迎掃碼關注,你的關注就是我寫做的最大動力