Git

創(chuàng)建一個(gè)版本庫

  創(chuàng)建一個(gè)版本庫:git init

  ( kwydwuf注: 新版 git 中應(yīng)該用 git init 容客,不要再用 init-db 命令领斥,具體可以通過命令 git help init 查看)

  可以了∶允兀現(xiàn)在我們來為本文的寫作創(chuàng)建一個(gè)版本庫:

  $ mkdir gittutorcn

  $ cd gittutorcn

  $ git init

  git 將會作出以下的回應(yīng)

  Initialized empty Git repository in /[yourpath]/.git

  這樣摘盆,一個(gè)空的版本庫就創(chuàng)建好了坝冕,并在當(dāng)前目錄中創(chuàng)建一個(gè)叫 .git 的子目錄欢峰。你可以用 ls -a 查看一下,并請注意其中的三項(xiàng)內(nèi)容:

  * 一個(gè)叫 HEAD 的文件坑夯,我們現(xiàn)在來查看一下它的內(nèi)容:

  $ cat .git/HEAD

  現(xiàn)在 HEAD 的內(nèi)容應(yīng)該是這樣:

  ref: refs/heads/master

  我們可以看到岖寞,HEAD 文件中的內(nèi)容其實(shí)只是包含了一個(gè)索引信息,并且柜蜈,這個(gè)索引將總是指向你的項(xiàng)目中的當(dāng)前開發(fā)分支仗谆。

  * 一個(gè)叫 objects 的子目錄,它包含了你的項(xiàng)目中的所有對象淑履,我們不必直接地了解到這些對象內(nèi)容隶垮,我們應(yīng)該關(guān)心是存放在這些對象中的項(xiàng)目的數(shù)據(jù)。

  Note

  關(guān)于 git 對象的分類秘噪,以及 git 對象數(shù)據(jù)庫的說明岁疼,請參看 [Discussion]

  * 一個(gè)叫 refs 的子目錄,它用來保存指向?qū)ο蟮乃饕?/p>

  具體地說缆娃,子目錄 refs 包含著兩個(gè)子目錄叫 heads 和 tags,就像他們的名字所表達(dá)的意味一樣:他們存放了不同的開發(fā)分支的頭的索引, 或者是你用來標(biāo)定版本的標(biāo)簽的索引瑰排。

  請注意:master 是默認(rèn)的分支贯要,這也是為什么 .git/HEAD 創(chuàng)建的時(shí)候就指向 master 的原因,盡管目前它其實(shí)并不存在椭住。 git 將假設(shè)你會在 master 上開始并展開你以后的工作崇渗,除非你自己創(chuàng)建你自己的分支。

  另外,這只是一個(gè)約定俗成的習(xí)慣而已宅广,實(shí)際上你可以將你的工作分支叫任何名字葫掉,而不必在版本庫中一定要有一個(gè)叫 master 的分支,盡管很多 git 工具都認(rèn)為 master 分支是存在的跟狱。

  現(xiàn)在已經(jīng)創(chuàng)建好了一個(gè) git 版本庫俭厚,但是它是空的,還不能做任何事情驶臊,下一步就是怎么向版本庫植入數(shù)據(jù)了挪挤。

植入內(nèi)容跟蹤信息

  植入內(nèi)容跟蹤信息:git add

  為了簡明起見,我們創(chuàng)建兩個(gè)文件作為練習(xí):

  $ echo "Hello world" > hello

  $ echo "Snake Zero" > snake

  我們再用 git add 命令將這兩個(gè)文件加入到版本庫文件索引當(dāng)中:

  $ git add hello snake

  git add 實(shí)際上是個(gè)腳本命令关翎,它是對 git 內(nèi)核命令 git update-index 的調(diào)用扛门。因此上面的命令和下面的命令其實(shí)是等價(jià)的:

  $ git update-index --add hello snake

  如果你要將某個(gè)文件從 git 的目錄跟蹤系統(tǒng)中清除出去,同樣可以用 git update-index 命令纵寝。例如:

  $ git update-index --force-remove foo.c

  Note

  git add 可以將某個(gè)目錄下的所有內(nèi)容全都納入內(nèi)容跟蹤之下论寨,例如: git add ./path/to/your/wanted 。但是在這樣做之前爽茴,應(yīng)該注意先將一些我們不希望跟蹤的文件清理掉葬凳,例如,gcc 編譯出來的 *.o 文件闹啦,vim 的交換文件 .*.swp 之類沮明。

  應(yīng)該建立一個(gè)清晰的概念就是,git add 和 git update-index 只是刷新了 git 的跟蹤信息窍奋,hello 和 snake 這兩個(gè)文件中的內(nèi)容并沒有提交到 git 的內(nèi)容跟蹤范疇之內(nèi)荐健。

  普通用戶總是應(yīng)該是用 git add, 而不要使用上面提到的 update-index 內(nèi)部命令琳袄。

提交內(nèi)容到版本庫

  提交內(nèi)容到版本庫:git commit

  既然我們刷新了 Git 的跟蹤信息江场,現(xiàn)在我們看看版本庫的狀態(tài):

  $ git status

  我們能看到 git 的狀態(tài)提示:

  #

  # Initial commit

  #

  #

  # Updated but not checked in:

  # (will commit)

  #

  # new file: example

  # new file: hello

  #

  提示信息告訴我們版本庫中加入了兩個(gè)新的文件,并且 git 提示我們提交這些文件窖逗,我們可以通過 git commit 命令來提交:

  $ git commit -m "Initial commit of gittutor reposistory"

  查看當(dāng)前的工作:git diff

  git diff 命令將比較當(dāng)前的工作目錄和版本庫數(shù)據(jù)庫中的差異≈贩瘢現(xiàn)在我們編輯一些文件來體驗(yàn)一下 git 的跟蹤功能。

  $ echo '這段是后來加的' > snake

  我們再來比較一下碎紊,當(dāng)前的工作目錄和版本庫中的數(shù)據(jù)的差別佑附。

  $ git diff

  差異將以典型的 patch 方式表示出來:

  diff --git a/snake b/snake

  index 3b85043..d79f20a 100644

  --- a/snake

  +++ b/snake

  @@ -1 +1 @@

  -snake zero

  +這段是后來加的

  此時(shí),我們可以再次使用組合命令 git add 和 git commit 將我們的工作提交到版本庫中仗考。

  $ git add snake

  $ git commit -m "new day for git"

  實(shí)際上音同,如果要提交的文件都是已經(jīng)納入 git 版本庫的文件,那么不必為這些文件都應(yīng)用 git add 命令之后再進(jìn)行提交秃嗜,下面的命令更簡捷并且和上面的命令是等價(jià)的权均。

  $ git commit -a -m "new day for git"

管理分支

  管理分支:git branch

  直至現(xiàn)在為止顿膨,我們的項(xiàng)目版本庫一直都是只有一個(gè)分支 master。在 git 版本庫中創(chuàng)建分支的成本幾乎為零叽赊,所以恋沃,不必吝嗇多創(chuàng)建幾個(gè)分支。下面列舉一些常見的分支策略必指,僅供大家參考:

  * 創(chuàng)建一個(gè)屬于自己的個(gè)人工作分支囊咏,以避免對主分支 master 造成太多的干擾,也方便與他人交流協(xié)作取劫。

  * 當(dāng)進(jìn)行高風(fēng)險(xiǎn)的工作時(shí)匆笤,創(chuàng)建一個(gè)試驗(yàn)性的分支,扔掉一個(gè)爛攤子總比收拾一個(gè)爛攤子好得多谱邪。

  * 合并別人的工作的時(shí)候炮捧,最好是創(chuàng)建一個(gè)臨時(shí)的分支,關(guān)于如何用臨時(shí)分支合并別人的工作的技巧惦银,將會在后面講述咆课。

