第 6 章 多人Git

2018-02-24 15:45 更新

我最初在一個(gè)私人項(xiàng)目上使用Git,那里我是唯一的開(kāi)發(fā)。在與Git分布式本性有關(guān)的命 令中,我只用到了?pull?和 clone,用以在不同地方保持同一個(gè)項(xiàng)目。

后來(lái)我想用Git發(fā)布我的代碼,并且包括其他貢獻(xiàn)者的變更。我不得不學(xué)習(xí)如何管理有來(lái) 自世界各地的多個(gè)開(kāi)發(fā)的項(xiàng)目,幸運(yùn)的是,這是Git的長(zhǎng)處,也可以說(shuō)是其存在的理由。

我是誰(shuí)?

每個(gè)提交都有一個(gè)作者姓名和電子信箱,這顯示在?git log?里。默認(rèn), Git使用系統(tǒng) 設(shè)定來(lái)填充這些域。要顯示地設(shè)定,鍵入:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

去掉global選項(xiàng)設(shè)定只對(duì)當(dāng)前倉(cāng)庫(kù)生效。

Git在SSH, HTTP上

假設(shè)你有ssh訪問(wèn)權(quán)限,以訪問(wèn)一個(gè)網(wǎng)頁(yè)服務(wù)器,但上面并沒(méi)有安裝Git。盡管比著它的 原生協(xié)議效率低,Git也是可以通過(guò)HTTP來(lái)進(jìn)行通信的。

那么在你的帳戶下,下載,編譯并安裝Git。在你的網(wǎng)頁(yè)目錄里創(chuàng)建一個(gè)Git倉(cāng)庫(kù):

$ GIT_DIR=proj.git git init
$ cd proj.git
$ git --bare update-server-info
$ cp hooks/post-update.sample hooks/post-update

對(duì)較老版本的Git,只拷貝還不夠,你應(yīng)運(yùn)行:

$ chmod a+x hooks/post-update

現(xiàn)在你可以通過(guò)SSH從隨便哪個(gè)克隆發(fā)布你的最新版本:

$ git push web.server:/path/to/proj.git master

那隨便誰(shuí)都可以通過(guò)如下命令得到你的項(xiàng)目:

$ git clone http://web.server/proj.git

Git在隨便什么上

想無(wú)需服務(wù)器,甚至無(wú)需網(wǎng)絡(luò)連接的時(shí)候同步倉(cāng)庫(kù)?需要在緊急時(shí)期湊合一下?我們 已經(jīng)看過(guò)git fast-export?和?git fast-import?可以轉(zhuǎn)換資源 庫(kù)到一個(gè)單一文件以及轉(zhuǎn)回來(lái)。 我們可以來(lái)來(lái)會(huì)會(huì)傳送這些文件以傳輸git倉(cāng)庫(kù), 通過(guò)任何媒介,但一個(gè)更有效率的工具是?git bundle?。

發(fā)送者創(chuàng)建一個(gè)“文件包”:

$ git bundle create somefile HEAD

然后傳輸這個(gè)文件包,?somefile?,給某個(gè)其他參與者:電子郵件,優(yōu)盤(pán),一個(gè)?xxd?打印品和一個(gè)OCR掃描儀,通過(guò)電話讀字節(jié),狼煙,等等。接收者通過(guò)鍵入如下命 令從文件包獲取提交:

$ git pull somefile

接收者甚至可以在一個(gè)空倉(cāng)庫(kù)做這個(gè)。不考慮大小,?somefile?可以包含整個(gè)原先 git倉(cāng)庫(kù)。

