Git 教程

Git 與 SVN 區(qū)別

Git不僅僅是個(gè)版本控制系統(tǒng)蕉斜,它也是個(gè)內(nèi)容管理系統(tǒng)(CMS),工作管理系統(tǒng)等锌奴。
如果你是一個(gè)具有使用SVN背景的人,你需要做一定的思想轉(zhuǎn)換伊者,來適應(yīng)Git提供的一些概念和特征坤候。

Git 與 SVN 區(qū)別點(diǎn):

  1. Git是分布式的胁赢,SVN不是:這是Git和其它非分布式的版本控制系統(tǒng),例如SVN白筹,CVS等智末,最核心的區(qū)別谅摄。
  2. Git把內(nèi)容按元數(shù)據(jù)方式存儲(chǔ),而SVN是按文件:所有的資源控制系統(tǒng)都是把文件的元信息隱藏在一個(gè)類似.svn,.cvs等的文件夾里系馆。
  3. Git分支和SVN的分支不同:分支在SVN中一點(diǎn)不特別送漠,就是版本庫中的另外的一個(gè)目錄。
  4. Git沒有一個(gè)全局的版本號由蘑,而SVN有:目前為止這是跟SVN相比Git缺少的最大的一個(gè)特征螺男。
  5. Git的內(nèi)容完整性要優(yōu)于SVN:Git的內(nèi)容存儲(chǔ)使用的是SHA-1哈希算法。這能確保代碼內(nèi)容的完整性纵穿,確保在遇到磁盤故障和網(wǎng)絡(luò)問題時(shí)降低對版本庫的破壞。

Git 工作流程

  • 本章節(jié)我們將為大家介紹 Git 的工作流程奢人。
  • 一般工作流程如下:
  • 克隆 Git 資源作為工作目錄谓媒。
  • 在克隆的資源上添加或修改文件。
  • 如果其他人修改了何乎,你可以更新資源句惯。
  • 在提交前查看修改。
  • 提交修改支救。
  • 在修改完成后抢野,如果發(fā)現(xiàn)錯(cuò)誤,可以撤回提交并再次修改并提交各墨。
    下圖展示了 Git 的工作流程:


Git 工作區(qū)指孤、暫存區(qū)和版本庫

基本概念

我們先來理解下Git 工作區(qū)、暫存區(qū)和版本庫概念

  • 工作區(qū):就是你在電腦里能看到的目錄贬堵。
  • 暫存區(qū):英文叫stage, 或index恃轩。一般存放在"git目錄"下的index文件(.git/index)中,所以我們把暫存區(qū)有時(shí)也叫作索引(index)黎做。
  • 版本庫:工作區(qū)有一個(gè)隱藏目錄.git叉跛,這個(gè)不算工作區(qū),而是Git的版本庫蒸殿。

下面這個(gè)圖展示了工作區(qū)筷厘、版本庫中的暫存區(qū)和版本庫之間的關(guān)系:


圖中左側(cè)為工作區(qū),右側(cè)為版本庫宏所。在版本庫中標(biāo)記為 "index" 的區(qū)域是暫存區(qū)(stage, index)酥艳,標(biāo)記為 "master" 的是 master 分支所代表的目錄樹。
圖中我們可以看出此時(shí) "HEAD" 實(shí)際是指向 master 分支的一個(gè)"游標(biāo)"楣铁。所以圖示的命令中出現(xiàn) HEAD 的地方可以用 master 來替換玖雁。
圖中的 objects 標(biāo)識的區(qū)域?yàn)?Git 的對象庫,實(shí)際位于 ".git/objects" 目錄下盖腕,里面包含了創(chuàng)建的各種對象及內(nèi)容赫冬。
當(dāng)對工作區(qū)修改(或新增)的文件執(zhí)行 "git add" 命令時(shí)浓镜,暫存區(qū)的目錄樹被更新,同時(shí)工作區(qū)修改(或新增)的文件內(nèi)容被寫入到對象庫中的一個(gè)新的對象中劲厌,而該對象的ID被記錄在暫存區(qū)的文件索引中膛薛。
當(dāng)執(zhí)行提交操作(git commit)時(shí),暫存區(qū)的目錄樹寫到版本庫(對象庫)中补鼻,master 分支會(huì)做相應(yīng)的更新哄啄。即 master 指向的目錄樹就是提交時(shí)暫存區(qū)的目錄樹。
當(dāng)執(zhí)行 "git reset HEAD" 命令時(shí)风范,暫存區(qū)的目錄樹會(huì)被重寫咨跌,被 master 分支指向的目錄樹所替換,但是工作區(qū)不受影響硼婿。
當(dāng)執(zhí)行 "git rm --cached <file>" 命令時(shí)锌半,會(huì)直接從暫存區(qū)刪除文件,工作區(qū)則不做出改變寇漫。
當(dāng)執(zhí)行 "git checkout ." 或者 "git checkout -- <file>" 命令時(shí)刊殉,會(huì)用暫存區(qū)全部或指定的文件替換工作區(qū)的文件。這個(gè)操作很危險(xiǎn)州胳,會(huì)清除工作區(qū)中未添加到暫存區(qū)的改動(dòng)记焊。
當(dāng)執(zhí)行 "git checkout HEAD ." 或者 "git checkout HEAD <file>" 命令時(shí),會(huì)用 HEAD 指向的 master 分支中的全部或者部分文件替換暫存區(qū)和以及工作區(qū)中的文件栓撞。這個(gè)命令也是極具危險(xiǎn)性的遍膜,因?yàn)椴坏珪?huì)清除工作區(qū)中未提交的改動(dòng),也會(huì)清除暫存區(qū)中未提交的改動(dòng)腐缤。