創(chuàng)建分支

  下面的命令將創(chuàng)建我自己的工作分支,名叫 robin扯俱,并且將以后的工作轉(zhuǎn)移到這個(gè)分支上開展书蚪。

  $ git branch robin

  $ git checkout robin

  更簡單和常用的方法是直接通過 checkout 命令來一次性創(chuàng)建并轉(zhuǎn)移到新建分支上,命令如下:

  $ git checkout -b robin [start_point]

  其中 start_point 是一個(gè)可選參數(shù)迅栅,指定新建分支 robin 是基于哪個(gè)節(jié)點(diǎn)殊校,默認(rèn)為當(dāng)前所在分支的節(jié)點(diǎn)。

刪除分支

  要?jiǎng)h除版本庫中的某個(gè)分支读存,使用 git branch -d 命令就可以了为流,例如:

  $ git branch -d branch-name

  但是需要注意的是,如果刪除的分支還沒有被 merge 到其他分支让簿,刪除這樣的分支會導(dǎo)致這個(gè)分支上所做的改動(dòng)丟失敬察,因此 git branch -d 命令會失敗,提示你這樣做會丟失信息尔当。如果你的確想刪除這樣的分支莲祸,不怕信息丟失,那么可以使用 git branch -D 命令椭迎,這個(gè)命令不會去判斷分支的merge狀態(tài)锐帜,例如:

  $ git branch -D branch-name

  通常建議使用 -d 參數(shù)來刪除分支,以防無意的信息丟失畜号。

查看分支

  運(yùn)行下面的命令可以得到你當(dāng)前工作目錄的分支列表:

  $ git branch

  在你正在工作的分支的名字前面缴阎,會有 * 號標(biāo)示,比如:

  $ git branch

  bugfix

  * master

  說明有兩個(gè)本地分支 bugfix 和 master弄兜, 其中當(dāng)前的工作分支為 master药蜻。

  查看項(xiàng)目的發(fā)展變化和比較差異

  這一節(jié)介紹幾個(gè)查看項(xiàng)目的版本庫的發(fā)展變化以及比較差異的很有用的命令:

  git show-branch

  git diff

  git whatchanged

  我們現(xiàn)在為 robin, master 兩個(gè)分支都增加一些內(nèi)容。

  $ git checkout robin

  $ echo "Work, work, workd" >> hello

  $ git commit -m "Some workd" -i hello

  $ git checkout master

  $ echo "Play, play, play" >> hello

  $ echo "Lots of fun" >> example

  $ git commit -m "Some fun" -i hello example

  git show-branch 命令可以使我們看到版本庫中每個(gè)分支的世系發(fā)展?fàn)顟B(tài)替饿,并且可以看到每次提交的內(nèi)容是否已進(jìn)入每個(gè)分支语泽。

  $ git show-branch

  這個(gè)命令讓我們看到版本庫的發(fā)展記錄。

  * [master] Some fun

  ! [robin] some work

  --

  * [master] Some fun

  + [robin] some work

  *+ [master^] a new day for git

  譬如我們要查看世系標(biāo)號為 master^ 和 robin 的版本的差異情況视卢,我們可以使用這樣的命令:

  $ git diff master^ robin

  我們可以看到這兩個(gè)版本的差異:

  diff --git a/hello b/hello

  index 263414f..cc44c73 100644

  --- a/hello

  +++ b/hello

  @@ -1,2 +1,3 @@

  Hello World

  It's a new day for git

  +Work, work, work

  Note

  關(guān)于 GIT 版本世系編號的定義踱卵,請參看 git help rev-parse 。

  我們現(xiàn)在再用 git whatchanged 命令來看看 master 分支是怎么發(fā)展的据过。

  $ git checkout master

  $ git whatchanged

  diff-tree 1d2fa05... (from 3ecebc0...)

  Author: Vortune.Robin

  Date: Tue Mar 21 02:24:31 2006 +0800

  Some fun

  :100644 100644 f24c74a... 7f8b141... M example

  :100644 100644 263414f... 06fa6a2... M hello

  diff-tree 3ecebc0... (from 895f09a...)

  Author: Vortune.Robin

  Date: Tue Mar 21 02:17:23 2006 +0800

  a new day for git

  :100644 100644 557db03... 263414f... M hello

  從上面的內(nèi)容中我們可以看到惋砂,在 robin 分支中的日志為 "Some work" 的內(nèi)容, 并沒有在 master 分支中出現(xiàn)。

合并兩個(gè)分支

  合并兩個(gè)分支:git merge

  既然我們?yōu)轫?xiàng)目創(chuàng)建了不同的分支绳锅,那么我們就要經(jīng)常地將自己或者是別人在一個(gè)分支上的工作合并到其他的分支上去〔斗ⅲ現(xiàn)在我們看看怎么將 robin 分支上的工作合并到 master 分支中≈擅現(xiàn)在轉(zhuǎn)移我們當(dāng)前的工作分支到 master,并且將 robin 分支上的工作合并進(jìn)來。

  $ git checkout master

  $ git merge -m "Merge from robin" robin

  上面的命令會將 robin 分支的改動(dòng) merge 到 master窃植,并生成一個(gè)新的 commit 節(jié)點(diǎn),這個(gè) commit 的注釋信息為 "Merge from robin"

  (kwydwuf注: $ git merge "Merge work in robin" HEAD robin 是老版本的用法休雌,應(yīng)該廢棄 )

  合并兩個(gè)分支假瞬,還有一個(gè)更簡便的方式,下面的命令和上面的命令是等價(jià)的 (kwydwuf注:git pull 的本意是用來 merge 遠(yuǎn)端版本庫中的某個(gè)分支喳坠,用在此處沒有任何簡便之處鞠评,可以廢棄)。

  $ git checkout master

  $ git pull . robin

  但是壕鹉,此時(shí) git 會出現(xiàn)合并沖突提示:

  Trying really trivial in-index merge...

  fatal: Merge requires file-level merging

  Nope.

  Merging HEAD with d2659fcf690ec693c04c82b03202fc5530d50960

  Merging:

  1d2fa05b13b63e39f621d8ee911817df0662d9b7 Some fun

  d2659fcf690ec693c04c82b03202fc5530d50960 some work

  found 1 common ancestor(s):

  3ecebc0cb4894a33208dfa7c7c6fc8b5f9da0eda a new day for git

  Auto-merging hello

  CONFLICT (content): Merge conflict in hello

  Automatic merge failed; fix up by hand

  git 的提示指出剃幌,在合并作用于文件 hello 的 'Some fun' 和 'some work' 這兩個(gè)對象時(shí)有沖突,具體通俗點(diǎn)說御板,就是在 master, robin 這兩個(gè)分支中的 hello 文件的某些相同的行中的內(nèi)容不一樣锥忿。我們需要手動(dòng)解決這些沖突,現(xiàn)在先讓我們看看現(xiàn)在的 hello 文件中的內(nèi)容怠肋。