在較大的項(xiàng)目里,可以通過(guò)只打包其他倉(cāng)庫(kù)缺少的變更消除浪費(fèi)。例如,假設(shè)提交 ‘`1b6d…’'是兩個(gè)參與者共享的最近提交:

$ git bundle create somefile HEAD ^1b6d

如果做的頻繁,人可能容易忘記剛發(fā)了哪個(gè)提交。幫助頁(yè)面建議使用標(biāo)簽解決這個(gè)問(wèn)題。 即,在你發(fā)了一個(gè)文件包后,鍵入:

$ git tag -f lastbundle HEAD

并創(chuàng)建較新文件包,使用:

$ git bundle create newbundle HEAD ^lastbundle

補(bǔ)?。喝蜇泿?/h2>

補(bǔ)丁是變更的文本形式,易于計(jì)算機(jī)理解,人也類似。補(bǔ)丁可以通吃。你可以給開(kāi)發(fā)電 郵一個(gè)補(bǔ)丁,不用管他們用的什么版本控制系統(tǒng)。只要你的觀眾可以讀電子郵件,他們 就能看到你的修改。類似,在你這邊,你只需要一個(gè)電子郵件帳號(hào):不必搭建一個(gè)在線 的Git倉(cāng)庫(kù)。

回想一下第一章:

$ git diff 1b6d > my.patch

輸出是一個(gè)補(bǔ)丁,可以粘貼到電子郵件里用以討論。在一個(gè)Git倉(cāng)庫(kù),鍵入:

$ git apply < my.patch

來(lái)打這個(gè)補(bǔ)丁。

在更正式些的設(shè)置里,當(dāng)作者名字以及或許簽名應(yīng)該記錄下的時(shí)候,為過(guò)去某一刻生成 補(bǔ)丁,鍵入:

$ git format-patch 1b6d

結(jié)果文件可以給?git-send-email?發(fā)送,或者手工發(fā)送。你也可以指定一個(gè)提交范圍:

$ git format-patch 1b6d..HEAD^^

在接收一端,保存郵件到一個(gè)文件,然后鍵入:

$ git am < email.txt

這就打了補(bǔ)丁并創(chuàng)建了一個(gè)提交,包含諸如作者之類的信息。

使用瀏覽器郵件客戶端,在保存補(bǔ)丁為文件之前,你可能需要建一個(gè)按鈕,看看郵件內(nèi) 容原來(lái)的原始形式。

對(duì)基于mbox的郵件客戶端有些微不同,但如果你在使用的話,你可能是那種能輕易找出 答案的那種人,不用讀教程。

對(duì)不起,移走了

克隆一個(gè)倉(cāng)庫(kù)后,運(yùn)行?git push?或?git pull?講自動(dòng)推到或從原先URL拉。Git 如何做這個(gè)呢?秘密在和克隆一起創(chuàng)建的配置選項(xiàng)。讓我們看一下:

$ git config --list

選項(xiàng)?remote.origin.url?控制URL源;“origin” 是給源倉(cāng)庫(kù)的昵稱。和 “master” 分支的慣例一樣,我們可以改變或刪除這個(gè)昵稱,但通常沒(méi)有理由這么做。

如果原先倉(cāng)庫(kù)移走,我們可以更新URL,通過(guò):

$ git config remote.origin.url git://new.url/proj.git

選項(xiàng)?branch.master.merge?指定?git pull?里的默認(rèn)遠(yuǎn)端分支。在初始克隆的時(shí)候, 它被設(shè)為原倉(cāng)庫(kù)的當(dāng)前分支,因此即使原倉(cāng)庫(kù)之后挪到一個(gè)不同的分支,后來(lái)的 pull也將忠實(shí)地跟著原來(lái)的分支。

這個(gè)選項(xiàng)只使用我們初次克隆的倉(cāng)庫(kù),它的值記錄在選項(xiàng)?branch.master.remote?。如果我們從其他倉(cāng)庫(kù)拉入,我們必須顯示指定我們想要哪個(gè)分支:

$ git pull git://example.com/other.git master

以上也解釋了為什么我們較早一些push和pull的例子沒(méi)有參數(shù)。

遠(yuǎn)端分支

當(dāng)你克隆一個(gè)倉(cāng)庫(kù),你也克隆了它的所有分支。你或許沒(méi)有注意到因?yàn)镚it將它們隱藏 起來(lái)了:你必須明確地要求。這使得遠(yuǎn)端倉(cāng)庫(kù)里的分支不至于干擾你的分支,也使 Git對(duì)初學(xué)者稍稍容易些。

列出遠(yuǎn)端分支,使用:

$ git branch -r

你應(yīng)該看到類似:

origin/HEAD
origin/master
origin/experimental

這顯示了遠(yuǎn)端倉(cāng)庫(kù)的分支和HEAD,可以用在常用的Git命令里。例如,假設(shè)你已經(jīng)做了 很多提交,并希望和最后取到的版本比較一下。你可以搜索適當(dāng)?shù)腟HA1哈希值,但使用 下面命令更容易些:

$ git diff origin/HEAD

或你可以看看‘`experimental’'分支都有啥:

$ git log origin/experimental

多遠(yuǎn)端

假設(shè)另兩個(gè)開(kāi)發(fā)在同一個(gè)項(xiàng)目上工作,我們希望保持兩個(gè)標(biāo)簽。我們可以同事跟多個(gè)倉(cāng)庫(kù):

$ git remote add other git://example.com/some_repo.git
$ git pull other some_branch

現(xiàn)在我們已經(jīng)從第二個(gè)倉(cāng)庫(kù)合并到一個(gè)分支,并且我們已容易訪問(wèn)所有倉(cāng)庫(kù)的所有 分支。

$ git diff origin/experimental^ other/some_branch~5

但如果為了不影響自己的工作,我們只想比較他們的變更怎么辦呢?換句話說(shuō),我們想 檢查一下他們的分支,又不使他們的變更入侵我們的工作目錄。那不是運(yùn)行pull命令, 而是運(yùn)行:

$ git fetch        # Fetch from origin, the default.
$ git fetch other  # Fetch from the second programmer.

這只是獲取歷史。盡管工作目錄維持不變,我們可以參考任何倉(cāng)庫(kù)的任何分支,使用 一個(gè)Git命令,因?yàn)槲覀儸F(xiàn)在有一個(gè)本地拷貝。

回想一下,在幕后,一個(gè)pull是簡(jiǎn)單地一個(gè)?fetch?然后?merge?。通常,我們?pull?因?yàn)槲覀兿朐讷@取后合并最近提交;這個(gè)情況是一個(gè)值得注意的例外。

關(guān)于如何去除遠(yuǎn)端倉(cāng)庫(kù),如何忽略特定分支等更多,參見(jiàn)?git help remote?。

我的喜好

對(duì)我手頭的項(xiàng)目,我喜歡貢獻(xiàn)者去準(zhǔn)備倉(cāng)庫(kù),這樣我可以從其中拉。一些Git伺服讓你 點(diǎn)一個(gè)按鈕,擁有自己的分叉項(xiàng)目。

在我獲取一個(gè)樹(shù)之后,我運(yùn)行Git命令去瀏覽并檢查這些變更,理想情況下這些變更組織 良好,描述良好。我合并這些變更,也或許做些編輯。直到滿意,我才把變更推入主資 源庫(kù)。

盡管我不經(jīng)常收到貢獻(xiàn),我相信這個(gè)方法擴(kuò)展性良好。參見(jiàn)?這篇 來(lái)自Linus Torvalds的博客

呆在Git的世界里比補(bǔ)丁文件稍更方便,因?yàn)椴挥梦覍⒀a(bǔ)丁轉(zhuǎn)換到Git提交。更進(jìn)一步, Git處理諸如作者姓名和信箱地址的細(xì)節(jié),還有時(shí)間和日期,以及要求作者描述他們的提 交。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)