Git的配置
在使用Git之前需要設置用戶名和用戶email末誓。這些是提交代碼的簽名有巧,每次的提交記錄例都會包含這些信息。使用git config命令進行配置:
$ git config --global user.name "clldaxigua"
$ git config --global user.email "clldaxigua@126.com"
在執(zhí)行了上面的命令以后剥险,會在用戶目錄下(~/)生成一個.gitconfig文件初斑。該文件就是Git全局的配置文件,內(nèi)容如下:
[user]
name = clldaxigua
email = clldaxigua@126.com
Git的一般配置方法是git config --global <配置名稱> <配置的值>
永淌。如果想是項目里的某個值與全局配置有區(qū)別崎场,可以在項目中使用不帶—global選項的git config
命令來設置。此時就會在當前的項目目錄下創(chuàng)建.git/config遂蛀,該配置文件僅對該項目有效谭跨。
獲得一個Git倉庫
在設置好Git的配置以后,就需要一個Git倉庫。有兩種方法可以獲得Git倉庫:一種是從已有的Git倉庫中clone螃宙;還有一種是新建一個倉庫蛮瞄,實現(xiàn)對項目文件的版本控制。
Clone一個倉庫
為了獲得一個項目的拷貝谆扎,我們需要知道這個項目倉庫的地址(Git URL)挂捅。Git支持多種通訊協(xié)議,包括ssh, http, git等堂湖。
實驗樓提供了一個測試用的共有倉庫闲先,可以使用下面的方法進行克隆:
$ git clone http://git.shiyanlou.com/shiyanlou/gitproject
Clone操作完成后无蜂,當前目錄下多出一個gitproject目錄伺糠,這個目錄中的內(nèi)容就是git clone獲得到的。由于gitproject僅是測試項目酱讶,里面只有一個README.md文件退盯。
初始化一個新的倉庫
可以對一個已存在的目錄用下面的命令對該目錄進行版本控制。
$ cd ~
$ mkdir project
$ cd project
$ git init
Initialized empty Git repository in /home/chen/project/.git/
.git目錄的內(nèi)容可以參考《Git Community Book中文版》泻肯。
'Git目錄'是為你的項目存儲所有歷史和元信息的目錄,包括所有的對(commits, trees, blobs, tags),這些對象指向不同的分支慰照。
每一個項目只能有一個'Git目錄'(這和SVN,CVS的每個子目錄中都有此類目錄相反), 這個叫'.git'的目錄在你項目的根目錄下(這是默認設置,但并不是必須的). 如果你查看這個目錄的內(nèi)容, 你可以看所有的重要文件:
$ tree -L 1
.
|-- HEAD # 這個git項目當前處在哪個分支里
|-- config # 項目的配置信息灶挟,git config命令會改動它
|-- description # 項目的描述信息
|-- hooks/ # 系統(tǒng)默認鉤子腳本目錄
|-- index # 索引文件
|-- logs/ # 各個refs的歷史信息
|-- objects/ # Git本地倉庫的所有對象 (commits, trees, blobs, tags)
|-- refs/ # 標識你項目里的每個分支指向了哪個提交(commit)
正常的工作流程
Git的基本流程如下:
- 創(chuàng)建或者修改文件。
- 使用git add命令添加新建或者修改的文件到本地的緩存區(qū)(Index)毒租。
- 使用git commit命令提交到本地代碼庫稚铣。
- 使用git push命令將本地代碼庫同步到遠端代碼庫(可選)。
一個示例
進入project目錄墅垮,分別創(chuàng)建3個文件file1, file2, file3惕医,并為3個文件添加內(nèi)容:
$ cd project
$ touch file1 file2 file3
$ echo "test content file1" >> file1
$ echo "test content file2" >> file2
$ echo "test content file3" >> file3
此時可以用git status
查看當前git倉庫的狀態(tài):
$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
file1
file2
file3
nothing added to commit but untracked files present (use "git add" to track)
此時有3個文件處于untracked狀態(tài),下一步需要用git add命令將他們添加到緩存區(qū):
$ git add file1 file2 file3
然后再次執(zhí)行git status
就會發(fā)現(xiàn)新的變化:
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to onstage)
new file: file1
new file: file2
new file: file3
此時可以使用git diff --cached
命令查看緩存區(qū)中哪些文件被修改,如下所示:
$ echo "append" >> file1
$ git diff --cached
diff --git a/file1 b/file1
new file mode 100644
index 0000000..61a4d74
--- /dev/null
+++ b/file1
@@ -0,0 +1 @@
+test content file1
diff --git a/file2 b/file2
new file mode 100644
index 0000000..4367933
--- /dev/null
+++ b/file2
@@ -0,0 +1 @@
+test content file2
diff --git a/file3 b/file3
new file mode 100644
index 0000000..6cd7bad
--- /dev/null
+++ b/file3
@@ -0,0 +1 @@
+test content file3
如果沒有—cached參數(shù)算色,則會顯示當先所有已做但是沒有加入到緩存區(qū)里的修改抬伺。
$ git diff
diff --git a/file1 b/file1
index 61a4d74..2260863 100644
--- a/file1
+++ b/file1
@@ -1 +1,2 @@
test content file1
+append
在這里需要特別說明的是git diff
命令只會顯示不在緩存區(qū)中的修改,而不會顯示不在緩存區(qū)的新建文件灾梦。也就是說峡钓,如果在project文件下新建一個file4,執(zhí)行git diff
命令并不會顯示file4若河。
此時能岩,可以通過commit命令將緩存區(qū)中的代碼提交到本地代碼倉庫中:
$ git commit -m "add 3 files"
[master (root-commit) b148ad6] add 3 files
3 files changed, 3 insertions(+)
create mode 100644 file1
create mode 100644 file2
create mode 100644 file3
再次輸入git status
查看狀態(tài),會發(fā)現(xiàn)當前的緩存區(qū)中已經(jīng)沒有待提交的文件萧福。至此拉鹃,第一次代碼提交已經(jīng)完成。之后如果需要添加或者修改文件,則需要將添加或者修改的文件git add
到緩存區(qū)中才可以提交膏燕。如果是刪除文件钥屈,則使用git rm
命令刪除后會自動將已刪除文件添加到緩存區(qū),此時執(zhí)行git commit
命令后就會將倉庫中的對應文件刪除煌寇。
這個時候焕蹄,如果本地的倉庫連接到遠程的Git服務器,則可以使用下面的命令將本地倉庫同步到遠端服務器:
$ git push origin master
分支與合并
Git的分支可以實現(xiàn)在主線(master分支)之外進行代碼提交阀溶,同時又不會影響代碼庫主線腻脏。分支的作用體現(xiàn)在多人協(xié)作開發(fā)中。比如在一個軟件項目的開發(fā)過程中银锻,一個程序員負責獨立的一個功能需要一個月的時間來完成永品,那就可以創(chuàng)建一個分支,只把該功能的代碼提交到這個分支击纬,而其他同事仍然可以繼續(xù)使用主線開發(fā)鼎姐。這樣一來,支線版本中的提交不會對他們造成任何影響更振。當該功能模塊功能實現(xiàn)并經(jīng)過測試后炕桨,再把分支代碼合并到主線中。
分支
一個Git倉庫可以維護很多開發(fā)分支】贤螅現(xiàn)在我們來創(chuàng)建一個新的叫 experimental的分支:
$ git branch experimental
運行git branch
命令可以查看當前的分支列表献宫,已經(jīng)目前的開發(fā)環(huán)境處在哪個分支上:
$ git branch
? ?experimental
* master
experimental 分支是剛才創(chuàng)建的分支,master分支是Git系統(tǒng)默認創(chuàng)建的主分支实撒。星號標識當前的工作分支姊途。輸入git checkout [branch name]
可以切換到其他分支:
$ git checkout experimental
Switched to branch 'experimental'
切換到experimental分支,切換完成后知态,先編輯里面的一個文件捷兰,再提交(commit)改動,最后切換回 “master”分支:
# 修改文件file1
$ echo "update" >> file1
# 添加并提交file1的修改
$ git add file1
# 提交代碼
$ git commit -m "update file1"
# 查看experimental分支中file1的內(nèi)容
$ cat file1
test
update
# 切換到master分支
$ git checkout master
# 查看master分支中file1的內(nèi)容
$ cat file1
test
此時查看file1中的內(nèi)容會發(fā)現(xiàn)负敏,剛才做的修改已經(jīng)消失贡茅。因為剛才的修改時在experimental分支下,現(xiàn)在切換回了master分支原在,目錄下的文件都是master分支上的文件了∮讶牛現(xiàn)在可以在master分支下再作一些不同的修改:
# 修改文件file2
$ echo "update" >> file2
# 添加并提交file2的修改
$ git add file2
$ git commit -m "update file2"
# 查看file2的內(nèi)容
$ cat file2
test
update again
合并
這時,兩個分支就有了各自不同的修改庶柿,分支的內(nèi)容都已經(jīng)不同村怪。可以通過git merge
命令來合并experimental到主線分支master:
# 切換到master分支
$ git checkout master
# 將experimental分支合并到master
$ git merge -m 'merge experimental branch' experimental
由于兩個branch修改了兩個不同的文件浮庐,所以合并時不會有沖突甚负,執(zhí)行上面的命令就可以完成代碼的合并柬焕。
合并沖突
如果有沖突,比如兩個分支修改同一個文件梭域,則合并時會失敗斑举。首先在master分支上修改file3文件并提交:
# 切換到master分支
$ git checkout master
# 修改file3文件
$ echo "master: update file3" >> file3
# 提交到master分支
$ git commit -a -m 'update file3 on master'
然后切換到experimental,修改file3并提交:
# 切換到experimental分支
$ git checkout experimental
# 修改file3文件
$ echo "experimental: update file3" >> file3
# 提交到master分支
$ git commit -a -m 'update file3 on experimental'
切換到master進行合并:
$ git checkout master
$ git merge experimental
Auto-merging file3
CONFLICT (content): Merge conflict in file3
Automatic merge failed; fix conflicts and then commit the result.
合并失敗后先用git status
查看狀態(tài)病涨,會發(fā)現(xiàn)file3顯示為both modified富玷,查看file3內(nèi)容會發(fā)現(xiàn):
$ cat file3
test
<<<<<<< HEAD
master: update file3
=======
experimental: update file3
>>>>>>> experimental
上面的內(nèi)容也可以使用git diff查看,先前已經(jīng)提到git diff不加參數(shù)可以顯示未提交到緩存區(qū)中的修改內(nèi)容既穆。
$ git diff
diff --cc file3
index 9e160c6,1b26a67..0000000
--- a/file3
+++ b/file3
@@@ -1,2 -1,2 +1,6 @@@
test3
++<<<<<<< HEAD
+master: update
++=======
+ experimental: update
++>>>>>>> experimental
同時赎懦,沖突的內(nèi)容都被添加到了file3中。
$ cat file3
test3
<<<<<<< HEAD
master: update
=======
experimental: update
>>>>>>> experimental
可以使用vim編輯這個文件幻工,去掉git自動產(chǎn)生標志沖突的<<<<<<等符號后励两,根據(jù)需要只保留我們需要的內(nèi)容后保存,然后使用git add file3
和git commit
命令來提交合并后的file3內(nèi)容囊颅,這個過程是手動解決沖突的流程当悔。
刪除分支
當我們完成合并后,不再需要experimental時踢代,可以使用下面的命令刪除:
$ git branch -d experimental
git branch -d
只能刪除那些已經(jīng)被當前分支的合并的分支. 如果你要強制刪除某個分支的話就用git branch –D
盲憎。
撤銷一個合并
如果你覺得你合并后的狀態(tài)是一團亂麻,想把當前的修改都放棄胳挎,你可以用下面的命令回到合并之前的狀態(tài):
$ git reset --hard HEAD^
快速向前合并
還有一種需要特殊對待的情況焙畔,在前面沒有提到。通常串远,一個合并會產(chǎn)生一個合并提交(commit), 把兩個父分支里的每一行內(nèi)容都合并進來。
但是儿惫,如果當前的分支和另一個分支沒有內(nèi)容上的差異澡罚,就是說當前分支的每一個提交(commit)都已經(jīng)存在另一個分支里了,git 就會執(zhí)行一個“快速向前"(fast forward)操作肾请;git 不創(chuàng)建任何新的提交(commit),只是將當前分支指向合并進來的分支留搔。
Git日志
查看日志
git log命令可以顯示所有的提交(commit):
$ git log
日志統(tǒng)計
如果用--stat選項使用'git log',它會顯示在每個提交(commit)中哪些文件被修改了, 這些文件分別添加或刪除了多少行內(nèi)容,這個命令相當于打印詳細的提交記錄:
$ git log --stat
格式化日志
你可以按你的要求來格式化日志輸出铛铁。--pretty 參數(shù)可以使用若干表現(xiàn)格式隔显。格式化輸出的格式支持oneline, short, medium, full, fuller, email 或raw。 此外饵逐,也可以用--pretty=format參數(shù)定義格式括眠。
--graph 選項可以可視化提交圖(commit graph),利用ASCII字符畫出一個提交歷史(commit history)線:
$ git log --graph --pretty=oneline
日志排序
日志記錄可以按不同的順序來顯示倍权。如果需要指定一個特定的順序掷豺,可以為git log命令添加順序參數(shù)。
按默認情況,提交會按逆時間順序顯示当船,可以指定--topo-order參數(shù)题画,讓提交按拓撲順序來顯示(就是子提交在它們的父提交前顯示);也可以用 --reverse參數(shù)來逆向顯示所有提交日志德频。