Mac 平臺上安裝

在 Mac 平臺上安裝 Git 最容易的當(dāng)屬使用圖形化的 Git 安裝工具捌归,下載地址為:
http://sourceforge.net/projects/git-osx-installer/
安裝界面如下所示:

Git 配置

Git 提供了一個(gè)叫做 git config 的命令,專門用來配置或讀取相應(yīng)的工作環(huán)境變量岭粤。這些環(huán)境變量惜索,決定了 Git 在各個(gè)環(huán)節(jié)的具體工作方式和行為。這些變量可以存放在以下三個(gè)不同的地方:

  • /etc/gitconfig 文件:系統(tǒng)中對所有用戶都普遍適用的配置剃浇。若使用 git config 時(shí)用 --system 選項(xiàng)巾兆,讀寫的就是這個(gè)文件。

  • ~/.gitconfig 文件:用戶目錄下的配置文件只適用于該用戶虎囚。若使用 git config 時(shí)用 --global 選項(xiàng)角塑,讀寫的就是這個(gè)文件。

  • 當(dāng)前項(xiàng)目的 Git 目錄中的配置文件(也就是工作目錄中的 .git/config 文件):這里的配置僅僅針對當(dāng)前項(xiàng)目有效淘讥。每一個(gè)級別的配置都會(huì)覆蓋上層的相同配置圃伶,所以 .git/config 里的配置會(huì)覆蓋 /etc/gitconfig 中的同名變量。

用戶信息

配置個(gè)人的用戶名稱和電子郵件地址:

$ git config --global user.name "runoob"
$ git config --global user.email test@runoob.com

如果用了 --global 選項(xiàng),那么更改的配置文件就是位于你用戶主目錄下的那個(gè)窒朋,以后你所有的項(xiàng)目都會(huì)默認(rèn)使用這里配置的用戶信息搀罢。如果要在某個(gè)特定的項(xiàng)目中使用其他名字或者電郵,只要去掉 --global 選項(xiàng)重新配置即可侥猩,新的設(shè)定保存在當(dāng)前項(xiàng)目的 .git/config 文件里榔至。

文本編輯器

設(shè)置Git默認(rèn)使用的文本編輯器, 一般可能會(huì)是 Vi 或者 Vim。如果你有其他偏好欺劳,比如 Emacs 的話唧取,可以重新設(shè)置:

$ git config --global core.editor emacs

差異分析工具

還有一個(gè)比較常用的是,在解決合并沖突時(shí)使用哪種差異分析工具划提。比如要改用 vimdiff 的話:

$ git config --global merge.tool vimdiff

Git 可以理解 kdiff3枫弟,tkdiff,meld鹏往,xxdiff媒区,emerge,vimdiff掸犬,gvimdiff,ecmerge绪爸,和 opendiff 等合并工具的輸出信息湾碎。
當(dāng)然,你也可以指定使用自己開發(fā)的工具奠货,具體怎么做可以參閱第七章介褥。
查看配置信息
要檢查已有的配置信息,可以使用 git config --list 命令:

$ git config --list
http.postbuffer=2M
user.name=runoob
user.email=test@runoob.com

有時(shí)候會(huì)看到重復(fù)的變量名递惋,那就說明它們來自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig)柔滔,不過最終 Git 實(shí)際采用的是最后一個(gè)。
這些配置我們也可以在 ~/.gitconfig 或 /etc/gitconfig 看到萍虽,如下所示:

vim ~/.gitconfig 

顯示內(nèi)容如下所示:

[http]
    postBuffer = 2M
[user]
    name = runoob
    email = test@runoob.com

也可以直接查閱某個(gè)環(huán)境變量的設(shè)定睛廊,只要把特定的名字跟在后面即可,像這樣:

$ git config user.name
runoff

Git 創(chuàng)建倉庫

git init

Git 使用 git init 命令來初始化一個(gè) Git 倉庫杉编,Git 的很多命令都需要在 Git 的倉庫中運(yùn)行超全,所以 git init 是使用 Git 的第一個(gè)命令。在執(zhí)行完成 git init 命令后邓馒,Git 倉庫會(huì)生成一個(gè) .git 目錄嘶朱,該目錄包含了資源的所有元數(shù)據(jù),其他的項(xiàng)目目錄保持不變(不像 SVN 會(huì)在每個(gè)子目錄生成 .svn 目錄光酣,Git 只在倉庫的根目錄生成 .git 目錄)疏遏。

使用方法

使用當(dāng)前目錄作為Git倉庫,我們只需使它初始化。

git init

該命令執(zhí)行完后會(huì)在當(dāng)期目錄生成一個(gè) .git 目錄财异。
使用我們指定目錄作為Git倉庫倘零。

git init newrepo

初始化后,會(huì)在 newrepo 目錄下會(huì)出現(xiàn)一個(gè)名為 .git 的目錄宝当,所有 Git 需要的數(shù)據(jù)和資源都存放在這個(gè)目錄中视事。
如果當(dāng)前目錄下有幾個(gè)文件想要納入版本控制,需要先用 git add 命令告訴 Git 開始對這些文件進(jìn)行跟蹤庆揩,然后提交:

$ git add *.c
$ git add README
$ git commit -m '初始化項(xiàng)目版本'

以上命令將目錄下以 .c 結(jié)尾及 README 文件提交到倉庫中俐东。

git clone

我們使用 git clone 從現(xiàn)有 Git 倉庫中拷貝項(xiàng)目(類似 svn checkout)。
克隆倉庫的命令格式為:

git clone <repo>