$ cat hello

  此時(shí)的 hello 文件應(yīng)是這樣的敬鬓,用過其他的版本控制系統(tǒng)的朋友應(yīng)該很容易看出這個(gè)典型的沖突表示格式:

  Hello World

  It's a new day for git

  <<<<<<< HEAD/hello

  Play, play, play

  =======

  Work, work, work

  >>>>>>> d2659fcf690ec693c04c82b03202fc5530d50960/hello

  我們用編輯器將 hello 文件改為:

  Hello World

  It's a new day for git

  Play, play, play

  Work, work, work

  現(xiàn)在可以將手動(dòng)解決了沖突的文件提交了。

  $ git commit -i hello

  以上是典型的兩路合并(2-way merge)算法笙各,絕大多數(shù)情況下已經(jīng)夠用钉答。但是還有更復(fù)雜的三路合并和多內(nèi)容樹合并的情況。詳情可參看: git help read-tree杈抢, git help merge 等文檔数尿。

逆轉(zhuǎn)與恢復(fù)

  逆轉(zhuǎn)與恢復(fù):git reset

  項(xiàng)目跟蹤工具的一個(gè)重要任務(wù)之一,就是使我們能夠隨時(shí)逆轉(zhuǎn)(Undo)和恢復(fù)(Redo)某一階段的工作惶楼。

  git reset 命令就是為這樣的任務(wù)準(zhǔn)備的右蹦。它將當(dāng)前的工作分支的 頭 定位到以前提交的任何版本中诊杆,它有三個(gè)重置的算法選項(xiàng)。

  命令形式:

  git reset [--mixed | --soft | --hard] [<commit-ish>]

  命令的選項(xiàng):

  --mixed

  僅是重置索引的位置何陆,而不改變你的工作樹中的任何東西(即晨汹,文件中的所有變化都會被保留,也不標(biāo)記他們?yōu)榇峤粻顟B(tài))贷盲,并且提示什么內(nèi)容還沒有被更新了淘这。這個(gè)是默認(rèn)的選項(xiàng)。

  --soft

  既不觸動(dòng)索引的位置巩剖,也不改變工作樹中的任何內(nèi)容铝穷,我們只是要求這些內(nèi)容成為一份好的內(nèi)容(之后才成為真正的提交內(nèi)容)。這個(gè)選項(xiàng)使你可以將已經(jīng)提交的東西重新逆轉(zhuǎn)至“已更新但未提交(Updated but not Check in)”的狀態(tài)佳魔。就像已經(jīng)執(zhí)行過 git update-index 命令曙聂,但是還沒有執(zhí)行 git commit 命令一樣。

  --hard

  將工作樹中的內(nèi)容和頭索引都切換至指定的版本位置中吃引,也就是說自 <commit-ish> 之后的所有的跟蹤內(nèi)容和工作樹中的內(nèi)容都會全部丟失筹陵。因此,這個(gè)選項(xiàng)要慎用镊尺,除非你已經(jīng)非常確定你的確不想再看到那些東西了朦佩。

  一個(gè)重要技巧--逆轉(zhuǎn)提交與恢復(fù)

使用技巧

  可能有人會問,--soft 選項(xiàng)既不重置頭索引的位置庐氮,也不改變工作樹中的內(nèi)容语稠,那么它有什么用呢?現(xiàn)在我們介紹一個(gè) --soft 選項(xiàng)的使用技巧弄砍。下面我們用例子來說明:

  $ git checkout master

  $ git checkout -b softreset

  $ git show-branch

  這里我們創(chuàng)建了一個(gè) master 的拷貝分支 softreset仙畦,現(xiàn)在我們可以看到兩個(gè)分支是在同一起跑線上的。

  ! [master] Merge branch 'robin'

  ! [robin] some work

  * [softreset] Merge branch 'robin'

  ---

  - - [master] Merge branch 'robin'

  + * [master^] Some fun

  ++* [robin] some work

  我們?yōu)?文件增加一些內(nèi)容并提交音婶。

  $ echo "Botch, botch, botch" >> hello

  $ git commit -a -m "some botch"

  $ git show-branch

  我們可以看到此時(shí) softreset 比 master 推進(jìn)了一個(gè)版本 "some botch" 慨畸。

  ! [master] Merge branch 'robin'

  ! [robin] some work

  * [softreset] some botch

  ---

  * [softreset] some botch

  - - [master] Merge branch 'robin'

  + * [master^] Some fun

  ++* [robin] some work

  現(xiàn)在讓我們來考慮這樣的一種情況,假如我們現(xiàn)在對剛剛提交的內(nèi)容不滿意衣式,那么我們再編輯項(xiàng)目的內(nèi)容寸士,再提交的話,那么 "some botch" 的內(nèi)容就會留在版本庫中了碴卧。我們當(dāng)然不希望將有明顯問題的內(nèi)容留在版本庫中弱卡,這個(gè)時(shí)候 --soft 選項(xiàng)就很有用了。為了深入了解 --soft 的機(jī)制住册,我們看看現(xiàn)在 softreset 分支的頭和 ORIG_HEAD 保存的索引婶博。

  $ cat .git/refs/heads/softreset .git/ORIG_HEAD

  結(jié)果如下:

  5e7cf906233e052bdca8c598cad2cb5478f9540a

  7bbd1370e2c667d955b6f6652bf8274efdc1fbd3

  現(xiàn)在用 --soft 選項(xiàng)逆轉(zhuǎn)剛才提交的內(nèi)容:

  git reset --soft HEAD^

  現(xiàn)在讓我們再看看 .git/ORIG_HEAD 的中保存了什么?

  $ cat .git/ORIG_HEAD

  結(jié)果如下:

  5e7cf906233e052bdca8c598cad2cb5478f9540a

  看荧飞!現(xiàn)在的 .git/ORIG_HEAD 等于逆轉(zhuǎn)前的 .git/refs/heads/softreset 凡人。也就是說名党,git reset --soft HEAD^ 命令逆轉(zhuǎn)了剛才提交的版本進(jìn)度,但是它將那次提交的對象的索引拷貝到了 .git/ORIG_HEAD 中挠轴。

  我們再編輯 hello 文件成為下面的內(nèi)容:

  Hello World

  It's a new day for git

  Play, play, play

  Work, work, work

  Nice, nice, nice

  我們甚至可以比較一下現(xiàn)在的工作樹中的內(nèi)容和被取消了的那次提交的內(nèi)容有什么差異:

  $ git diff ORIG_HEAD

  結(jié)果如下:

  diff --git a/hello b/hello

  index f978676..dd02c32 100644

  --- a/hello

  +++ b/hello

  @@ -2,4 +2,4 @@ Hello World

  It's a new day for git

  Play, play, play

  Work, work, work

  -Botch, botch, botch

  +Nice, nice, nice

  接著兑巾,我們可以恢復(fù)剛才被取消了的那次提交了。

  $ git commit -a -c ORIG_HEAD

  注意忠荞,這個(gè)命令會打開默認(rèn)的文本編輯器以編輯原來提交的版本日志信息,我們改為 "nice work" 帅掘。大家可以自行用 git show-branch 命令來查看一下現(xiàn)在的分支狀態(tài)委煤。并且我們還可以不斷地重復(fù)上述的步驟,一直修改到你對這個(gè)版本進(jìn)度滿意為止修档。

  git reset 命令還有很多的用途和技巧碧绞,請參考 git reset ,以及 Everyday GIT with 20 commands or So 吱窝。

提取版本庫中的數(shù)據(jù)

  這是個(gè)很有用的小技巧讥邻,如果你對你現(xiàn)在的工作目錄下的東西已經(jīng)不耐煩了,隨時(shí)可以取出你提交過的東西覆蓋掉當(dāng)前的文件院峡,譬如:

  $ git checkout -f foo.c

編輯本段標(biāo)定版本