如果我們需要克隆到指定的目錄订晌,可以使用以下命令格式:

git clone <repo> <directory>

參數(shù)說明:

  • repo:Git 倉庫虏辫。
  • directory:本地目錄。
    比如锈拨,要克隆 Ruby 語言的 Git 代碼倉庫 Grit砌庄,可以用下面的命令:
$ git clone git://github.com/schacon/grit.git

執(zhí)行該命令后,會(huì)在當(dāng)前目錄下創(chuàng)建一個(gè)名為grit的目錄奕枢,其中包含一個(gè) .git 的目錄娄昆,用于保存下載下來的所有版本記錄。
如果要自己定義要新建的項(xiàng)目目錄名稱缝彬,可以在上面的命令末尾指定新的名字:

$ git clone git://github.com/schacon/grit.git mygrit

Git 基本操作

基本快照

Git 的工作就是創(chuàng)建和保存你的項(xiàng)目的快照及與之后的快照進(jìn)行對比萌焰。本章將對有關(guān)創(chuàng)建與提交你的項(xiàng)目的快照的命令作介紹。
git add
git add 命令可將該文件添加到緩存谷浅,如我們添加以下兩個(gè)文件:

$ touch README
$ touch hello.php
$ ls
README      hello.php
$ git status -s
?? README
?? hello.php
$ 

git status 命令用于查看項(xiàng)目的當(dāng)前狀態(tài)扒俯。
接下來我們執(zhí)行 git add 命令來添加文件:

$ git add README hello.php 

現(xiàn)在我們再執(zhí)行 git status,就可以看到這兩個(gè)文件已經(jīng)加上去了一疯。

$ git status -s
A  README
A  hello.php
$ 

新項(xiàng)目中撼玄,添加所有文件很普遍,我們可以使用 git add . 命令來添加當(dāng)前項(xiàng)目的所有文件墩邀。
現(xiàn)在我們修改 README 文件:

$ vim README
<pre>
<p>在 README 添加以下內(nèi)容:<b>#Git 測試</b>掌猛,然后保存退出。</p>
<p>再執(zhí)行一下 git status:</p>
$ git status -s
AM README
A  hello.php

"AM" 狀態(tài)的意思是眉睹,這個(gè)文件在我們將它添加到緩存之后又有改動(dòng)留潦。改動(dòng)后我們在執(zhí)行 git add 命令將其添加到緩存中:

$ git add *
$ git status -s
A  README
A  hello.php

當(dāng)你要將你的修改包含在即將提交的快照里的時(shí)候,需要執(zhí)行 git add辣往。

git status

git status 以查看在你上次提交之后是否有修改兔院。
我演示該命令的時(shí)候加了 -s 參數(shù),以獲得簡短的結(jié)果輸出站削。如果沒加該參數(shù)會(huì)詳細(xì)輸出內(nèi)容:

$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   README
    new file:   hello.php

git diff

執(zhí)行 git diff 來查看執(zhí)行 git status 的結(jié)果的詳細(xì)信息坊萝。
git diff 命令顯示已寫入緩存與已修改但尚未寫入緩存的改動(dòng)的區(qū)別。git diff 有兩個(gè)主要的應(yīng)用場景。

  • 尚未緩存的改動(dòng):git diff
  • 查看已緩存的改動(dòng): git diff --cached
  • 查看已緩存的與未緩存的所有改動(dòng):git diff HEAD
  • 顯示摘要而非整個(gè) diff:git diff --stat

在 hello.php 文件中輸入以下內(nèi)容:

<?php
echo 'Hello World!';
?>
$ git status -s
A  README
AM hello.php
$ git diff
diff --git a/hello.php b/hello.php
index e69de29..69b5711 100644
--- a/hello.php
+++ b/hello.php
@@ -0,0 +1,3 @@
+<?php
+echo 'Hello World!';
+?>

git status 顯示你上次提交更新后的更改或者寫入緩存的改動(dòng)十偶, 而 git diff 一行一行地顯示這些改動(dòng)具體是啥菩鲜。
接下來我們來查看下 git diff --cached 的執(zhí)行效果:

$ git add hello.php 
$ git status -s
A  README
A  hello.php
$ git diff --cached
diff --git a/README b/README
new file mode 100644
index 0000000..8f87495
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+# Runoob Git 測試
diff --git a/hello.php b/hello.php
new file mode 100644
index 0000000..69b5711
--- /dev/null
+++ b/hello.php
@@ -0,0 +1,3 @@
+<?php
+echo 'Hello World!';
+?>

git commit

使用 git add 命令將想要快照的內(nèi)容寫入緩存區(qū), 而執(zhí)行 git commit 將緩存區(qū)內(nèi)容添加到倉庫中惦积。
Git 為你的每一個(gè)提交都記錄你的名字與電子郵箱地址接校,所以第一步需要配置用戶名和郵箱地址。

$ git config --global user.name 'runoob'
$ git config --global user.email test@runoob.com

接下來我們寫入緩存狮崩,并提交對 hello.php 的所有改動(dòng)蛛勉。在首個(gè)例子中,我們使用 -m 選項(xiàng)以在命令行中提供提交注釋睦柴。

$ git add hello.php
$ git status -s
A  README
A  hello.php
$ $ git commit -m '第一次版本提交'
[master (root-commit) d32cf1f] 第一次版本提交
 2 files changed, 4 insertions(+)
 create mode 100644 README
 create mode 100644 hello.php

現(xiàn)在我們已經(jīng)記錄了快照诽凌。如果我們再執(zhí)行 git status:

$ git status
# On branch master
nothing to commit (working directory clean)

以上輸出說明我們在最近一次提交之后,沒有做任何改動(dòng)坦敌,是一個(gè)"working directory clean:干凈的工作目錄"侣诵。
如果你沒有設(shè)置 -m 選項(xiàng),Git 會(huì)嘗試為你打開一個(gè)編輯器以填寫提交信息狱窘。 如果 Git 在你對它的配置中找不到相關(guān)信息杜顺,默認(rèn)會(huì)打開 vim。屏幕會(huì)像這樣:

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   hello.php
#
~
~
".git/COMMIT_EDITMSG" 9L, 257C

如果你覺得 git add 提交緩存的流程太過繁瑣蘸炸,Git 也允許你用 -a 選項(xiàng)跳過這一步哑舒。命令格式如下:

git commit -a

我們先修改 hello.php 文件為以下內(nèi)容:

<?php
echo 'Hello World!';
echo 'Hello World!';
?>

再執(zhí)行以下命令:

git commit -am '修改 hello.php 文件'
[master 71ee2cb] 修改 hello.php 文件
 1 file changed, 1 insertion(+)

git reset HEAD

git reset HEAD 命令用于取消已緩存的內(nèi)容。
我們先改動(dòng)文件 README 文件幻馁,內(nèi)容如下:

# Git 測試
# Git教程

hello.php 文件修改為:

<?php
echo 'Hello World!';
echo 'Hello World!';
echo 'Hello World!';
?>

現(xiàn)在兩個(gè)文件修改后,都提交到了緩存區(qū)越锈,我們現(xiàn)在要取消其中一個(gè)的緩存仗嗦,操作如下:

$ git status -s
 M README
 M hello.php
$ git add .
$ git status -s
M  README
M  hello.pp
$ git reset HEAD -- hello.php 
Unstaged changes after reset:
M   hello.php
$ git status -s
M  README
 M hello.php

現(xiàn)在你執(zhí)行 git commit,只會(huì)將 README 文件的改動(dòng)提交甘凭,而 hello.php 是沒有的稀拐。

$ git commit -m '修改'
[master f50cfda] 修改
 1 file changed, 1 insertion(+)
$ git status -s
 M hello.php

可以看到 hello.php 文件的修改并為提交。
這時(shí)我們可以使用以下命令將 hello.php 的修改提交:

$ git commit -am '修改 hello.php 文件'
[master 760f74d] 修改 hello.php 文件
 1 file changed, 1 insertion(+)
$ git status
On branch master
nothing to commit, working directory clean

簡而言之丹弱,執(zhí)行 git reset HEAD 以取消之前 git add 添加德撬,但不希望包含在下一提交快照中的緩存。

git rm

git rm 會(huì)將條目從緩存區(qū)中移除躲胳。這與 git reset HEAD 將條目取消緩存是有區(qū)別的蜓洪。 "取消緩存"的意思就是將緩存區(qū)恢復(fù)為我們做出修改之前的樣子。
默認(rèn)情況下坯苹,git rm file 會(huì)將文件從緩存區(qū)和你的硬盤中(工作目錄)刪除隆檀。
如果你要在工作目錄中留著該文件,可以使用 git rm --cached:
如我們刪除 hello.php文件:

$ git rm hello.php 
rm 'hello.php'
$ ls
README

不從工作區(qū)中刪除文件:

$ git rm --cached README 
rm 'README'
$ ls
README

git mv
git mv 命令做得所有事情就是 git rm --cached 命令的操作, 重命名磁盤上的文件恐仑,然后再執(zhí)行 git add 把新文件添加到緩存區(qū)泉坐。
我們先把剛移除的 README 添加回來:

$ git add README

然后對其重名:

$ git mv README  README.md
$ ls
README.md

Git 分支管理

幾乎每一種版本控制系統(tǒng)都以某種形式支持分支。使用分支意味著你可以從開發(fā)主線上分離開來裳仆,然后在不影響主線的同時(shí)繼續(xù)工作腕让。
有人把 Git 的分支模型稱為"必殺技特性",而正是因?yàn)樗缯澹瑢?Git 從版本控制系統(tǒng)家族里區(qū)分出來纯丸。
創(chuàng)建分支命令:

git branch (branchname)

切換分支命令:

git checkout (branchname)

當(dāng)你切換分支的時(shí)候,Git 會(huì)用該分支的最后提交的快照替換你的工作目錄的內(nèi)容构捡, 所以多個(gè)分支不需要多個(gè)目錄液南。
合并分支命令:

git merge

你可以多次合并到統(tǒng)一分支, 也可以選擇在合并之后直接刪除被并入的分支勾徽。

Git 分支管理

列出分支
列出分支基本命令:

git branch

沒有參數(shù)時(shí)滑凉,git branch 會(huì)列出你在本地的分支。

$ git branch
* master

此例的意思就是喘帚,我們有一個(gè)叫做"master"的分支畅姊,并且該分支是當(dāng)前分支。
當(dāng)你執(zhí)行 git init 的時(shí)候吹由,缺省情況下 Git 就會(huì)為你創(chuàng)建"master"分支若未。
如果我們要手動(dòng)創(chuàng)建一個(gè)分支,并切換過去倾鲫。執(zhí)行 git branch (branchname) 即可粗合。

$ git branch testing
$ git branch
* master
  testing

現(xiàn)在我們可以看到,有了一個(gè)新分支 testing乌昔。
當(dāng)你以此方式在上次提交更新之后創(chuàng)建了新分支隙疚,如果后來又有更新提交, 然后又切換到了"testing"分支磕道,Git 將還原你的工作目錄到你創(chuàng)建分支時(shí)候的樣子
接下來我們將演示如何切換分支供屉,我們用 git checkout (branch) 切換到我們要修改的分支。