兩種類型的標(biāo)簽

  在 git 中兴使,有兩種類型的標(biāo)簽,“輕標(biāo)簽”和“署名標(biāo)簽”照激。

  技術(shù)上說发魄,一個(gè)“輕標(biāo)簽”和一個(gè)分支沒有任何區(qū)別,只不過我們將它放在了 .git/refs/tags/ 目錄俩垃,而不是 heads 目錄励幼。因此,打一個(gè)“輕標(biāo)簽”再簡單不過了口柳。

  $ git-tag my-first-tag

  如果你打算針對某個(gè)commit ID來打標(biāo)簽苹粟,雖然該命令可以通過gitk里的右鍵菜單來實(shí)現(xiàn),但是該命令對實(shí)際應(yīng)用是很有幫助的跃闹。

  $ git-tag mytag f0af6283824688f9d23426031734657661b54388

  “署名標(biāo)簽”是一個(gè)真正的 git 對象嵌削,它不但包含指向你想標(biāo)記的狀態(tài)的指針,還有一個(gè)標(biāo)記名和信息辣卒,可選的 PGP 簽名掷贾。你可以通過 -a 或者是 -s 選項(xiàng)來創(chuàng)建“署名標(biāo)簽”。

  $ git-tag -s <tag-name>

合并外部工作

  通常的情況下荣茫,合并其他的人的工作的情況會比合并自己的分支的情況要多想帅,這在 git 中是非常容易的事情,和你運(yùn)行 git-merge 命令沒有什么區(qū)別啡莉。事實(shí)上港准,遠(yuǎn)程合并的無非就是“抓戎及(fetch)一個(gè)遠(yuǎn)程的版本庫中的工作到一個(gè)臨時(shí)的標(biāo)簽中”,然后再使用 git-merge 命令浅缸。

  可以通過下面的命令來抓取遠(yuǎn)程版本庫:

  $ git-fetch <remote-repository>

  根據(jù)不同的遠(yuǎn)程版本庫所使用的通訊協(xié)議的路徑來替代上面的 remoted-repository 就可以了轨帜。

  Rsync

  rsync://remote.machine/patch/to/repo.git/

  SSH

  remote.machine:/path/to/repo.git

  or

  ssh://remote.machine/patch/to/repo.git/

  這是可以上傳和下載的雙向傳輸協(xié)議,當(dāng)然衩椒,你要有通過 ssh 協(xié)議登錄遠(yuǎn)程機(jī)器的權(quán)限蚌父。它可以找出兩端的機(jī)器提交過的對象集之中相互缺少了那些對象,從而得到需要傳輸?shù)淖钚ο蠹取_@是最高效地交換兩個(gè)版本庫之間的對象的方式(在 git 兼容的所有傳輸協(xié)議當(dāng)中)苟弛。

  下面是個(gè)取得 SSH 遠(yuǎn)程版本庫的命令例子:

  $ git-fetch robin@192.168.1.168:/path/to/gittutorcn.git (1)

  (1) 這里 robin 是登錄的用戶名,192.168.1.168 是保存著主版本庫的機(jī)器的 IP 地址阁将。

  Local directory

  /path/to/repo.git/

  本地目錄的情況和 SSH 情況是一樣的膏秫。

  git Native

  git://remote.machine/path/to/repo.git/

  git 自然協(xié)議是設(shè)計(jì)來用于匿名下載的,它的工作方式類似于 SSH 協(xié)議的交換方式做盅。

  HTTP(S)

  http://remote.machine/path/to/repo.git/

  到這里可能有些朋友已經(jīng)想到缤削,實(shí)際上,我們可以通過 Rsync, SSH 之類的雙向傳輸方式來建立類似 CVS吹榴,SVN 這樣的中心版本庫模式的開發(fā)組織形式亭敢。

通過電子郵件交換工作

  讀過上一節(jié)之后,有的朋友可能要問图筹,如果版本庫是通過單向的下載協(xié)議發(fā)布的吨拗,如 HTTP,我們就無法將工作上傳到公共的版本庫中婿斥。別人也不能訪問我的機(jī)器來抓取我的工作劝篷,那怎么辦呢?

  不必?fù)?dān)心民宿,我們還有 email 娇妓!別忘了 git 本來就是為了管理 Linux 的內(nèi)核開發(fā)而設(shè)計(jì)的。所以活鹰,它非常適合像 Linux Kernel 這樣的開發(fā)組織形式高度分散哈恰,嚴(yán)重依賴 email 來進(jìn)行交流的項(xiàng)目。

  下面模擬你參加到《Git 中文教程》的編寫工作中來志群,看看我們可以怎么通過 email 進(jìn)行工作交流着绷。你可以通過下面的命令下載這個(gè)項(xiàng)目的版本庫。

  之后锌云,你會在當(dāng)前目錄下得到一個(gè)叫 gittutorcn 的目錄荠医,這就是你的項(xiàng)目的工作目錄了。默認(rèn)地,它會有兩個(gè)分支: master 和 origin彬向,你可以直接在 master 下展開工作兼贡,也可以創(chuàng)建你自己的工作分支,但是千萬不要修改 origin 分支娃胆,切記遍希!因?yàn)樗枪舶姹編斓?a target="_blank">鏡像,如果你修改了它里烦,那么就不能生成正確的對公共版本庫的 patch 文件了凿蒜。

  Note

  如果你的確修改過 origin 分支的內(nèi)容,那么在生成 patch 文件之前胁黑,請用 git-reset --hard 命令將它逆轉(zhuǎn)到最原始的篙程,沒經(jīng)過任何修改的狀態(tài)。

  你可以直接在 master 下開展工作别厘,也可以創(chuàng)建你自己的工作分支。當(dāng)你對項(xiàng)目做了一定的工作拥诡,并提交到庫中触趴。我們用 git-show-branch 命令先看下庫的狀態(tài)。

  * [master] your buddy's contribution

  ! [origin] degining of git-format-patch example

  --

  * [master] your buddy's contribution

  *+ [origin] degining of git-format-patch example

  上面就假設(shè)你已經(jīng)提交了一個(gè)叫 "your buddy's contribution" 的工作】嗜猓現(xiàn)在我們來看看怎么通過 email 來交流工作了冗懦。

  $ git-fetch origin (1)

  $ git-rebase origin (2)

  $ git-format-patch origin (3)

  (1)更新 origin 分支,防止 origin 分支不是最新的公共版本仇祭,產(chǎn)生錯(cuò)誤的補(bǔ)丁文件披蕉;

  (2)將你在 master 上提交的工作遷移到新的源版本庫的狀態(tài)的基礎(chǔ)上;

  (3)生成補(bǔ)丁文件乌奇;

  上面的幾個(gè)命令没讲,會在當(dāng)前目錄下生成一個(gè)大概名為 0001-your-buddy-s-contribution.txt 補(bǔ)丁文件, 建議你用文本工具查看一下這個(gè)文件的具體形式,然后將這個(gè)文件以附件的形式發(fā)送到項(xiàng)目維護(hù)者的郵箱

  當(dāng)項(xiàng)目的維護(hù)者收到你的郵件后礁苗,只需要用 git-am 命令爬凑,就可以將你的工作合并到項(xiàng)目中來。

  $ git-checkout -b buddy-incomming

  $ git-am /path/to/0001-your-buddy-s-contribution.txt