$ ls
README
$ echo 'Hello World!' > test.txt
$ git add .
$ git commit -m 'add test.txt'
[master 048598f] add test.txt
 2 files changed, 1 insertion(+), 3 deletions(-)
 delete mode 100644 hello.php
 create mode 100644 test.txt
$ ls
README      test.txt
$ git checkout testing
Switched to branch 'testing'
$ ls
README      hello.php

當(dāng)我們切換到"testing"分支的時(shí)候溺蕉,我們添加的新文件test.txt被移除了, 原來被刪除的文件hello.php文件又出現(xiàn)了伶丐。切換回"master"分支的時(shí)候,它們有重新出現(xiàn)了疯特。

$ git checkout master
Switched to branch 'master'
$ ls
README      test.txt

我們也可以使用 git checkout -b (branchname) 命令來創(chuàng)建新分支并立即切換到該分支下哗魂,從而在該分支中操作。

$ git checkout -b newtest
Switched to a new branch 'newtest'
$ git rm test2.txt 
rm 'test2.txt'
$ ls
README      test.txt
$ git commit -am 'removed test2.txt'
[newtest 556f0a0] removed test2.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test2.txt
$ git checkout master
Switched to branch 'master'
$ ls
README      test.txt    test2.txt

如你所見漓雅,我們創(chuàng)建了一個(gè)分支啡彬,在該分支的上下文中移除了一些文件羹与,然后切換回我們的主分支,那些文件又回來了庶灿。
使用分支將工作切分開來纵搁,從而讓我們能夠在不同上下文中做事,并來回切換往踢。

刪除分支

刪除分支命令:

git branch -d (branchname)

例如我們要?jiǎng)h除"testing"分支:

$ git branch
* master
  testing
$ git branch -d testing
Deleted branch testing (was 85fc7e7).
$ git branch
* master

分支合并

一旦某分支有了獨(dú)立內(nèi)容腾誉,你終究會(huì)希望將它合并回到你的主分支。 你可以使用以下命令將任何分支合并到當(dāng)前分支中去:

git merge
$ git branch
* master
  newtest
$ ls
README      test.txt    test2.txt
$ git merge newtest
Updating 2e082b7..556f0a0
Fast-forward
 test2.txt | 1 -
 1 file changed, 1 deletion(-)
 delete mode 100644 test2.txt
$ ls
README      test.txt

以上實(shí)例中我們將 newtest 分支合并到主分支去峻呕,test2.txt 文件被刪除利职。

合并沖突

合并并不僅僅是簡單的文件添加、移除的操作瘦癌,Git 也會(huì)合并修改猪贪。

$ git branch
* master
$ cat test.txt
Hello World!

首先,我們創(chuàng)建一個(gè)叫做"change_site"的分支讯私,切換過去热押,我們將內(nèi)容改為"Hello Git!" 。

$ git checkout -b change_site
Switched to a new branch 'change_site'
$ vim test.txt 
$ head -1 test.txt 
Hello Git!
$ git commit -am 'changed the site'
[change_site d7e7346] changed the site
 1 file changed, 1 insertion(+), 1 deletion(-)

將修改的內(nèi)容提交到 "change_site" 分支中斤寇。 現(xiàn)在桶癣,假如切換回 "master" 分支我們可以看內(nèi)容恢復(fù)到我們修改前的,我們再次修改test.txt文件娘锁。

$ git checkout master
Switched to branch 'master'
$ head -1 test.txt 
Hello World!
$ vim test.txt 
$ cat test.txt
Hello World!
新增加一行
$ git diff
diff --git a/test.txt b/test.txt
index 704cce7..f84c2a4 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,2 @@
Hello World!
+新增加一行
$ git commit -am '新增加一行'
[master 14b4dca] 新增加一行
 1 file changed, 1 insertion(+)

現(xiàn)在這些改變已經(jīng)記錄到我的 "master" 分支了牙寞。接下來我們將 "change_site" 分支合并過來。

 $ git merge change_site
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
$ cat test.txt 
<<<<<<< HEAD
Hello World!
新增加一行
=======
Hello Git!
>>>>>>> change_site

我們將前一個(gè)分支合并到 "master" 分支莫秆,一個(gè)合并沖突就出現(xiàn)了间雀,接下來我們需要手動(dòng)去修改它。

$ vim test.txt 
$ cat test.txt 
Hello Git!
新增加一行
$ git diff
diff --cc test.txt
index f84c2a4,bccb7c2..0000000
--- a/test.txt
+++ b/test.txt
@@@ -1,2 -1,1 +1,2 @@@
- Hello Git!
+ Hello World!
 +新增加一行

在 Git 中镊屎,我們可以用 git add 要告訴 Git 文件沖突已經(jīng)解決

$ git status -s
UU test.txt
$ git add test.txt 
$ git status -s
M  test.txt
$ git commit
[master 88afe0e] Merge branch 'change_site'

現(xiàn)在我們成功解決了合并中的沖突惹挟,并提交了結(jié)果。

Git 查看提交歷史

在使用 Git 提交了若干更新之后杯道,又或者克隆了某個(gè)項(xiàng)目,想回顧下提交歷史责蝠,我們可以使用 git log 命令查看党巾。
針對我們前一章節(jié)的操作,使用 git log 命令列出歷史提交記錄如下:

$ git log
commit 88afe0e02adcdfea6844bb627de97da21eb10af1
Merge: 14b4dca d7e7346
Author: author
Date:   Sun Mar 1 15:03:42 2015 +0800

    Merge branch 'change_site'
    
    Conflicts:
        test.txt