用 Git 協(xié)同工作

  假設(shè) Alice 在一部機(jī)器上自己的個(gè)人目錄中創(chuàng)建了一個(gè)項(xiàng)目 /home/alice/project, Bob 想在同一部機(jī)器自己的個(gè)人目錄中為這個(gè)項(xiàng)目做點(diǎn)什么试伙。

  Bob 首先這樣開始:

  $ git-clone /home/alice/project myrepo

  這樣就創(chuàng)建了一個(gè)保存著 Alice 的版本庫的鏡像的新目錄 "myrepo"嘁信。這個(gè)鏡像保存著原始項(xiàng)目的起點(diǎn)和它的發(fā)展歷程。

  接著 Bob 對項(xiàng)目做了些更改并提交了這些更改:

  (編輯一些文件)

  $ git-commit -a

  (如果需要的話再重復(fù)這個(gè)步驟)

  當(dāng)他搞定之后疏叨,他告訴 Alice 將他的東西從 /home/bob/myrepo 中引入潘靖,她只需要這樣:

  $ cd /home/alice/project

  $ git pull /home/bob/myrepo

  這樣就將 Bob 的版本庫中的 "master" 分支的變化引入了。 Alice 也可以通過在 pull 命令的后面加入?yún)?shù)的方式來引入其他的分支蚤蔓。

  在導(dǎo)入了 Bob 的工作之后卦溢,用 "git-whatchanged" 命令可以查看有什么信的提交對象。如果這段時(shí)間里以來,Alice 也對項(xiàng)目做過自己的修改既绕,當(dāng) Bob 的修改被合并進(jìn)來的時(shí)候啄刹,那么她需要手動(dòng)修復(fù)所有的合并沖突。

  謹(jǐn)慎的 Alice 在導(dǎo)入 Bob 的工作之前凄贩,希望先檢查一下誓军。那么她可以先將 Bob 的工作導(dǎo)入到一個(gè)新創(chuàng)建的臨時(shí)分支中,以方便研究 Bob 的工作:

  $ git fetch /home/bob/myrepo master:bob-incoming

  這個(gè)命令將 Bob 的 master 分支的導(dǎo)入到名為 bob-incoming 的分支中(不同于 git-pull 命令疲扎,git-fetch 命令只是取得 Bob 的開發(fā)工作的拷貝昵时,而不是合并經(jīng)來)。接著:

  $ git whatchanged -p master..bob-incoming

  這會列出 Bob 自取得 Alice 的 master 分支之后開始工作的所有變化椒丧。檢查過這些工作壹甥,并做過必須的調(diào)整之后, Alice 就可以將變化導(dǎo)入到她的 master 分支中:

  $ git-checkout master

  $git-pull . bob-incoming

  最后的命令就是將 "bob-incoming" 分支的東西導(dǎo)入到 Alice 自己的版本庫中的壶熏,稍后句柠,Bob 就可以通過下面的命令同步 Alice 的最新變化。

  $ git-pull

  注意不需為這個(gè)命令加入 Alice 的版本庫的路徑棒假,因?yàn)楫?dāng) Bob 克隆 Alice 的版本庫的時(shí)候溯职, git 已經(jīng)將這個(gè)路徑保存到 .git/remote/origin 文件中,它將會是所以的導(dǎo)入操作的默認(rèn)路徑帽哑。

  Bob 可能已經(jīng)注意到他并沒有在他的版本庫中創(chuàng)建過分支(但是分支已經(jīng)存在了):

  $ git branch

  * master

  origin

  "origin" 分支谜酒,它是運(yùn)行 "git-clone" 的時(shí)候自動(dòng)創(chuàng)建的,他是 Alice 的 master 分支的原始鏡像妻枕, Bob 應(yīng)該永遠(yuǎn)不要向這個(gè)分支提交任何東西僻族。

  如果 Bob 以后決定在另外一部主機(jī)上開展工作,那么他仍然需要通過 SSH 協(xié)議從新克隆和導(dǎo)入( Alice 的版本庫):

  我們可以使用 git 自然協(xié)議屡谐,或者是 rsync, http 等協(xié)議的任何一種述么,詳情請參考 git-pull。

  Git 同樣可以建立類似 CVS 那樣的開發(fā)模式愕掏,也就是所有開發(fā)者都向中心版本庫提交工作的方式碉输,詳情參考 git_push 和 git for CVS users 。

為版本庫打包

  在前面亭珍,我們已經(jīng)看到在 .git/objects/??/ 目錄中保存著我們創(chuàng)建的每一個(gè) git 對象敷钾。這樣的方式對于自動(dòng)和安全地創(chuàng)建對象很有效,但是對于網(wǎng)絡(luò)傳輸則不方便肄梨。 git 對象一旦創(chuàng)建了阻荒,就不能被改變,但有一個(gè)方法可以優(yōu)化對象的存儲众羡,就是將他們“打包到一起”侨赡。

  $ git repack

  上面的命令讓你做到這點(diǎn),如果你一直是做著我們的例子過來的,你現(xiàn)在大約會在 .git/objects/??/ 目錄下積累了17個(gè)對象羊壹。 git-repack 會告訴你有幾個(gè)對象被打包了蓖宦,并且將他們保存在 .git/objects/pack 目錄當(dāng)中。

  Note

  你將會看到兩個(gè)文件油猫,pack-*.pack and pack-*.idx 在 .git/objects/pack 目錄稠茂。他們的關(guān)系是很密切的,如果你手動(dòng)將他們拷貝到別的版本庫中的話情妖,你要決定將他們一起拷貝睬关。前者是保存著所有被打包的數(shù)據(jù)的文件,后者是隨機(jī)訪問的索引毡证。

  如果你是個(gè)偏執(zhí)狂电爹,就運(yùn)行一下 git-verity-pack 命令來檢查一下有缺陷的包吧,不過料睛,其實(shí)你無須太多擔(dān)心丐箩,我們的程序非常出色 ;-).

  一旦你已經(jīng)對那些對象打包了,那么那些已經(jīng)被打過包的原始的對象恤煞,就沒有必要保留了屎勘。

  $ git prune-packed

  會幫你清楚他們。

  如果你好奇的話阱州,你可以在執(zhí)行 git-prune-repacked 命令之前和之后,都運(yùn)行一下 find .git/objects -type f法梯,這樣你就能看到有多少沒有打包的對象苔货,以及節(jié)省了多少磁盤空間。

  git pull git-pull 對于 HTTP 傳輸來說立哑,一個(gè)打包過的版本庫會將一定數(shù)量的相關(guān)聯(lián)的對象放進(jìn)一個(gè)有關(guān)聯(lián)性的打包中夜惭。如果你設(shè)想多次從 HTTP 公共版本庫中導(dǎo)入數(shù)據(jù),你也許要頻繁地 reapck & prune铛绰,要么就干脆從不這樣做诈茧。

  如果你此時(shí)再次運(yùn)行 git-repack,它就會說 "Nothing to pack"捂掰。要是你繼續(xù)開發(fā)敢会,并且積累了一定數(shù)量的變遷,再運(yùn)行 git-repack 將會創(chuàng)建一個(gè)新的包这嚣,它會包含你自上次對庫打包以來創(chuàng)建的對象鸥昏。我們建議你盡快在初始化提交之后打包一下你的版本庫(除非你現(xiàn)在的項(xiàng)目是個(gè)涂鴉式的草稿項(xiàng)目),并且在項(xiàng)目經(jīng)歷過一段很活躍的時(shí)期時(shí)姐帚,再運(yùn)行 git-repack 一下吏垮。

  當(dāng)一個(gè)版本庫通過 git-push 和 git-pull 命令來同步源版本庫中打包過的對像的時(shí)候,通常保存到目標(biāo)版本庫中的是解包了的對象,除非你使用的是 rsync(遠(yuǎn)程同步協(xié)議)協(xié)議的傳輸方式膳汪。正是這種容許你在兩頭的版本庫中有不同的打包策略的方式唯蝶,他意味著你也許在過一段時(shí)間之后,需要在兩頭的版本庫中都重新打包一下遗嗽。

發(fā)布你的工作

  我們可以通過一個(gè)遠(yuǎn)程的版本庫來利用他人的工作粘我,但是,你如何準(zhǔn)備一個(gè)自己的版本庫來供其他人下載呢媳谁?你在自己的工作目錄下進(jìn)行工作涂滴,這樣你的版本庫就被作為.git的一個(gè)子目錄放在你的工作樹下。你可以讓其他人來遠(yuǎn)程的訪問你的版本庫晴音,但是實(shí)際上這不是通常的做法柔纵。推薦的做法是創(chuàng)建一個(gè)公共的版本庫,讓它可供其他人訪問锤躁,并且搁料,當(dāng)你在你的工作目錄下做了很好的改動(dòng)時(shí),你可以更新到公共的版本庫中系羞。這通常稱為pushing郭计。

  公共版本庫是可以被映像的,上的git公共版本庫也是這樣管理的椒振。

  從你的本地的(私有的)版本庫中發(fā)布改動(dòng)到你的遠(yuǎn)程的(公共的)版本庫中需要遠(yuǎn)程機(jī)器上的寫權(quán)限昭伸。你需要一個(gè)SSH的帳號來運(yùn)行一個(gè)簡單的命令,git-receive-pack澎迎。首先庐杨,你需要在遠(yuǎn)程機(jī)器上創(chuàng)建一個(gè)空的版本庫來存放你的公共版本庫。這個(gè)空版本庫以后將通過pushing來保持更新夹供。顯然灵份,這個(gè)版本庫之需要在開始的時(shí)候創(chuàng)建一次。

  git push使用一對命令哮洽,git-send-pack在本地機(jī)上運(yùn)行填渠,git-receive-pack在遠(yuǎn)程機(jī)上運(yùn)行。這兩個(gè)命令通過SSH連接來進(jìn)行通訊鸟辅。

  你本地的版本庫的git目錄通常是.git氛什,但是你的公共版本庫通常還要加上你的項(xiàng)目名,即.git匪凉。讓我們來為my-git創(chuàng)建這樣一個(gè)版本庫屉更。首先,登入遠(yuǎn)程的機(jī)器洒缀,創(chuàng)建一個(gè)空目錄(如果你選擇HTTP作為發(fā)布方法瑰谜,這個(gè)空目錄需要建在web server的根目錄下面):

  $ mkdir my-git.git

  然后運(yùn)行g(shù)it init-db命令將這個(gè)目錄加入git版本庫中欺冀,這里,因?yàn)檫@個(gè)版本庫的名字不是通常的.git萨脑,我們需要稍微改動(dòng)一下命令:

  $ GIT_DIR=my-git.git git-init-db

  有很多種傳輸方式可以發(fā)布公共版本庫隐轩。這里,要確認(rèn)這個(gè)目錄可以通過你選擇的傳輸方式來被其他人訪問渤早。你也需要確認(rèn)你有g(shù)it-receive-pack這個(gè)程序在$PATH這個(gè)路徑下职车。

  當(dāng)你直接運(yùn)行程序的時(shí)候,很多sshd的安裝版并沒有將你的shell作為登陸的shell鹊杖;這就是說悴灵,如果你登陸的shell是bash 的話,被讀到的是.bashrc而不是.bash_profile骂蓖。確認(rèn).bashrc設(shè)置好了$PATH路徑积瞒,這樣你才可以運(yùn)行g(shù)it-receive-pack命令。

  如果你打算通過HTTP來發(fā)布這個(gè)版本庫登下,這是你就應(yīng)該運(yùn)行命令chmod +x my-git.git/hooks/post-update茫孔。這確認(rèn)了每次你導(dǎo)入數(shù)據(jù)到這個(gè)版本庫中,git-update-server-info能夠被執(zhí)行被芳。

  現(xiàn)在你的“公共的版本庫”可以接受你的任何改動(dòng)了缰贝。回到你的本地機(jī)上畔濒,運(yùn)行命令:

  $ git push :/path/to/my-git.git master

  該命令將你的公共版本庫和你當(dāng)前的版本庫中指定名稱的分支頭部同步(這里是master)剩晴。舉一個(gè)實(shí)際的例子,你可以這樣來更新公共的git版本庫侵状。的鏡像網(wǎng)絡(luò)也這樣來同步其他公共的可訪問的機(jī)器:

  將工作捆綁到一起

  通過 git 的分支功能赞弥,你可以非常容易地做到好像在同一時(shí)間進(jìn)行許多“相關(guān)-或-無關(guān)”的工作一樣阿浓。

  我們已經(jīng)通過前面的 "fun and work" 使用兩個(gè)分支的例子恐仑,看到分支是怎么工作的。這樣的思想在多于兩個(gè)的分支的時(shí)候也是一樣的,比方說诽俯,你現(xiàn)在在 master 的頭,并有些新的代碼在 master 中承粤,另外還有兩個(gè)互不相關(guān)的補(bǔ)丁分別在 "commit-fix" 和 "diff-fix" 兩個(gè)分支中暴区。

  $ git show-branch

  ! [commit-fix] Fix commit message normalization.

  ! [diff-fix] Fix rename detection.

  * [master] Release candidate #1

  ---

  + [diff-fix] Fix rename detection.

  + [diff-fix~1] Better common substring algorithm.

  + [commit-fix] Fix commit message normalization.

  * [master] Release candidate #1

  ++* [diff-fix~2] Pretty-print messages.

  兩個(gè)補(bǔ)丁我們都測試好了,到這里辛臊,你想將他們倆合并起來仙粱,于是你可以先合并 diff-fix ,然后再合并 commit-fix彻舰,像這樣:

  $ git merge 'Merge fix in diff-fix' master diff-fix

  $ git merge 'Merge fix in commit-fix' master commit-fix

  結(jié)果如下:

  $ git show-branch

  ! [commit-fix] Fix commit message normalization.

  ! [diff-fix] Fix rename detection.

  * [master] Merge fix in commit-fix

  ---

  - [master] Merge fix in commit-fix

  + * [commit-fix] Fix commit message normalization.

  - [master~1] Merge fix in diff-fix

  +* [diff-fix] Fix rename detection.

  +* [diff-fix~1] Better common substring algorithm.

  * [master~2] Release candidate #1

  ++* [master~3] Pretty-print messages.

  然而伐割,當(dāng)你確信你手頭上的確是一堆互不相關(guān)的項(xiàng)目變化時(shí)候味,就沒有任何理由將這堆東西一個(gè)個(gè)地合并(假如他們的先后順序很重要,那么他們就不應(yīng)該被定以為無關(guān)的變化)隔心,你可以一次性將那兩個(gè)分支合并到當(dāng)前的分支中白群,首先我們將我們剛剛做過的事情逆轉(zhuǎn)一下,我們需要通過將 master 分支重置到 master~2 位置的方法來將它逆轉(zhuǎn)到合并那兩個(gè)分支之前的狀態(tài)硬霍。

  $ git reset --hard master~2

  你可以用 git-show-branch 來確認(rèn)一下的確是回到了兩次 git-merge 的狀態(tài)了≈穆現(xiàn)在你可以用一行命令將那兩個(gè)分支導(dǎo)入的方式來替代兩次運(yùn)行(也就是所謂的 炮制章魚 -- making an Octopus)git-merge :

  $ git pull . commit-fix diff-fix

  $ git show-branch

  ! [commit-fix] Fix commit message normalization.

  ! [diff-fix] Fix rename detection.

  * [master] Octopus merge of branches 'diff-fix' and 'commit-fix'

  ---

  - [master] Octopus merge of branches 'diff-fix' and 'commit-fix'

  + * [commit-fix] Fix commit message normalization.

  +* [diff-fix] Fix rename detection.

  +* [diff-fix~1] Better common substring algorithm.

  * [master~1] Release candidate #1

  ++* [master~2] Pretty-print messages.

  注意那些不適合制作章魚的場合,盡管你可以那樣做唯卖。一只“章魚”往往可以使項(xiàng)目的提交歷史更具可讀性粱玲,前提是你在同一時(shí)間導(dǎo)入的兩份以上的變更是互不關(guān)聯(lián)的。然而拜轨,如果你在合并任何分支的過程中出現(xiàn)合并沖突抽减,并且需要手工解決的話,那意味著這些分支當(dāng)中有相互干涉的開發(fā)工作在進(jìn)行撩轰,那么你就應(yīng)該將這個(gè)兩個(gè)沖突先合并胯甩,并且記錄下你是如何解決這個(gè)沖突,以及你首先處理他們的理由堪嫂。(譯者按:處理完沖突之后偎箫,你就可以放心制作“章魚”了)否則的話將會造成項(xiàng)目的發(fā)展歷史很難跟蹤。