commit 14b4dcadbdc847207651d5a9fae0d315057f346e
Author: author
Date:   Sun Mar 1 14:53:15 2015 +0800

    新增加一行

commit d7e734640da06055e107eaf29cf350b3f1de1c2c
Author: author
Date:   Sun Mar 1 14:48:57 2015 +0800

    changed the site

commit 556f0a0637978097b82287ac665a717623b21f3f
Author: author
Date:   Sun Mar 1 14:40:34 2015 +0800

    removed test2.txt

我們可以用 --oneline 選項(xiàng)來查看歷史記錄的簡潔的版本霜医。

$ git log --oneline
88afe0e Merge branch 'change_site'
14b4dca 新增加一行
d7e7346 changed the site
556f0a0 removed test2.txt
2e082b7 add test2.txt
048598f add test.txt
85fc7e7 test comment from Hello World!

這告訴我們的是齿拂,此項(xiàng)目的開發(fā)歷史。
我們還可以用 --graph 選項(xiàng)肴敛,查看歷史中什么時(shí)候出現(xiàn)了分支署海、合并吗购。以下為相同的命令,開啟了拓?fù)鋱D選項(xiàng):

$ git log --oneline --graph
*   88afe0e Merge branch 'change_site'
|\  
| * d7e7346 changed the site
* | 14b4dca 新增加一行
|/  
* 556f0a0 removed test2.txt
* 2e082b7 add test2.txt
* 048598f add test.txt
* 85fc7e7 test comment from Hello World!

現(xiàn)在我們可以更清楚明了地看到何時(shí)工作分叉砸狞、又何時(shí)歸并捻勉。
你也可以用 '--reverse'參數(shù)來逆向顯示所有日志。

$ git log --reverse --oneline
85fc7e7 test comment from Hello World!
048598f add test.txt
2e082b7 add test2.txt
556f0a0 removed test2.txt
d7e7346 changed the site
14b4dca 新增加一行
88afe0e Merge branch 'change_site'

如果只想查找指定用戶的提交日志可以使用命令:git log --author , 例如刀森,比方說我們要找 Git 源碼中 Linus 提交的部分:

$ git log --author=Linus --oneline -5
81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory
3bb7256 make "index-pack" a built-in
377d027 make "git pack-redundant" a built-in
b532581 make "git unpack-file" a built-in
112dd51 make "mktag" a built-in

如果你要指定日期踱启,可以執(zhí)行幾個(gè)選項(xiàng):--since 和 --before,但是你也可以用 --until 和 --after研底。
例如埠偿,如果我要看 Git 項(xiàng)目中三周前且在四月十八日之后的所有提交,我可以執(zhí)行這個(gè)(我還用了 --no-merges 選項(xiàng)以隱藏合并提交):

$ git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges
5469e2d Git 1.7.1-rc2
d43427d Documentation/remote-helpers: Fix typos and improve language
272a36b Fixup: Second argument may be any arbitrary string
b6c8d2d Documentation/remote-helpers: Add invocation section
5ce4f4e Documentation/urls: Rewrite to accomodate transport::address
00b84e9 Documentation/remote-helpers: Rewrite description
03aa87e Documentation: Describe other situations where -z affects git diff
77bc694 rebase-interactive: silence warning when no commits rewritten
636db2c t3301: add tests to use --format="%N"

更多 git log 命令可查看:http://git-scm.com/docs/git-log

Git 標(biāo)簽

如果你達(dá)到一個(gè)重要的階段榜晦,并希望永遠(yuǎn)記住那個(gè)特別的提交快照冠蒋,你可以使用 git tag 給它打上標(biāo)簽。
比如說乾胶,我們想為我們的 w3cschoolcc 項(xiàng)目發(fā)布一個(gè)"1.0"版本抖剿。 我們可以用 git tag -a v1.0 命令給最新一次提交打上(HEAD)"v1.0"的標(biāo)簽。
-a 選項(xiàng)意為"創(chuàng)建一個(gè)帶注解的標(biāo)簽"胚吁。 不用 -a 選項(xiàng)也可以執(zhí)行的牙躺,但它不會(huì)記錄這標(biāo)簽是啥時(shí)候打的,誰打的腕扶,也不會(huì)讓你添加個(gè)標(biāo)簽的注解孽拷。 我推薦一直創(chuàng)建帶注解的標(biāo)簽。

$ git tag -a v1.0 

當(dāng)你執(zhí)行 git tag -a 命令時(shí)半抱,Git 會(huì)打開你的編輯器脓恕,讓你寫一句標(biāo)簽注解,就像你給提交寫注解一樣窿侈。
現(xiàn)在炼幔,注意當(dāng)我們執(zhí)行 git log --decorate 時(shí),我們可以看到我們的標(biāo)簽了:

$ git log --oneline --decorate --graph
*   88afe0e (HEAD, tag: v1.0, master) Merge branch 'change_site'
|\  
| * d7e7346 (change_site) changed the site
* | 14b4dca 新增加一行
|/  
* 556f0a0 removed test2.txt
* 2e082b7 add test2.txt
* 048598f add test.txt
* 85fc7e7 test comment from Hello World!

如果我們忘了給某個(gè)提交打標(biāo)簽史简,又將它發(fā)布了乃秀,我們可以給它追加標(biāo)簽。
例如圆兵,假設(shè)我們發(fā)布了提交 85fc7e7(上面實(shí)例最后一行)跺讯,但是那時(shí)候忘了給它打標(biāo)簽。 我們現(xiàn)在也可以:

$ git tag -a v0.9 85fc7e7
$ git log --oneline --decorate --graph
*   88afe0e (HEAD, tag: v1.0, master) Merge branch 'change_site'
|\  
| * d7e7346 (change_site) changed the site
* | 14b4dca 新增加一行
|/  
* 556f0a0 removed test2.txt
* 2e082b7 add test2.txt
* 048598f add test.txt
* 85fc7e7 (tag: v0.9) test comment from Hello World!

如果我們要查看所有標(biāo)簽可以使用以下命令:

$ git tag
v0.9
v1.0

指定標(biāo)簽信息命令:

git tag -a <tagname> -m "Hello World!標(biāo)簽"

PGP簽名標(biāo)簽命令:

git tag -s <tagname> -m "Hello World!標(biāo)簽"

Git 遠(yuǎn)程倉庫

該文使用了 Github 作為遠(yuǎn)程倉庫殉农,Github創(chuàng)建遠(yuǎn)程倉庫的做法可以直接百度刀脏,這里就不贅述了。

添加遠(yuǎn)程庫

要添加一個(gè)新的遠(yuǎn)程倉庫超凳,可以指定一個(gè)簡單的名字愈污,以便將來引用,命令格式如下:

git remote add [shortname] [url]

由于你的本地Git倉庫和GitHub倉庫之間的傳輸是通過SSH加密的耀态,所以我們需要配置驗(yàn)證信息:
使用以下命令生成SSH Key:

$ ssh-keygen -t rsa -C "youremail@example.com"

后面的your_email@youremail.com改為你在github上注冊的郵箱允懂,之后會(huì)要求確認(rèn)路徑和輸入密碼饼拍,我們這使用默認(rèn)的一路回車就行。成功的話會(huì)在~/下生成.ssh文件夾兰吟,進(jìn)去擎析,打開id_rsa.pub簿盅,復(fù)制里面的key∽峄辏回到github上桨醋,進(jìn)入 Account Settings(賬戶配置),左邊選擇SSH Keys现斋,Add SSH Key,title隨便填喜最,粘貼在你電腦上生成的key。

為了驗(yàn)證是否成功庄蹋,輸入以下命令:

$ ssh -T git@github.com
You've successfully authenticated, but GitHub does not provide shell access.

以下命令說明我們已成功連上 Github瞬内。

查看當(dāng)前的遠(yuǎn)程庫

要查看當(dāng)前配置有哪些遠(yuǎn)程倉庫,可以用命令:

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

執(zhí)行時(shí)加上 -v 參數(shù)限书,你還可以看到每個(gè)別名的實(shí)際鏈接地址虫蝶。

提取遠(yuǎn)程倉庫

Git 有兩個(gè)命令用來提取遠(yuǎn)程倉庫的更新。
1倦西、從遠(yuǎn)程倉庫下載新分支與數(shù)據(jù):

git fetch

該命令執(zhí)行完后需要執(zhí)行g(shù)it merge 遠(yuǎn)程分支到你所在的分支能真。
2、從遠(yuǎn)端倉庫提取數(shù)據(jù)并嘗試合并到當(dāng)前分支:

git pull

該命令就是在執(zhí)行 git fetch 之后緊接著執(zhí)行 git merge 遠(yuǎn)程分支到你所在的任意分支扰柠。
假設(shè)你配置好了一個(gè)遠(yuǎn)程倉庫粉铐,并且你想要提取更新的數(shù)據(jù),你可以首先執(zhí)行 git fetch [alias] 告訴 Git 去獲取它有你沒有的數(shù)據(jù)卤档,然后你可以執(zhí)行 git merge [alias]/[branch] 以將服務(wù)器上的任何更新(假設(shè)有人這時(shí)候推送到服務(wù)器了)合并到你的當(dāng)前分支蝙泼。
接下來我們在 Github 上點(diǎn)擊"README" 并在線修改它。之后我們在本地更新修改劝枣。

$ git fetch origin
Warning: Permanently added the RSA host key for IP address '192.30.252.128' to the list of known hosts.
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:Wanlima/test
   7d2081c..f5f3dd5  master     -> origin/master

以上信息"7d2081c..f5f3dd5 master -> origin/master" 說明 master 分支已被更新汤踏,我們可以使用以下命令將更新同步到本地:

$ git merge origin/master
Updating 7d2081c..f5f3dd5
Fast-forward
 "README\350\217\234\351\270\237\346\225\231\347\250\213\346\265\213\350\257\225.md" | 1 +
 1 file changed, 1 insertion(+)

推送到遠(yuǎn)程倉庫

推送你的新分支與數(shù)據(jù)到某個(gè)遠(yuǎn)端倉庫命令:

git push [alias] [branch]

以上命令將你的 [branch] 分支推送成為 [alias] 遠(yuǎn)程倉庫上的 [branch] 分支,實(shí)例如下舔腾。

$ git merge origin/master
Updating 7d2081c..f5f3dd5
Fast-forward
 "README\350\217\234\351\270\237\346\225\231\347\250\213\346\265\213\350\257\225.md" | 1 +
 1 file changed, 1 insertion(+)
boon:test Wanlima$ vim README.md
boon:test Wanlima $ git push origin master
Everything up-to-date

刪除遠(yuǎn)程倉庫

刪除遠(yuǎn)程倉庫你可以使用命令:

git remote rm [別名]
$ git remote -v
origin  git@github.com:Wanlima/test.git (fetch)
origin  git@github.com:Wanlima/test.git (push)
$ git remote add origin2 git@github.com:Wanlima/test.git
$ git remote -v
origin  git@github.com:Wanlima/test.git (fetch)
origin  git@github.com:Wanlima/test.git (push)
origin2 git@github.com:Wanlima/test.git (fetch)
origin2 git@github.com:Wanlima/test.git (push)
$ git remote rm origin2
$ git remote -v
origin  git@github.com:Wanlima/test.git (fetch)
origin  git@github.com:Wanlima/test.git (push)