管理版本庫

  版本庫的管理員可以用下面的工具來建立和維護(hù)版本庫皆串。

  * git-daemon(1) 容許匿名下載版本庫淹办。

  * git-shell(1) 面向中心版本庫模式的用戶的類似 受限的 shell 的命令。

  update hook howto 一個(gè)很好的管理中心版本庫的例子恶复。

  例子

  在 /pub/scm 上運(yùn)行 git 守護(hù)進(jìn)程

  $ grep git /etc/inet.conf

  git stream tcp nowait nobody \

  /usr/bin/git-daemon git-daemon --inetd --syslog --export-all /pub/scm

  這個(gè)配置行應(yīng)該在配置文件中用一行來寫完怜森。

  僅給開發(fā)者 push/pull 的訪問權(quán)限。

  $ grep git /etc/passwd (1)

  alice:x:1000:1000::/home/alice:/usr/bin/git-shell

  bob:x:1001:1001::/home/bob:/usr/bin/git-shell

  cindy:x:1002:1002::/home/cindy:/usr/bin/git-shell

  david:x:1003:1003::/home/david:/usr/bin/git-shell

  $ grep git /etc/shells (2)

  /usr/bin/git-shell

  (1) 將用戶的登錄 shell 設(shè)定為 /usr/bin/git-shell,

  它除了運(yùn)行 "git-push" 和 "git-pull" 不能做任何事谤牡。

  這樣用戶就可以通過 ssh 來訪問機(jī)器副硅。

  (2) 許多的發(fā)行版需要在 /etc/shells 配置文件中列明要用什么 shell 來作為登錄 shell。

  CVS - 模式的公共庫翅萤。

  $ grep git /etc/group (1)

  git:x:9418:alice,bob,cindy,david

  $ cd /home/devo.git

  $ ls -l (2)

  lrwxrwxrwx 1 david git 17 Dec 4 22:40 HEAD -> refs/heads/master

  drwxrwsr-x 2 david git 4096 Dec 4 22:40 branches

  -rw-rw-r-- 1 david git 84 Dec 4 22:40 config

  -rw-rw-r-- 1 david git 58 Dec 4 22:40 description

  drwxrwsr-x 2 david git 4096 Dec 4 22:40 hooks

  -rw-rw-r-- 1 david git 37504 Dec 4 22:40 index

  drwxrwsr-x 2 david git 4096 Dec 4 22:40 info

  drwxrwsr-x 4 david git 4096 Dec 4 22:40 objects

  drwxrwsr-x 4 david git 4096 Nov 7 14:58 refs

  drwxrwsr-x 2 david git 4096 Dec 4 22:40 remotes

  $ ls -l hooks/update (3)

  -r-xr-xr-x 1 david git 3536 Dec 4 22:40 update

  $ cat info/allowed-users (4)

  refs/heads/master alice\|cindy

  refs/heads/doc-update bob

  refs/tags/v[0-9]* david

  (1) 將所有的開發(fā)人員都作為 git 組的成員恐疲。

  (2) 并且給予他們公共版本庫的寫權(quán)限。

  (3) 用一個(gè)在 Documentation/howto/ 中的 Carl 寫的例子來實(shí)現(xiàn)版本庫的分支控制策略套么。

  (4) Alice 和 Cindy 可以提交入 master 分支培己,只有 Bob 能提交入 doc-update 分支,

  David 則是發(fā)行經(jīng)理只有他能創(chuàng)建并且 push 版本標(biāo)簽胚泌。

  支持默協(xié)議傳輸?shù)?HTTP 服務(wù)器省咨。

  dev$ git update-server-info (1)

  ftp> cp -r .git /home/user/myproject.git

  (1) 保證 info/refs 和 object/info/packs 是最新的。

  (2) 上傳到你的 HTTP 服務(wù)器主機(jī)玷室。

項(xiàng)目開發(fā)的模式推介

  盡管 git 是一個(gè)正式項(xiàng)目發(fā)布系統(tǒng)零蓉,它卻可以方便地將你的項(xiàng)目建立在松散的開發(fā)人員組織形式上笤受。 Linux 內(nèi)核的開發(fā),就是按這樣的模式進(jìn)行的敌蜂。在 Randy Dunlap 的著作中("Merge to Mainline" 第17頁)就有很好的介紹

  需要強(qiáng)調(diào)的是正真的非常規(guī)的開發(fā)組織形式感论, git 這種組織形式,意味著對于工作流程的約束紊册,沒有任何強(qiáng)迫性的原則比肄。你不必從唯一一個(gè)遠(yuǎn)程版本庫中導(dǎo)入(工作目錄)。

  項(xiàng)目領(lǐng)導(dǎo)人(project lead)的工作推介

  1. 在你自己的本地機(jī)器上準(zhǔn)備好主版本庫囊陡。你的所有工作都在這里完成芳绩。

  2. 準(zhǔn)備一個(gè)能讓大家訪問的公共版本庫。

  如果其他人是通過默協(xié)議的方式(http)來導(dǎo)入版本庫的撞反,那么你有必要保持這個(gè) 默協(xié)議的友好性妥色。 git-init-db 之后,復(fù)制自標(biāo)準(zhǔn)模板庫的 $GIT_DIR/hooks/post-update 將包含一個(gè)對 git-update-server-info 的調(diào)用遏片,但是 post-update 默認(rèn)是不能喚起它自身的嘹害。通過 chmod +x post-update 命令使能它。這樣讓 git-update-server-info 保證那些必要的文件是最新的吮便。

  3. 將你的主版本庫推入公共版本庫笔呀。

  4. git-repack 公共版本庫。這將建立一個(gè)包含初始化提交對象集的打包作為項(xiàng)目的起始線髓需,可能的話许师,執(zhí)行一下 git-prune,要是你的公共庫是通過 pull 操作來從你打包過的版本庫中導(dǎo)入的僚匆。

  5. 在你的主版本庫中開展工作微渠,這些工作可能是你自己的最項(xiàng)目的編輯,可能是你由 email 收到的一個(gè)補(bǔ)丁咧擂,也可能是你從這個(gè)項(xiàng)目的“子系統(tǒng)負(fù)責(zé)人” 的公共庫中導(dǎo)入的工作等等逞盆。

  你可以在任何你喜歡的時(shí)候重新打包你的這個(gè)私人的版本庫。

  6. 將項(xiàng)目的進(jìn)度推入公共庫中松申,并給大家公布一下云芦。

  7. 盡管一段時(shí)間以后,"git-repack" 公共庫攻臀。并回到第5步繼續(xù)工作焕数。

  項(xiàng)目的子系統(tǒng)負(fù)責(zé)人(subsystem maintainer)也有自己的公共庫纱昧,工作流程大致如下:

  1. 準(zhǔn)被一個(gè)你自己的工作目錄刨啸,它通過 git-clone 克隆自項(xiàng)目領(lǐng)導(dǎo)人的公共庫。原始的克隆地址(URL)將被保存在 .git/remotes/origin 中识脆。

  2. 準(zhǔn)備一個(gè)可以給大家訪問的公共庫设联,就像項(xiàng)目領(lǐng)導(dǎo)人所做的那樣善已。

  3. 復(fù)制項(xiàng)目領(lǐng)導(dǎo)人的公共庫中的打包文件到你的公共庫中,除非你的公共庫和項(xiàng)目領(lǐng)導(dǎo)人的公共庫是在同一部主機(jī)上离例。以后你就可以通過 objects/info/alternates 文件的指向來瀏覽它所指向的版本庫了换团。

  4. 將你的主版本庫推入你的公共版本庫,并運(yùn)行 git-repack宫蛆,如果你的公共庫是通過的公共庫是通過 pull 來導(dǎo)入的數(shù)據(jù)的話艘包,再執(zhí)行一下 git-prune 。

  5. 在你的主版本庫中開展工作耀盗。這些工作可能包括你自己的編輯想虎,來自 email 的補(bǔ)丁,從項(xiàng)目領(lǐng)導(dǎo)人叛拷,“下一級子項(xiàng)目負(fù)責(zé)人”的公共庫哪里導(dǎo)入的工作等等舌厨。

  你可以在任何時(shí)候重新打包你的私人版本庫。

  6. 將你的變更推入公共庫中裙椭,并且請“項(xiàng)目領(lǐng)導(dǎo)人”和“下級子系統(tǒng)負(fù)責(zé)人”導(dǎo)入這些變更署浩。

  7. 每隔一段時(shí)間之后,git-repack 公共庫筋栋。回到第 5 步繼續(xù)工作二汛。

  “一般開發(fā)人員”無須自己的公共庫,大致的工作方式是:

  1. 準(zhǔn)備你的工作庫氓栈,它應(yīng)該用 git-clone 克隆自“項(xiàng)目領(lǐng)導(dǎo)人”的公共庫(如果你只是開發(fā)子項(xiàng)目,那么就克隆“子項(xiàng)目負(fù)責(zé)人”的)婿着∈谑荩克隆的源地址(URL)會被保存到 .git/remotes/origin 中。

  2. 在你的個(gè)人版本庫中的 master 分支中開展工作竟宋。

  3. 每隔一段時(shí)間提完,向上游的版本庫運(yùn)行一下 git-fetch origin 。這樣只會做 git-pull 一半的操作丘侠,即只克隆不合并徒欣。公共版本庫的新的頭就會被保存到 .git/refs/heads/origins 。

  4. 用 git-cherry origin 命令蜗字,看一下你有什么補(bǔ)丁被接納了打肝。并用 git-rebase origin 命令將你以往的變更遷移到最新的上游版本庫的狀態(tài)中脂新。(關(guān)于 git-rebase 命令,請參考 git-rebase)

  5. 用 git-format-patch origin 生成 email 形式的補(bǔ)丁并發(fā)給上游的維護(hù)者粗梭≌悖回到第二步接著工作。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末断医,一起剝皮案震驚了整個(gè)濱河市滞乙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鉴嗤,老刑警劉巖酷宵,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異躬窜,居然都是意外死亡浇垦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門荣挨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來男韧,“玉大人默垄,你說我怎么就攤上這事口锭。” “怎么了韭寸?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵恩伺,是天一觀的道長晶渠。 經(jīng)常有香客問我褒脯,道長番川,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任缚陷,我火速辦了婚禮箫爷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘硫痰。我一直安慰自己效斑,他們只是感情好缓屠,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布敌完。 她就那樣靜靜地躺著滨溉,像睡著了一般晦攒。 火紅的嫁衣襯著肌膚如雪勤家。 梳的紋絲不亂的頭發(fā)上伐脖,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天讼庇,我揣著相機(jī)與錄音蠕啄,去河邊找鬼歼跟。 笑死哈街,一個(gè)胖子當(dāng)著我的面吹牛骚秦,可吹牛的內(nèi)容都是我干的作箍。 我是一名探鬼主播胞得,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼罩息,長吁一口氣:“原來是場噩夢啊……” “哼个扰!你這毒婦竟也來了递宅?” 一聲冷哼從身側(cè)響起办龄,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤安接,失蹤者是張志新(化名)和其女友劉穎盏檐,沒想到半個(gè)月后驶悟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痕鳍,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年旨别,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秸弛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胆屿。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖纯趋,靈堂內(nèi)的尸體忽然破棺而出吵冒,到底是詐尸還是另有隱情痹栖,我是刑警寧澤揪阿,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布南捂,位于F島的核電站溺健,受9級特大地震影響鞭缭,放射性物質(zhì)發(fā)生泄漏缚去。R本人自食惡果不足惜易结,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一躏精、第九天 我趴在偏房一處隱蔽的房頂上張望鹦肿。 院中可真熱鬧箩溃,春花似錦涣旨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浆洗。三九已至伏社,卻和暖如春洛口,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背买优。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工杀赢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脂崔,地道東北人砌左。 一個(gè)月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓屁擅,卻偏偏與公主長得像产弹,于是被迫代替她去往敵國和親痰哨。 傳聞我的和親對象是個(gè)殘疾皇子斤斧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

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

  • 之前參照莫煩的Git教程整理過一遍Git總結(jié)贝或,后來使用Git的時(shí)候發(fā)現(xiàn)還是有很多操作一知半解锐秦,所以再次梳理下Git...
    憶江南_1569閱讀 577評論 2 0
  • 一、基本概念: 注:對于git的分布式概念及其優(yōu)點(diǎn)扇谣,不重復(fù)說明闲昭,自己百度或谷歌序矩。本文中涉及到指令前面有$的,在cm...
    大廠offer閱讀 1,431評論 0 3
  • 以下筆記主要參考gitgot,大致了解git使用和原理租幕。 第一部分我們從個(gè)人的視角去研究如何用好Git劲绪,并且揭示G...
    carolwhite閱讀 2,386評論 0 1
  • 這篇博文是自己在學(xué)習(xí)git過程中的思考總結(jié)。本文僅僅代表個(gè)人的看法歉眷,如有不妥地方還請本文文末留言姥芥。 ?? 原文鏈接g...
    Ming_Hu閱讀 1,087評論 4 18
  • 搞笑 南方人就是喜歡講究庸追,據(jù)說燃放煙花爆竹淡溯,也要看時(shí)間和地點(diǎn)簿训,時(shí)間要精確到秒强品,方位需要用盛菜盤(羅盤)來確定的榛。 幾...
    檀梓林閱讀 182評論 0 0