Git 服務(wù)器搭建

上一章節(jié)中我們遠(yuǎn)程倉庫使用了 Github溪胶,Github 公開的項(xiàng)目是免費(fèi)的,但是如果你不想讓其他人看到你的項(xiàng)目就需要收費(fèi)琢唾。
這時(shí)我們就需要自己搭建一臺Git服務(wù)器作為私有倉庫使用载荔。
接下來我們將以 Centos 為例搭建 Git 服務(wù)器盾饮。
1采桃、安裝Git

$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel
$ yum install git

接下來我們 創(chuàng)建一個(gè)git用戶組和用戶懒熙,用來運(yùn)行g(shù)it服務(wù):

$ groupadd git
$ adduser git -g git

2、創(chuàng)建證書登錄
收集所有需要登錄的用戶的公鑰普办,公鑰位于id_rsa.pub文件中工扎,把我們的公鑰導(dǎo)入到/home/git/.ssh/authorized_keys文件里,一行一個(gè)衔蹲。
如果沒有該文件創(chuàng)建它:

$ cd /home/git/
$ mkdir .ssh
$ chmod 700 .ssh
$ touch .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys

3肢娘、初始化Git倉庫
首先我們選定一個(gè)目錄作為Git倉庫,假定是/home/gitrepo/test.git舆驶,在/home/gitrepo目錄下輸入命令:

$ cd /home
$ mkdir gitrepo
$ chown git:git gitrepo/
$ cd gitrepo

$ git init --bare test.git
Initialized empty Git repository in /home/gitrepo/test.git/

以上命令Git創(chuàng)建一個(gè)空倉庫橱健,服務(wù)器上的Git倉庫通常都以.git結(jié)尾。然后沙廉,把倉庫所屬用戶改為git:
$ chown -R git:git test.git
4拘荡、克隆倉庫

$ git clone git@192.168.45.4:/home/gitrepo/test.git
Cloning into 'test'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

192.168.45.4 為 Git 所在服務(wù)器 ip ,你需要將其修改為你自己的 Git 服務(wù) ip撬陵。
這樣我們的 Git 服務(wù)器安裝就完成了珊皿,接下來我們可以禁用 git 用戶通過shell登錄,可以通過編輯/etc/passwd文件完成巨税。找到類似下面的一行:

git:x:503:503::/home/git:/bin/bash

改為:

git:x:503:503::/home/git:/sbin/nologin

如果我們想把Xcode工程項(xiàng)目托管到GitHub上面請參考:如何把項(xiàng)目托管到GitHub蟋定。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市草添,隨后出現(xiàn)的幾起案子驶兜,更是在濱河造成了極大的恐慌,老刑警劉巖果元,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件促王,死亡現(xiàn)場離奇詭異,居然都是意外死亡而晒,警方通過查閱死者的電腦和手機(jī)蝇狼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倡怎,“玉大人迅耘,你說我怎么就攤上這事〖嗍穑” “怎么了颤专?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長钠乏。 經(jīng)常有香客問我栖秕,道長,這世上最難降的妖魔是什么晓避? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任簇捍,我火速辦了婚禮只壳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘暑塑。我一直安慰自己吼句,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布事格。 她就那樣靜靜地躺著惕艳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪驹愚。 梳的紋絲不亂的頭發(fā)上远搪,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音逢捺,去河邊找鬼终娃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蒸甜,可吹牛的內(nèi)容都是我干的棠耕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柠新,長吁一口氣:“原來是場噩夢啊……” “哼窍荧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恨憎,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蕊退,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后憔恳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓤荔,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年钥组,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了输硝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡程梦,死狀恐怖点把,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情屿附,我是刑警寧澤郎逃,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站挺份,受9級特大地震影響褒翰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一优训、第九天 我趴在偏房一處隱蔽的房頂上張望错邦。 院中可真熱鬧,春花似錦型宙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至毛仪,卻和暖如春搁嗓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背箱靴。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工腺逛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人衡怀。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓棍矛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親抛杨。 傳聞我的和親對象是個(gè)殘疾皇子够委,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 這個(gè)是廣大網(wǎng)友評為最淺顯易懂Git教程的讀書筆記, 這個(gè)PDF文檔CSDN可以免積分下載.建議大家看看這個(gè)文檔,這...
    wg689閱讀 1,209評論 0 10
  • 今天是周末,接兒子幼兒園放學(xué)怖现,一家三口去飯店吃了一餐茁帽,很開心。 雖然中間某人為了帶兒子的方式的啥事的屈嗤,有些生我的氣...
    吳佟閱讀 240評論 0 4
  • 我25歲了潘拨,一個(gè)尷尬的年齡,愛情沒有收獲饶号,學(xué)業(yè)還在上一個(gè)普通學(xué)校的研究生铁追,家里的條件也不能給我提供什么,每次想起這...
    齊天大圣踏著祥云來了閱讀 672評論 1 0
  • 吵架 我想大多數(shù)的情侶都會(huì)碰到過 彼此越是喜歡 而越容易吵架 ? 明明知道是很小的一點(diǎn)事 卻到最后是那么的生氣 互...
    茗藝堂閱讀 208評論 0 0
  • Flex是Flexible Box的縮寫,意為"彈性布局"透硝,F(xiàn)lex布局將會(huì)是未來布局的首選方案狰闪,因?yàn)榉浅1憬荩?..
    荷小音閱讀 1,301評論 2 5