![Git權(quán)威指南(上篇1-2章)_第1頁](http://file4.renrendoc.com/view/c78e3cafafb6f086e0901320e131cfdf/c78e3cafafb6f086e0901320e131cfdf1.gif)
![Git權(quán)威指南(上篇1-2章)_第2頁](http://file4.renrendoc.com/view/c78e3cafafb6f086e0901320e131cfdf/c78e3cafafb6f086e0901320e131cfdf2.gif)
![Git權(quán)威指南(上篇1-2章)_第3頁](http://file4.renrendoc.com/view/c78e3cafafb6f086e0901320e131cfdf/c78e3cafafb6f086e0901320e131cfdf3.gif)
![Git權(quán)威指南(上篇1-2章)_第4頁](http://file4.renrendoc.com/view/c78e3cafafb6f086e0901320e131cfdf/c78e3cafafb6f086e0901320e131cfdf4.gif)
![Git權(quán)威指南(上篇1-2章)_第5頁](http://file4.renrendoc.com/view/c78e3cafafb6f086e0901320e131cfdf/c78e3cafafb6f086e0901320e131cfdf5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
Git權(quán)威指南上(1-2篇)目錄\h第1篇初識Git\h第1章版本控制的前世和今生\h1.1黑暗的史前時代\h1.2CVS——開啟版本控制大爆發(fā)\h1.3SVN——集中式版本控制集大成者\h1.4Git——Linus的第二個偉大作品\h第2章愛上Git的理由\h2.1每日工作備份\h2.2異地協(xié)同工作\h2.3現(xiàn)場版本控制\h2.4避免引入輔助目錄\h2.5重寫提交說明\h2.6想吃后悔藥\h2.7更好用的提交列表\h2.8更好的差異比較\h2.9工作進(jìn)度保存\h2.10代理SVN提交實現(xiàn)移動式辦公\h2.11無處不在的分頁器\h2.12快\h第3章Git的安裝和使用\h3.1在Linux下安裝和使用Git\h3.1.1包管理器方式安裝\h3.1.2從源代碼進(jìn)行安裝\h3.1.3從Git版本庫進(jìn)行安裝\h3.1.4命令補齊\h3.1.5中文支持\h3.2在MacOSX下安裝和使用Git\h3.2.1以二進(jìn)制發(fā)布包的方式安裝\h3.2.2安裝Xcode\h3.2.3使用Homebrew安裝Git\h3.2.4從Git源碼進(jìn)行安裝\h3.2.5命令補齊\h3.2.6其他輔助工具的安裝\h3.2.7中文支持\h3.3在Windows下安裝和使用Git(Cygwin篇)\h3.3.1安裝Cygwin\h3.3.2安裝Git\h3.3.3Cygwin的配置和使用\h3.3.4Cygwin下Git的中文支持\h3.3.5Cygwin下Git訪問SSH服務(wù)\h3.4Windows下安裝和使用Git(msysGit篇)\h3.4.1安裝msysGit\h3.4.2msysGit的配置和使用\h3.4.3msysGit中shell環(huán)境的中文支持\h3.4.4msysGit中Git的中文支持\h3.4.5使用SSH協(xié)議\h3.4.6TortoiseGit的安裝和使用\h3.4.7TortoiseGit的中文支持\h第2篇Git獨奏\h第4章Git初始化\h4.1創(chuàng)建版本庫及第一次提交\h4.2思考:為什么工作區(qū)根目錄下有一個.git目錄\h4.3思考:gitconfig命令的各參數(shù)有何區(qū)別\h4.4思考:是誰完成的提交\h4.5思考:隨意設(shè)置提交者姓名,是否太不安全\h4.6思考:命令別名是干什么的\h4.7備份本章的工作成果\h第5章Git暫存區(qū)\h5.1修改不能直接提交嗎\h5.2理解Git暫存區(qū)(stage)\h5.3GitDiff魔法\h5.4不要使用gitcommit-a\h5.5擱置問題,暫存狀態(tài)\h第6章Git對象\h6.1Git對象庫探秘\h6.2思考:SHA1哈希值到底是什么,是如何生成的\h6.3思考:為什么不用順序的數(shù)字來表示提交\h第7章Git重置\h7.1分支游標(biāo)master探秘\h7.2用reflog挽救錯誤的重置\h7.3深入了解gitreset命令\h第8章Git檢出\h8.1HEAD的重置即檢出\h8.2挽救分離頭指針\h8.3深入了解gitcheckout命令\h第9章恢復(fù)進(jìn)度\h9.1繼續(xù)暫存區(qū)未完成的實踐\h9.2使用gitstash\h9.3探秘gitstash\h第10章Git基本操作\h10.1先來合個影\h10.2刪除文件\h10.2.1本地刪除不是真的刪除\h10.2.2執(zhí)行g(shù)itrm命令刪除文件\h10.2.3命令gitadd-u快速標(biāo)記刪除\h10.3恢復(fù)刪除的文件\h10.4移動文件\h10.5一個顯示版本號的HelloWorld\h10.6使用gitadd-i選擇性添加\h10.7HelloWorld引發(fā)的新問題\h10.8文件忽略\h10.9文件歸檔\h第11章歷史穿梭\h11.1圖形工具:gitk\h11.2圖形工具:gitg\h11.3圖形工具:qgit\h11.4命令行工具\h11.4.1版本表示法:gitrev-parse\h11.4.2版本范圍表示法:gitrev-list\h11.4.3瀏覽日志:gitlog\h11.4.4差異比較:gitdiff\h11.4.5文件追溯:gitblame\h11.4.6二分查找:gitbisect\h11.4.7獲取歷史版本\h第12章改變歷史\h12.1悔棋\h12.2多步悔棋\h12.3回到未來\h12.3.1時間旅行一\h12.3.2時間旅行二\h12.3.3時間旅行三\h12.4丟棄歷史\h12.5反轉(zhuǎn)提交\h第13章Git克隆\h13.1雞蛋不裝在一個籃子里\h13.2對等工作區(qū)\h13.3克隆生成裸版本庫\h13.4創(chuàng)建生成裸版本庫\h第14章Git庫管理\h14.1對象和引用哪里去了\h14.2暫存區(qū)操作引入的臨時對象\h14.3重置操作引入的對象\h14.4Git管家:git-gc\h14.5Git管家的自動執(zhí)行第1篇初識GitGit是一款分布式版本控制系統(tǒng),有別于CVS和SVN等集中式版本控制系統(tǒng),Git可以讓研發(fā)團(tuán)隊更加高效地協(xié)同工作,從而提高生產(chǎn)率。使用Git,開發(fā)人員的工作不會因為頻繁地遭遇提交沖突而中斷,管理人員也無須為數(shù)據(jù)的備份而擔(dān)心。經(jīng)過Linux這樣的龐大項目的考驗之后,Git被證明可以勝任任何規(guī)模的團(tuán)隊,即便團(tuán)隊成員分布于世界各地。Git是開源社區(qū)奉獻(xiàn)給每一個人的寶貝,用好它不僅可以實現(xiàn)個人的知識積累、保護(hù)好自己的數(shù)據(jù),而且還能與他人分享自己的成果。這在其他的很多版本控制系統(tǒng)中是不可想象的。你會為個人的版本控制而花費高昂的費用去購買商業(yè)版本控制工具嗎?你會去使用必須搭建額外的服務(wù)器才能使用的版本控制系統(tǒng)嗎?你會把“雞蛋”放在具有單點故障、服務(wù)器軟硬件有可能崩潰的唯一的“籃子”里嗎?如果你不會,那么選擇Git,一定是最明智的選擇。本篇我們首先用一章的內(nèi)容來回顧一下版本控制的歷史,并以此向版本控制的前輩CVS和SVN致敬。第2章會通過一些典型的版本控制實例向您展示Git獨特的魅力,讓您愛上Git。在本篇的最后一章會介紹Git在Linux、MacOSX及Windows下的安裝和使用,這是我們進(jìn)一步研究Git的基礎(chǔ)。在這里有必要糾正一下Git的發(fā)音。一種錯誤是按照單個字母來發(fā)音,另外一種更為普遍的錯誤是把整個單詞讀作“技特”,實際上Git中字母G的發(fā)音與下列單詞中的G類似:GOD、GIVES、GREAT、GIFT。因此Git正確的發(fā)音應(yīng)該聽起來像是“歌易特”。本書的英文名為《GotGit》,當(dāng)面對這樣的書名時您還會把Git讀錯嗎?第1章版本控制的前世和今生除了茫然未知的宇宙,幾乎任何事物都是從無到有,從簡陋到完善。隨著時間車輪的滾滾向前,歷史被拋在身后逐漸遠(yuǎn)去,如同我們的現(xiàn)代社會,世界大同,到處都是忙碌和喧囂,再也看不到已經(jīng)遠(yuǎn)去的刀耕火種、男耕女織的慢生活歲月。版本控制系統(tǒng)是一個另類。雖然其歷史并不短暫,也有幾十年,但是它的演進(jìn)進(jìn)程卻一直在社會的各個角落重復(fù)著,而且驚人的相似。有的人從未使用甚至從未聽說過版本控制系統(tǒng),他和他的團(tuán)隊就像停留在黑暗的史前時代,任由數(shù)據(jù)自生自滅。有的人使用著有幾十年歷史的CVS或其改良版Subversion,讓時間空耗在網(wǎng)絡(luò)連接的等待中。以Git為代表的分布式版本控制系統(tǒng)已經(jīng)風(fēng)靡整個開源社區(qū),正等待你的靠近。1.1黑暗的史前時代談及遠(yuǎn)古,人們總愛以“黑暗”來形容。黑暗實際上指的是秩序和工具的匱乏,而不是自然。如果以自然環(huán)境而論,由于工業(yè)化和城市化對環(huán)境的破壞,現(xiàn)今才是最黑暗的年代。對于軟件開發(fā)來說也是如此,在C語言一統(tǒng)天下的日子里我們的選擇很簡單,如今面臨Java、.Net和腳本語言時,我們的選擇變得復(fù)雜起來,但是從工具和秩序上講,過去的年代是黑暗的。回顧一下我經(jīng)歷的版本控制的“史前時代”吧。在大學(xué)里,代碼分散地拷貝在各個軟盤中,最終我被搞糊涂,不知道哪個軟盤中的代碼是最優(yōu)的,因為最新并非最優(yōu),失敗的重構(gòu)會毀掉原來尚能運作的代碼。在我工作的第一年,代碼的管理并未得到改善,還是以簡單的目錄拷貝進(jìn)行數(shù)據(jù)的備份,三四個程序員利用文件服務(wù)器的共享目錄進(jìn)行協(xié)同,公共類庫和頭文件在操作過程中相互覆蓋,痛苦不堪。很明顯,那時我尚不知道版本控制系統(tǒng)為何物。我的版本控制史前時代一直延續(xù)到2000年,那時CVS已經(jīng)誕生了14年,而我在那時對CVS還一無所知。實際上,即便是在CVS出現(xiàn)之前的“史前時代”,也已經(jīng)有了非常好用的用于源碼比較和打補丁的工具:diff和patch,它們今天生命力依然頑強。大名鼎鼎的LinusTorvalds先生(Linux之父)也對這兩個工具偏愛有加,在1991~2002年之間,Linus一直頑固地使用diff、patch和tar包管理著Linux的代碼,雖然不斷有人提醒他有CVS的存在\h[1]。那么來看看diff和patch,熟悉它們將對理解版本控制系統(tǒng)(差異存儲)和使用版本控制系統(tǒng)(代碼比較和沖突解決)都有莫大的好處。1.用diff命令比較兩個文本文件或目錄的差異先來構(gòu)造兩個文件:\h對這兩個文件執(zhí)行diff命令,并通過輸出重定向,將差異保存在diff.txt文件中。$diff-uhelloworld>diff.txt上面執(zhí)行diff命令的-u參數(shù)很重要,使得差異輸出中帶有上下文。打開文件diff.txt,會看到其中的差異比較結(jié)果。為了說明方便,為每一行增添了行號。1hello2010-09-2117:45:33.551610940+08002+++world2010-09-2117:44:46.343610465+08003@@-1,4+1,4@@4-應(yīng)該杜絕文章中的錯別子。5+應(yīng)該杜絕文章中的錯別字。67但是無論使用8*全拼,雙拼9@@-6,6+6,7@@1011是人就有可能犯錯,軟件更是如此。1213-犯了錯,就要扣工資!14-15改正的成本可能會很高。16+17+但是“只要眼球足夠多,所有Bug都好捉”,18+這就是開源的哲學(xué)之一。上面的差異文件,可以這么理解:第1行和第2行分別記錄了原始文件和目標(biāo)文件的文件名及時間戳。以三個減號()開始的行標(biāo)識的是原始文件,以三個加號(+++)開始的行標(biāo)識的是目標(biāo)文件。在比較內(nèi)容中,以減號(-)開始的行是只出現(xiàn)在原始文件中的行,例如:第4、13、14行。在比較內(nèi)容中,以加號(+)開始的行是只出現(xiàn)在目標(biāo)文件中的行,例如:第5行和16-18行。在比較內(nèi)容中,以空格開始的行,是在原始文件和目標(biāo)文件中都出現(xiàn)的行,例如:第6-8、10-12和第15行。這些行是用作差異比較的上下文。第3-8行是第一個差異小節(jié)。每個差異小節(jié)以一行差異定位語句開始。第3行就是一條差異定位語句,其前后分別用兩個@進(jìn)行標(biāo)識。第3行定位語句中-1,4的含義是:本差異小節(jié)的內(nèi)容相當(dāng)于原始文件的從第1行開始的4行。而第4、6、7、8行是原始文件中的內(nèi)容,加起來剛好是4行。第3行定位語句中+1,4的含義是:本差異小節(jié)的內(nèi)容相當(dāng)于目標(biāo)文件的從第1行開始的4行。而第5、6、7、8行是目標(biāo)文件中的內(nèi)容,加起來剛好是4行。因為命令diff是用于行比較的,所以即使改正了一個字,也顯示為一整行的修改(參見差異文件第4、5行)。Git對diff進(jìn)行了擴展,并且還提供一種逐詞比較的差異比較方法,參見本書第2篇的第11.4.4小節(jié)。第9-18行是第二個差異小節(jié)。第9行是一條差異定位語句。第9行定位語句中-6,6的含義是:本差異小節(jié)的內(nèi)容相當(dāng)于原始文件的從第6行開始的6行。第10-15行是原始文件中的內(nèi)容,加起來剛好是6行。第9行定位語句中+6,7的含義是:本差異小節(jié)的內(nèi)容相當(dāng)于目標(biāo)文件的從第6行開始的7行。而第10-12、15-18行是目標(biāo)文件中的內(nèi)容,加起來剛好是7行。2.命令patch相當(dāng)于diff的反向操作有了hello和diff.txt文件,可以放心地將world文件刪除或用hello文件將world文件覆蓋。用下面的命令可以還原world文件:$cphelloworld$patchworld<diff.txt也可以保留world和diff.txt文件,刪除hello文件或用word文件將hello文件覆蓋。用下面的命令可以恢復(fù)hello文件:$cpworldhello$patch-Rhello<diff.txt命令diff和patch還可以對目錄進(jìn)行比較操作,這也就是Linus在1991~2002年用于維護(hù)Linux不同版本間差異的辦法。在沒有版本控制系統(tǒng)的情況下,可以用此命令記錄并保存改動前后的差異,還可以將差異文件注入版本控制系統(tǒng)(如果有的話)。標(biāo)準(zhǔn)的diff和patch命令存在一個局限,就是不能對二進(jìn)制文件進(jìn)行處理。對二進(jìn)制文件的修改或添加會在差異文件中缺失,進(jìn)而丟失對二進(jìn)制文件的改動或添加。Git對差異文件格式提供了擴展支持,支持二進(jìn)制文件的比較,解決了這個問題。這一點可以參考本書第7篇第38章的相關(guān)內(nèi)容。\h[1]LinusTorvalds于2007年5月3日在Google的演講:/watch?v=4XpnKHJAok8\h[2]此處是故意將“字”寫成“子”,以便兩個文件進(jìn)行差異比較。1.2CVS——開啟版本控制大爆發(fā)CVS(ConcurrentVersionsSystem)\h[1]誕生于1985年,是由荷蘭阿姆斯特丹VU大學(xué)的DickGrune教授實現(xiàn)的。當(dāng)時DickGrune和兩個學(xué)生共同開發(fā)一個項目,但是三個人的工作時間無法協(xié)調(diào)到一起,迫切需要一個記錄和協(xié)同開發(fā)的工具軟件。于是DickGrune通過腳本語言對RCS(一個針對單獨文件的版本管理工具)進(jìn)行封裝,設(shè)計出有史以來第一個被大規(guī)模使用的版本控制工具。Dick教授的網(wǎng)站上介紹了CVS的這段早期歷史。\h[2]“在1985年的一個糟糕的秋日里,我在校汽車站等車回家,腦海里一直糾結(jié)著一件事——如何處理RCS文件、用戶文件(工作區(qū))和Entries文件的復(fù)雜關(guān)系,有的文件可能會缺失、沖突、刪除,等等。我的頭有些暈了,于是決定畫一個大表,將復(fù)雜的關(guān)聯(lián)畫在其中,看看出來的結(jié)果是什么樣的……”1986年Dick通過新聞組發(fā)布了CVS,1989年BrianBerliner用C語言將CVS進(jìn)行了重寫。從CVS的歷史可以看出,CVS不是設(shè)計出來的,而是被實際需要“逼”出來的,因此根據(jù)“實用為上”的原則,借用了已有的針對單一文件的版本管理工具RCS。CVS采用客戶端/服務(wù)器架構(gòu)設(shè)計,版本庫位于服務(wù)器端,實際上就是一個RCS文件容器。每一個RCS文件以",v"作為文件名后綴,用于保存對應(yīng)文件的每一次更改歷史。RCS文件中只保留一個版本的完全拷貝,其他歷次更改僅將差異存儲其中,使得存儲變得非常有效率。我在2008年設(shè)計了一個SVN管理后臺pySvnManager\h[3],實際上也采用了RCS作為SVN授權(quán)文件的變更記錄的“數(shù)據(jù)庫”。圖1-1展示了CVS版本控制系統(tǒng)的工作原理,可以看到作為RCS文件容器的CVS版本庫和工作區(qū)目錄結(jié)構(gòu)的一一對應(yīng)關(guān)系。圖1-1CVS版本控制系統(tǒng)示意圖CVS這種實現(xiàn)方式的最大好處就是簡單。把版本庫中任意一個目錄拿出來就可以成為另外一個版本庫。如果將版本庫中的一個RCS文件重命名,工作區(qū)檢出的文件名也會相應(yīng)地改變。這種低成本的服務(wù)器管理模式成為很多CVS粉絲至今不愿離開CVS的原因。CVS的出現(xiàn)讓軟件工程師認(rèn)識到了原來還可以這樣工作。CVS成功地為后來的版本控制系統(tǒng)確立了標(biāo)準(zhǔn),像提交說明(commitlog)、檢入(checkin)、檢出(checkout)、里程碑(tag)、分支(branch)等概念在CVS中早就已經(jīng)確立。CVS的命令行格式也被后來的版本控制系統(tǒng)競相模仿。在2001年,我正為使用CVS激動不已的時候,公司領(lǐng)導(dǎo)要求采用和美國研發(fā)部門同樣的版本控制解決方案。于是,我的項目組率先進(jìn)行了從CVS到該商業(yè)版本控制工具的遷移\h[4]。雖然商業(yè)版本控制工具有更漂亮的界面及更好的產(chǎn)品整合性,但是就版本控制本身而言,商業(yè)版本控制工具存在著如下缺陷。采用黑盒子式的版本庫設(shè)計。讓人捉摸不透的版本庫設(shè)計,最主要的目的可能就是阻止用戶再遷移到其他平臺。缺乏版本庫整理工具。如果有一個文件(如記錄核彈引爆密碼的文件)檢入到版本庫中,就無法再徹底移除它。商業(yè)版本控制工具很難為個人提供版本控制解決方案,除非個人愿意花費高昂的許可證費用。商業(yè)版本控制工具注定是小眾軟件,新員工的培訓(xùn)成本不可忽視。而上述商業(yè)版本控制系統(tǒng)的缺點恰恰是CVS及其他開源版本控制系統(tǒng)的優(yōu)點。但在經(jīng)歷了最初的成功之后,CVS也盡顯疲態(tài):服務(wù)器端松散的RCS文件導(dǎo)致在建立里程碑或分支時效率不高,服務(wù)器端文件越多,速度越慢。分支和里程碑不可見,因為它們被分散地記錄在服務(wù)器端的各個RCS文件中。合并困難重重,因為缺乏對合并的追蹤,從而導(dǎo)致重復(fù)合并,引發(fā)嚴(yán)重沖突。缺乏對原子提交的支持,會導(dǎo)致客戶端向服務(wù)器端提交不完整的數(shù)據(jù)。不能優(yōu)化存儲內(nèi)容相同但文件名不同的文件,因為在服務(wù)器端每個文件都是單獨進(jìn)行差異存儲的。不能對文件和目錄的重命名進(jìn)行版本控制,雖然直接在服務(wù)器端修改RCS文件名可以讓改名后的文件保存歷史,但是這樣做實際上會破壞歷史。CVS的成功導(dǎo)致了版本控制系統(tǒng)的大爆發(fā),各式各樣的版本控制系統(tǒng)如雨后春筍般誕生了。新的版本控制系統(tǒng)或多或少地解決了CVS版本控制系統(tǒng)存在的問題。在這些版本控制系統(tǒng)中,最典型的就是Subversion(SVN)。\h[1]/cvs/\h[2]/Programs/CVS.orig/\h[3]\h[4]于是就有了這篇文章:/doc/cvs_vs_starteam1.3SVN——集中式版本控制集大成者Subversion\h[1],由于其命令行工具名為svn,因此通常被簡稱為SVN。SVN由CollabNet公司于2000年資助并開始開發(fā),目的是創(chuàng)建一個更好用的版本控制系統(tǒng)以取代CVS。SVN的前期開發(fā)使用CVS做版本控制,到了2001年,SVN已經(jīng)可以用于自己的版本控制了\h[2]。我開始真正關(guān)注SVN是在2005年,那時SVN正經(jīng)歷著后端存儲上的變革,即從BDB(簡單的關(guān)系型數(shù)據(jù)庫)到FSFS(文件數(shù)據(jù)庫)的轉(zhuǎn)變。相對于BDB而言,F(xiàn)SFS具有穩(wěn)定、免維護(hù)和實現(xiàn)的可視性高等優(yōu)點,于是我馬上就被SVN吸引了。圖1-2展示了SVN版本控制系統(tǒng)的工作原理。圖1-2SVN版本控制系統(tǒng)示意圖SVN的每一次提交,都會在服務(wù)器端的db/revs和db/revprops目錄下各創(chuàng)建一個以順序數(shù)字編號命名的文件。其中,db/revs目錄下的文件(即變更集文件)記錄了與上一個提交之間的差異(字母A表示新增,M表示修改,D表示刪除)。在db/revprops目錄下的同名文件(沒有在圖1-2中體現(xiàn))則保存著提交日志、作者、提交時間等信息。這樣設(shè)計的好處有:擁有全局版本號。每提交一次,SVN的版本號就會自動加一。這為SVN的使用提供了極大的便利?;叵隒VS時代,每個文件都擁有各自獨立的版本號(RCS版本號),要想獲得全局版本號,只能通過手工不斷地建立里程碑來實現(xiàn)。實現(xiàn)了原子提交。SVN不會像CVS那樣出現(xiàn)文件的部分內(nèi)容被提交而其余的內(nèi)容沒有被提交的情況。文件名不受限制。因為服務(wù)器端不再需要建立和客戶端文件相似的文件名,于是,文件的命名就不再受服務(wù)器操作系統(tǒng)的字符集和大小寫的限制。文件和目錄重命名也得到了支持。SVN最具有特色的功能是輕量級拷貝,例如將目錄trunk拷貝為branches/v1.x只相當(dāng)于在db/revs目錄中的變更集文件中用特定的語法做了一下標(biāo)注,無須真正的文件拷貝。SVN使用輕量級拷貝的功能,輕松地解決了CVS存在的里程碑和分支的創(chuàng)建速度慢又不可見的問題,使用SVN創(chuàng)建里程碑和分支只在眨眼之間。SVN在版本庫授權(quán)上也有改進(jìn),不再像CVS那樣依賴操作系統(tǒng)本身對版本庫目錄和文件進(jìn)行授權(quán),而是采用授權(quán)文件的方式來實現(xiàn)。SVN還有一個創(chuàng)舉,就是在工作區(qū)跟蹤目錄下(.svn目錄)為當(dāng)前目錄中的每一個文件都保存一份冗余的原始拷貝。這樣做的好處是部分命令不再需要網(wǎng)絡(luò)連接,例如文件修改的差異比較,以及錯誤更改的回退等。正是由于這些閃亮的功能特性,才使得SVN在CVS之后誕生的諸多版本控制系統(tǒng)中脫穎而出,成為開源社區(qū)一時的新寵,也成為當(dāng)時各個企業(yè)進(jìn)行版本控制的最佳選擇之一。但是,相對于CVS,SVN在本質(zhì)上并沒有突破,都屬于集中式版本控制系統(tǒng)。即一個項目只有唯一的一個版本庫與之對應(yīng),所有的項目成員都通過網(wǎng)絡(luò)向該服務(wù)器進(jìn)行提交。這樣的設(shè)計除了容易出現(xiàn)單點故障以外,在查看日志和提交數(shù)據(jù)等操作時的延遲,會讓基于廣域網(wǎng)協(xié)同工作的團(tuán)隊抓狂。除了集中式版本控制系統(tǒng)固有的問題外,SVN的里程碑和分支的設(shè)計也被證明是一個錯誤,雖然這個錯誤的設(shè)計使得SVN擁有了快速創(chuàng)建里程碑和分支的能力,但是這個錯誤的設(shè)計也導(dǎo)致了如下的更多問題。項目文件在版本庫中必須按照一定的目錄結(jié)構(gòu)進(jìn)行部署,否則就可能無法建立里程碑和分支。我在項目咨詢過程中見過很多團(tuán)隊,直接在版本庫的根目錄下創(chuàng)建項目文件。這樣的版本庫布局,在需要創(chuàng)建里程碑和分支時就無從下手了,因為根目錄是不能拷貝到子目錄中的。所以SVN的用戶在創(chuàng)建版本庫時必須遵守一個古怪的約定:先創(chuàng)建三個頂級目錄/trunk、/tags和/branches。創(chuàng)建里程碑和分支會破壞精心設(shè)計的授權(quán)。SVN的授權(quán)是基于目錄的,分支和里程碑也被視為目錄(和其他目錄沒有分別)。因此每次創(chuàng)建分支或里程碑時,就要將針對/trunk目錄及其子目錄的授權(quán)在新建的分支或里程碑上重建。隨著分支和里程碑?dāng)?shù)量的增多,授權(quán)愈加復(fù)雜,維護(hù)也愈加困難。分支太隨意從而導(dǎo)致混亂。SVN的分支創(chuàng)建非常隨意:可以基于/trunk目錄創(chuàng)建分支,也可以基于其他任何目錄創(chuàng)建分支,因此SVN很難畫出一個有意義的分支圖。再加上一次提交可以同時包含針對不同分支的文件變更,使得事情變得更糟。雖然SVN在1.5版之后擁有了合并追蹤功能,但這個功能會因為混亂的分支管理而被抵消。2009年年底,SVN由CollabNet公司交由Apache社區(qū)管理,至此SVN成為了Apache組織的一個子項目\h[3]。這對SVN到底意味著什么?是開發(fā)的停滯?還是新的開始?結(jié)果如何我們將拭目以待。\h[1]/\h[2]/en/1.5/ro.whatis.html#ro.history\h[3]/wiki/Apache_Subversion1.4Git——Linus的第二個偉大作品Linux之父Linus是堅定的CVS反對者,他也同樣地反對SVN。這就是為什么在1991-2002這十余年間,Linus寧可以手工修補文件的方式維護(hù)代碼,也遲遲不愿使用CVS的原因。我想在當(dāng)時要想勸說Linus使用CVS只有一個辦法:把CVS服務(wù)器請進(jìn)Linus的臥室,并對外配以千兆帶寬。2002年至2005年,Linus頂著開源社區(qū)精英們口誅筆伐的壓力,選擇了一個商業(yè)版本控制系統(tǒng)BitKeeper作為Linux內(nèi)核的代碼管理工具\h[1]。BitKeeper不同于CVS和SVN等集中式版本控制工具,而是一款分布式版本控制工具。分布式版本控制系統(tǒng)最大的反傳統(tǒng)之處在于,可以不需要集中式的版本庫,每個人都工作在通過克隆建立的本地版本庫中。也就是說每個人都擁有一個完整的版本庫,查看提交日志、提交、創(chuàng)建里程碑和分支、合并分支、回退等所有操作都直接在本地完成而不需要網(wǎng)絡(luò)連接。每個人都是本地版本庫的主人,不再有誰能提交誰不能提交的限制,加上多樣的協(xié)同工作模型(版本庫間推送、拉回,以及補丁文件傳送等)讓開源項目的參與度有爆發(fā)式增長。2005年發(fā)生的一件事最終導(dǎo)致了Git的誕生。在2005年4月,AndrewTridgell(即大名鼎鼎的Samba的作者)試圖對BitKeeper進(jìn)行反向工程,以開發(fā)一個能與BitKeeper交互的開源工具。這激怒了BitKeeper軟件的所有者BitMover公司,要求收回對Linux社區(qū)免費使用BitKeeper的授權(quán)\h[2]。迫不得已,Linus選擇了自己開發(fā)一個分布式版本控制工具以替代BitKeeper。以下是Git誕生過程中的大事記\h[3]:2005年4月3日,開始開發(fā)Git。2005年4月6日,項目發(fā)布。2005年4月7日,Git就可以作為自身的版本控制工具了。2005年4月18日,發(fā)生第一個多分支合并。2005年4月29日,Git的性能就已經(jīng)達(dá)到了Linus的預(yù)期。2005年6月16日,Linux內(nèi)核2.6.12發(fā)布,那時Git已經(jīng)在維護(hù)Linux核心的源代碼了。Linus以一個文件系統(tǒng)專家和內(nèi)核設(shè)計者的視角對Git進(jìn)行了設(shè)計,其獨特的設(shè)計讓Git擁有非凡的性能和最為優(yōu)化的存儲能力。完成原型設(shè)計后,在2005年7月26日,Linus功成身退,將Git的維護(hù)交給另外一個Git的主要貢獻(xiàn)者JunioCHamano\h[4],直到現(xiàn)在。最初的Git除了一些核心命令以外,其他的都用腳本語言開發(fā),而且每個功能都作為一條獨立的命令,例如克隆操作用git-clone,提交操作用git-commit。這導(dǎo)致Git擁有龐大的命令集,使用習(xí)慣也和其他版本控制系統(tǒng)格格不入。隨著Git的開發(fā)者和使用者的增加,Git也在逐漸演變,例如到1.5.4版本時,將一百多個獨立的命令封裝為一個git命令,使它看起來更像是一個獨立的工具,也使Git更貼近于普通用戶的使用習(xí)慣。經(jīng)過短短幾年的發(fā)展,眾多的開源項目都紛紛從SVN或其他版本控制系統(tǒng)遷移到Git。雖然版本控制系統(tǒng)的遷移過程是痛苦的,但是因為遷移到Git會帶來開發(fā)效率的極大提升,以及巨大的效益,所以很快就會忘記遷移的痛苦過程,而且很快就會適應(yīng)新的工作模式。在Git的官方網(wǎng)站上列出了幾個使用Git的重量級項目,每一個都是人們耳熟能詳?shù)?,除了Git和Linux內(nèi)核外,還有Perl、Eclipse、Gnome、KDE、Qt、RubyonRails、Android、PostgreSQL、Debian、X.org,當(dāng)然還有GitHub的上百萬個項目。Git雖然是在Linux下開發(fā)的,但現(xiàn)在已經(jīng)可以跨平臺運行在所有主流的操作系統(tǒng)上,包括Linux、MacOSX和Windows等??梢哉f每一個使用計算機的用戶都可以分享Git帶來的便利和快樂。\h[1]/wiki/BitKeeper\h[2]/wiki/Andrew_Tridgell\h[3]/wiki/Git_%28software%29\h[4]/?l=git&m=112243466603239第2章愛上Git的理由本章將通過一些典型應(yīng)用展示Git作為版本控制系統(tǒng)的獨特用法,不熟悉版本控制系統(tǒng)的讀者可以通過這些示例對版本控制擁有感性的認(rèn)識。如果是有經(jīng)驗的讀者,示例中Git和SVN的對照可以讓您體會到Git的神奇和強大。本章將列舉Git的一些閃亮特性,期待能夠讓您愛上Git。2.1每日工作備份當(dāng)我開始撰寫本書時才明白寫書真的是一個辛苦活。如何讓辛苦的工作不會因為筆記本硬盤的意外損壞而丟失?如何防范災(zāi)害而不讓一個籃子里的雞蛋都?xì)в谝坏??下面就介紹一下我在寫本書時是如何使用Git進(jìn)行文稿備份的,請看圖2-1。圖2-1利用Git做數(shù)據(jù)的備份如圖2-1所示,我的筆記本在公司局域網(wǎng)里的IP地址是00,公司的Git服務(wù)器的IP地址是。公司使用動態(tài)IP上網(wǎng)因而沒有固定的外網(wǎng)IP,但是公司在數(shù)據(jù)中心有托管服務(wù)器,擁有固定的IP地址,其中一臺服務(wù)器用作Git服務(wù)器鏡像。我的寫書習(xí)慣大概是這樣:在寫完一個小節(jié)或是畫完一張圖后,我會執(zhí)行下面的命令提交一次。每一天平均提交3-5次。提交是在本地完成的,因此在圖中沒有表示出來。$gitadd-u#如果創(chuàng)建了新文件,可以執(zhí)行g(shù)itadd-i命令。$gitcommit下班后,我會執(zhí)行一次推送操作,將我在本地Git版本庫中的提交同步到公司的Git服務(wù)器上。相當(dāng)于圖2-1中的步驟①。$gitpush因為公司的Git服務(wù)器和異地數(shù)據(jù)中心的Git服務(wù)器建立了鏡像,所以每當(dāng)我向公司內(nèi)網(wǎng)服務(wù)器推送的時候,就會自動觸發(fā)從內(nèi)網(wǎng)服務(wù)器到外網(wǎng)Git服務(wù)器的鏡像操作。這相當(dāng)于圖2-1中的步驟②,步驟②是自動執(zhí)行的,無須人工干預(yù)。圖2-1中標(biāo)記為mirror的版本庫就是Git鏡像版本庫,該版本庫只向用戶提供只讀訪問服務(wù),而不能對其進(jìn)行寫操作(推送)。從圖2-1中可以看出,我的每日工作保存有三個拷貝,一個在筆記本中,一個在公司內(nèi)網(wǎng)的服務(wù)器上,還有一個在外網(wǎng)的鏡像版本庫中。雞蛋分別裝在了三個籃子里。關(guān)于如何架設(shè)可以實時鏡像的Git服務(wù)器,會在本書第5篇第30章中詳細(xì)介紹。2.2異地協(xié)同工作為了能夠加快寫書的進(jìn)度,熬夜是必須的,這就出現(xiàn)了在公司和家里兩地工作同步的問題。圖2-2用于說明我是如何解決兩地工作同步問題的。圖2-2利用Git實現(xiàn)異地工作協(xié)同我在家里的電腦IP地址是00(家里也有一個小局域網(wǎng))。如果在家里有時間工作的話,首先要做的就是圖2-2中步驟③的操作:將mirror版本庫中的數(shù)據(jù)同步到本地。只需要一條命令就好了:$gitpullmirrormaster然后在家里的電腦上繼續(xù)編寫書稿并提交。當(dāng)準(zhǔn)備完成一天的工作后,就執(zhí)行下面的命令,相當(dāng)于圖2-2中步驟④的操作:將在家中的提交推送到標(biāo)記為home的版本庫中。$gitpushhome為什么還要再引入另外一個名為home的版本庫呢?使用mirror版本庫不好么?不要忘了mirror版本庫只是一個鏡像庫,不能提供寫操作。當(dāng)一早到公司,開始動筆寫書之前,先要執(zhí)行圖2-2中步驟⑤的操作,從home版本庫將家里做的提交同步到公司的電腦中。$gitpullhomemaster公司的小崔是我這本書的忠實讀者,每當(dāng)有新章節(jié)完成,他都會執(zhí)行圖2-2中步驟⑥的工作,從公司內(nèi)網(wǎng)服務(wù)器獲取我最新的文稿。$gitpull一旦發(fā)現(xiàn)文字錯誤,小崔會直接在文稿中修改,然后推送到公司的服務(wù)器上(圖2-2中步驟⑦)。當(dāng)然他的這個推送也會自動同步到外網(wǎng)的mirror版本庫。$gitpush而我只要執(zhí)行g(shù)itpull操作就可以獲得小崔對文稿的修訂(圖2-2中的步驟⑧)。采用這種工作方式,文稿竟然分布在5臺電腦上擁有6個拷貝,真可謂狡兔三窟。不,比狡兔還要多三窟。在本節(jié)中,出現(xiàn)在Git命令中的mirror和home是和工作區(qū)關(guān)聯(lián)的遠(yuǎn)程版本庫。關(guān)于如何注冊和使用遠(yuǎn)程版本庫,請參見本書第3篇第19章中的內(nèi)容。2.3現(xiàn)場版本控制所謂現(xiàn)場版本控制,就是在客戶現(xiàn)場或在產(chǎn)品部署的現(xiàn)場進(jìn)行源代碼的修改,并在修改過程中進(jìn)行版本控制,以便在完成修改后能夠?qū)⑿薷慕Y(jié)果甚至修改過程一并帶走,并能夠?qū)⑿薷慕Y(jié)果合并至項目對應(yīng)的代碼庫中。1.SVN的解決方案如果使用SVN進(jìn)行版本控制,首先要將服務(wù)器上部署的產(chǎn)品代碼目錄變成SVN工作區(qū),這個過程不僅不簡單,而且會顯得很繁瑣,最后將改動結(jié)果導(dǎo)出也非常不方便,具體操作過程如下。(1)在其他位置建立一個SVN版本庫。$svnadmincreate/path/to/repos/project1(2)在需要版本控制的目錄下檢出剛剛建立的空版本庫。$svncheckoutfile:///path/to/repos/project1.(3)執(zhí)行添加文件操作,然后執(zhí)行提交操作。這個提交將是版本庫中編號為1的提交。$svnadd*$svnci-m"initialized"(4)開始在工作區(qū)中修改文件并提交。$svnci(5)如果對修改結(jié)果滿意,可以通過創(chuàng)建補丁文件的方式將工作成果保存并帶走。但是SVN很難針對每次提交逐一創(chuàng)建補丁,一般用下面的命令與最早的提交進(jìn)行比較,以創(chuàng)建出一個大補丁文件。$svndiff-r1>hacks.patch上面用SVN將工作成果導(dǎo)出的過程存在一個致命的缺陷,就是SVN的補丁文件不支持二進(jìn)制文件,因此采用補丁文件的方式有可能丟失數(shù)據(jù),如新增或修改的圖形文件會丟失。更為穩(wěn)妥但也更為復(fù)雜的方式可能要用到svnadmin命令將版本庫導(dǎo)出。命令如下:$svnadmindump--incremental-r2:HEAD\/path/to/repos/project1/>hacks.dump將svnadmin命令創(chuàng)建的導(dǎo)出文件恢復(fù)到版本庫中也非常具有挑戰(zhàn)性,這里就不再詳細(xì)說明了。還是來看看Git在這種情況下的表現(xiàn)吧。2.Git的解決方案與SVN將產(chǎn)品部署目錄轉(zhuǎn)化為SVN的工作區(qū)相比,Git要更為簡單,而且使用Git導(dǎo)出提交歷史也更為簡單和實用,具體操作過程如下。(1)創(chuàng)建現(xiàn)場版本庫。直接在需要版本控制的目錄下執(zhí)行Git版本庫初始化命令。$gitinit(2)添加文件并提交。$gitadd-A$gitcommit-m"initialized"(3)為初始提交建立一個里程碑:"v1"。$gittagv1(4)開始在工作區(qū)中工作——修改文件并提交。$gitcommit-a(5)當(dāng)對修改結(jié)果滿意并想將工作成果保存帶走時,可以通過下面的命令將從v1開始的歷次提交逐一導(dǎo)出為補丁文件。轉(zhuǎn)換的補丁文件都包含一個數(shù)字前綴,并提取提交日志信息作為文件名,而且補丁文件還提供對二進(jìn)制文件的支持。下面命令的輸出摘自本書第3篇第20章中的實例。$gitformat-patchv1..HEAD0001-Fix-typo-help-to-help.patch0002-Add-I18N-support.patch0003-Translate-for-Chinese.patch(6)通過郵件將補丁文件發(fā)出。當(dāng)然,也可以通過其他方式將補丁文件帶走。$gitsend-email*.patchGit創(chuàng)建的補丁文件使用了Git擴展格式,因此在導(dǎo)入時為了避免數(shù)據(jù)遺漏,要使用Git提供的命令而不能使用GNU的patch命令。即使要導(dǎo)入的不是Git版本庫,也可以使用Git命令,具體操作請參見本書第7篇第38章中的相關(guān)內(nèi)容。2.4避免引入輔助目錄很多版本控制系統(tǒng)都要在工作區(qū)中引入輔助目錄或文件,如SVN要在工作區(qū)的每一個子目錄下都創(chuàng)建.svn目錄,CVS要在工作區(qū)的每一個子目錄下都創(chuàng)建CVS目錄。這些輔助目錄如果出現(xiàn)在服務(wù)器上,尤其是Web服務(wù)器上是非常危險的,因為這些輔助目錄下的Entries文件會暴露出目錄下的文件列表,讓管理員精心配置的禁止目錄瀏覽的努力全部白費。還有,SVN的.svn輔助目錄下還存在文件的原始拷貝,在文件搜索時結(jié)果會加倍。如果你曾經(jīng)在SVN的工作區(qū)用過grep命令進(jìn)行內(nèi)容查找,就會明白我指的是什么。Git沒有這個問題,不會在子目錄下引入討厭的輔助目錄或文件(.gitignore和.gitattributes文件不算)。當(dāng)然,Git還是要在工作區(qū)的頂級目錄下創(chuàng)建名為.git的目錄(版本庫目錄),不過,如果你認(rèn)為唯一的一個.git目錄也過于礙眼,可以將其放到工作區(qū)之外的任意目錄。一旦這么做了,在執(zhí)行Git命令時,就要通過命令行(--git-dir)或環(huán)境變量GIT_DIR為工作區(qū)指定版本庫目錄,甚至還要指定工作區(qū)目錄。Git還專門提供了一個gitgrep命令,這樣在工作區(qū)根目錄下執(zhí)行查找時,目錄.git也不會對搜索造成影響。關(guān)于輔助目錄的詳細(xì)討論請參見本書第2篇第4.2節(jié)中的內(nèi)容。2.5重寫提交說明很多人可能像我一樣,在敲下回車之后才發(fā)現(xiàn)提交說明中有錯別字,或忘記了寫關(guān)聯(lián)的BugID,此時就需要重寫提交說明。1.SVN的解決方案在默認(rèn)情況下,SVN的提交說明是禁止更改的,因為SVN的提交說明屬于不受版本控制的屬性,一旦修改就不可恢復(fù)。我建議SVN的管理員只有在配置了版本庫更改的外發(fā)郵件通知之后,再開放提交說明更改的功能。我發(fā)布于SourceForge上的pySvnManager項目提供了SVN版本庫圖形化的鉤子管理,會簡化管理員的配置工作。即使SVN管理員啟用了允許更改提交說明的設(shè)置,修改提交說明也還是挺復(fù)雜的,看看下面的命令:$svnps--revprop-r<REV>svn:log"newlogmessage..."2.Git的解決方案Git修改提交說明很簡單,而且提交說明的修改也是被追蹤的。Git修改最新提交的提交說明最為簡單,使用一條名為修補提交的命令即可。$gitcommit--amend這個命令如果不帶-m參數(shù),會進(jìn)入提交說明編輯界面,修改原來的提交說明,直到滿意為止。如果要修改某個歷史提交的提交說明,Git也可以實現(xiàn),但要用到另外一個命令:變基命令。例如,要修改<commit-id>所標(biāo)識的提交的提交說明,執(zhí)行下面的命令,并在彈出的變基索引文件中修改相應(yīng)提交前面的動作的關(guān)鍵字。$gitrebase-i<commit-id>^關(guān)于如何使用交互式變基操作更改歷史提交的提交說明,請參見本書第2篇第12章中的內(nèi)容。2.6想吃后悔藥假如提交的數(shù)據(jù)中不小心包含了一個不應(yīng)該檢入的虛擬機文件——大約有1個GB!這時候,您會多么希望這個世界上有后悔藥賣啊。1.SVN的解決方案SVN遇到這個問題該怎么辦呢?刪除錯誤加入的大文件后再提交,這樣的操作是不能解決問題的。雖然表面上去掉了這個文件,但是它依然存在于歷史中。管理員可能是受影響最大的人,因為他要負(fù)責(zé)管理服務(wù)器的磁盤空間占用及版本庫的備份。實際上這個問題也只有管理員才能解決,所以你必須向管理員坦白,讓他幫你在服務(wù)器端徹底刪除錯誤引入的大文件。我要告訴你的是,對于管理員,這并不是一個簡單的活。(1)如果SVN管理員沒有歷史備份,只能重新用svnadmindump導(dǎo)出整個版本庫。(2)再用svndumpfilter命令過濾掉不應(yīng)檢入的大文件。(3)然后用svnadminload重建版本庫。上面的操作描述中省略了一些竅門,如果要把竅門講清楚,這本書就不是講Git,而是講SVN了,故本書中不進(jìn)行深入探討。2.Git的解決方案如果你用Git,一切就會變得非常簡單,而且你也不必去乞求管理員,因為使用Git,每個人都是管理員。如果是最新的提交引入了不該提交的大文件:winxp.img,操作起來會非常簡單,還是用修補提交命令。$gitrm--cachedwinxp.img$gitcommit--amend如果是歷史版本,例如是在<commit-id>所標(biāo)識的提交中引入的文件,則需要使用變基操作。$gitrebase-i<commit-id>^執(zhí)行交互式變基操作拋棄歷史提交,版本庫還不能立即瘦身,具體原因和解決方案請參見本書第2篇第14章中的內(nèi)容。除了使用變基操作,Git還有更多的武器可以實現(xiàn)版本庫的整理操作,具體請參見本書第6篇第35.4節(jié)的內(nèi)容。2.7更好用的提交列表正確的版本控制系統(tǒng)的使用方法是,一次提交只干一件事:或是完成了一個新功能,或是修改了一個Bug、或是寫完了一節(jié)的內(nèi)容,或是添加了一幅圖片,就執(zhí)行一次提交。不要在下班時才想起來要提交,那樣的話版本控制系統(tǒng)就被降格為文件備份系統(tǒng)了。但有時在同一個工作區(qū)中可能要同時做兩件事情:一個是尚未完成的新功能,另外一個是解決剛剛發(fā)現(xiàn)的Bug。很多版本控制系統(tǒng)沒有提交列表的概念,要么需要在命令行中指定要提交的文件,要么默認(rèn)把所有修改內(nèi)容全部提交,破壞了一次提交只干一件事的原則。1.SVN的解決方案SVN1.5開始提供變更列表(changelist)的功能,是通過引入一個新的命令svnchangelist來實現(xiàn)的。但是我從來就沒有真正用過,因為:定義一個變更列表太麻煩。例如,沒有一個快捷命令將當(dāng)前所有改動的文件加入列表,也沒有快捷命令將工作區(qū)中的新文件全部加入列表。一個文件不能同時屬于兩個變更列表。兩次變更不許有文件交叉,這樣的限制不合理。變更列表是一次性的,提交之后自動消失。這樣的設(shè)計沒有問題,但是相比定義列表時的繁瑣,以及提交時必須指定列表的繁瑣,使用變更列表未免得不償失。因為Subversion的提交不能撤銷,如果在提交時忘了提供變更列表名稱以針對特定的變更列表進(jìn)行提交,錯誤的提交內(nèi)容將無法補救??傊?,SVN的變更列表尚不如雞肋,食之無味,棄之不可惜。2.Git的解決方案Git通過提交暫存區(qū)實現(xiàn)對提交內(nèi)容的定制,非常完美地實現(xiàn)了對工作區(qū)的修改內(nèi)容進(jìn)行篩選提交:執(zhí)行g(shù)itadd命令將修改內(nèi)容加入提交暫存區(qū)。執(zhí)行g(shù)itadd-u命令可以將所有修改過的文件加入暫存區(qū),執(zhí)行g(shù)itadd-A命令可以將本地刪除文件和新增文件都登記到提交暫存區(qū),執(zhí)行g(shù)itadd-p命令甚至可以對一個文件內(nèi)的修改進(jìn)行有選擇性的添加。一個修改后的文件被登記到提交暫存區(qū)后,可以繼續(xù)修改,繼續(xù)修改的內(nèi)容不會被提交,除非對此文件再執(zhí)行一次gitadd命令。即一個修改的文件可以擁有兩個版本,在提交暫存區(qū)中有一個版本,在工作區(qū)中有另外一個版本。執(zhí)行g(shù)itcommit命令提交,無須設(shè)定變更列表,直接將登記在暫存區(qū)中的內(nèi)容提交。Git支持撤銷提交,而且可以撤銷任意多次。只要使用Git,就會時刻與隱形的提交列表打交道。本書第2篇第5章會詳細(xì)介紹Git的這一特性,相信你會愛上Git的這個特性。2.8更好的差異比較Git對差異比較進(jìn)行了擴展,支持對二進(jìn)制文件的差異比較,這是對GNU的diff和patch命令的重要補充。而且Git的差異比較除了支持基于行的差異比較外,還支持在一行內(nèi)逐字比較的方式,當(dāng)向gitdiff命令傳遞--word-diff參數(shù)時,就會進(jìn)行逐字比較。上面介紹了工作區(qū)的文件修改可能會有兩個不同的版本:一個在提交暫存區(qū),一個在工作區(qū)。因此,在執(zhí)行g(shù)itdiff命令時會遇到令Git新手費解的現(xiàn)象。修改后的文件在執(zhí)行g(shù)itdiff命令時會看到修改造成的差異。修改后的文件通過gitadd命令提交到暫存區(qū)后,再執(zhí)行g(shù)itdiff命令將看不到該文件的差異。繼續(xù)對此文件進(jìn)行修改,再次執(zhí)行g(shù)itdiff命令會看到新的修改顯示在差異中,而看不到舊的修改。執(zhí)行g(shù)itdiff--cached命令才可以看到添加到暫存區(qū)中的文件所做出的修改。Git差異比較的命令充滿了魔法,本書第5.3節(jié)會帶您破解Git的diff魔法。一旦您習(xí)慣了,就會非常喜歡gitdiff的這個行為。2.9工作進(jìn)度保存如果在工作區(qū)的修改尚未完成時忽然有一個緊急的任務(wù),需要從一個干凈的工作區(qū)開始新的工作,或要切換到別的分支進(jìn)行工作,那么如何保存當(dāng)前尚未完成的工作進(jìn)度呢?1.SVN的解決方案如果版本庫規(guī)模不大,最好重新檢出一個新的工作區(qū),在新的工作區(qū)進(jìn)行工作。否則,可以執(zhí)行下面的操作。$svndiff>/path/to/saved/patch.file$svnrevert-R$svnswitch<new_branch>在新的分支中工作完畢后,再切換回當(dāng)前分支,將補丁文件重新應(yīng)用到工作區(qū)。$svnswitch<o(jì)riginal_branch>$patch-p1</path/to/saved/patch.file但是切記SVN的補丁文件不支持二進(jìn)制文件,這種操作方法可能會丟失對二進(jìn)制文件的更改!2.Git的解決方案Git提供了一個可以保存和恢復(fù)工作進(jìn)度的命令gitstash。這個命令非常方便地解決了這個難題。在切換到新的工作分支之前執(zhí)行g(shù)itstash保存工作進(jìn)度,工作區(qū)就會變得非常干凈,然后就可以切換到新的分支中了。$gitstash$gitcheckout<new_branch>新的工作分支修改完畢后,再切換回當(dāng)前分支,調(diào)用gitstashpop命令則可恢復(fù)之前保存的工作進(jìn)度。$gitcheckout<o(jì)rignal_branch>$gitstashpop本書第2篇第9章會為您揭開gitstash命令的奧秘。2.10代理SVN提交實現(xiàn)移動式辦公使用像SVN一樣的集中式版本控制系統(tǒng),要求使用者和版本控制服務(wù)器之間要有網(wǎng)絡(luò)連接,如果因為出差在外或在家辦公訪問不到版本控制服務(wù)器就無法提交。Git屬于分布式版本控制系統(tǒng),不存在這樣的問題。當(dāng)版本控制服務(wù)器無法實現(xiàn)從SVN到Git的遷移時,仍然可以使用Git進(jìn)行工作。在這種情況下,Git作為客戶端來操作SVN服務(wù)器,實現(xiàn)在移動辦公狀態(tài)下的版本提交(當(dāng)然是在本地Git庫中提交)。當(dāng)能夠連通SVN服務(wù)器時,一次性將移動辦公狀態(tài)下的本地提交同步到SVN服務(wù)器。整個過程對于SVN來說是透明的,沒有人知道你是使用Git在進(jìn)行提交。使用Git來操作SVN版本控制服務(wù)器的一般工作流程為:(1)訪問SVN服務(wù)器,將SVN版本庫克隆為一個本地的Git庫,一個貨真價實的Git庫,不過其中包含針對SVN的擴展。$gitsvnclone<svn_repos_url>(2)使用Git命令操作本地克隆的版本庫,例如提交就使用gitcommit命令。(3)當(dāng)能夠通過網(wǎng)絡(luò)連接到SVN服務(wù)器,并想將本地提交同步到SVN服務(wù)器時,先獲取SVN服務(wù)器上最新的提交,然后執(zhí)行變基操作,最后再將本地提交推送給SVN服務(wù)器。$gitsvnfetch$gitsvnrebase$gitsvndcommit本書第4篇第26章會詳細(xì)介紹這一話題。2.11無處不在的分頁器雖然擁有圖形化的客戶端,但Git的主要操作還是以命令行的方式完成的。使用命令行方式的好處一個是快,另外一個是可以防止鼠標(biāo)手的出現(xiàn)。Git的命令行加入了大量的人性化設(shè)計,包括命令補全、彩色字符輸出\h[1]等,不過最具特色的還是無處不在的分頁器。在操作其他版本控制系統(tǒng)的命令行時,如果命令的輸出超過了一屏,為了能夠逐屏顯示,需要在命令的后面加上一個管道符號將輸出交給一個分頁器。例如:$svnlog|less而Git則不用如此麻煩,因為每個Git命令自動帶有一個分頁器,默認(rèn)使用less命令(less-FRSX)進(jìn)行分頁。當(dāng)一屏顯示不下時啟動分頁器,這個分頁器支持帶顏色的字符輸出,對于太長的行則采用截斷方式處理。因為less分頁器在翻屏?xí)r使用了vi風(fēng)格的熱鍵,如果您不熟悉vi的話,可能會遇到麻煩。下面是分頁器中常用的熱鍵:字母q:退出分頁器。字母h:顯示分頁器幫助。按空格下翻一頁,按字母b上翻一頁。字母d和u:分別代表向下翻動半頁和向上翻動半頁。字母j和k:分別代表向上翻一行和向下翻一行。如果行太長被截斷,可以用左箭頭和右箭頭使窗口內(nèi)容左右滾動。輸入/pattern:向下尋找和pattern匹配的內(nèi)容。輸入?pattern:向上尋找和pattern匹配的內(nèi)容。字母n或N:代表向前或向后繼續(xù)尋找。字母g:跳到第一行;字母G:跳到最后一行;輸入數(shù)字再加字母g:則跳轉(zhuǎn)到對應(yīng)的行。輸入!<command>:可以執(zhí)行Shell命令。如果不習(xí)慣分頁器的長行截斷模式而希望能夠自動換行,可以通過設(shè)置LESS環(huán)境變量來實現(xiàn)。LESS環(huán)境變量設(shè)置如下:$exportLESS=FRX或者使用Git的方式,通過定義Git配置變量來改變分頁器的默認(rèn)行為。例如設(shè)置core.pager配置變量如下:$gitconfig--globalcore.pager'less-+$LESS-FRX'\h[1]須通過Git配置變量啟用,如運行命令:gitconfig--globalcolor.uitrue2.12快您有項目托管在的CVS或SVN服務(wù)器上么?是否會因為公司的SVN服務(wù)器部署在另外一個城市而需要經(jīng)過互聯(lián)網(wǎng)才能訪問?使用傳統(tǒng)的集中式版本控制服務(wù)器時,如果遇到上面的情況,而且網(wǎng)絡(luò)帶寬沒有保證,那么使用起來時一定會因為速度慢而讓人痛苦不堪。Git作為分布式版本控制系統(tǒng)徹底解決了這個問題,幾乎所有的操作都在本地進(jìn)行,而且速度還不是一般的快。還有很多其他的分布式版本控制系統(tǒng),如Hg和Bazaar等,與這些分布式版本控制系統(tǒng)相比,Git在速度上也有優(yōu)勢,這得益于Git獨特的版本庫設(shè)計。第2篇的相關(guān)章節(jié)會向您展示Git獨特的版本庫設(shè)計。其他很多的版本控制系統(tǒng),當(dāng)輸入檢出、更新或克隆等命令后,只能雙手合十,然后望眼欲穿,因為整個操作過程不知道什么時候才能夠完成。而Git在版本庫克隆及與版本庫同步的時候,能夠?qū)崟r地顯示完成的進(jìn)度,這不但是非常人性化的設(shè)計,更體現(xiàn)了Git的智能。Git的智能協(xié)議源自于會話過程中在客戶端和服務(wù)器端各自啟用了一個會話的角色,用于按需傳輸和獲取進(jìn)度。第3章Git的安裝和使用Git源自Linux,現(xiàn)在已經(jīng)可以部署在所有的主流平臺之上,包括Linux、MacOSX和Windows。我們在開始Git之旅之前,首先要做的就是安裝Git。3.1在Linux下安裝和使用GitGit誕生于Linux平臺并作為版本控制系統(tǒng)率先服務(wù)于Linux內(nèi)核,因此在Linux上安裝Git是非常方便的。可以通過兩種不同的方式在Linux上安裝Git:一種方法是通過Linux發(fā)行版的包管理器安裝已經(jīng)編譯好的二進(jìn)制格式的Git軟件包,另外一種方式就是從Git源碼開始安裝。3.1.1包管理器方式安裝用Linux發(fā)行版的包管理器安裝Git最為簡單,而且會自動配置好命令補齊等功能,但安裝的Git可能不是最新的版本。還有一點要注意,Git軟件包在有的Linux發(fā)行版中可能不叫g(shù)it,而叫g(shù)it-core。這是因為有一款名為GNU交互工具\h[1](GNUInteractiveTools)的GNU軟件,在Git之前就在一些Linux發(fā)行版(Deianlenny)中占用了git這個名稱。為了以示區(qū)分,作為版本控制系統(tǒng)的Git,其軟件包在這些平臺就被命名為git-core。不過,因為作為版本控制系統(tǒng)的Git太有名了,所以一些Linux發(fā)行版在最新的版本中將GNUInteractiveTools軟件包的名稱由git改為了gnuit,將git-core改為了git。因此在下面介紹的在不同的Linux發(fā)行版中安裝Git時,會看到有g(shù)it和git-core兩個不同的名稱。Ubuntu10.10(maverick)或更新的版本、Debian(
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年信用卡消費借款合同樣本
- 2025年廣告授權(quán)協(xié)議
- 2025年鉚接設(shè)備項目提案報告模板
- 2025年事業(yè)單位合同違約責(zé)任免除條件
- 2025年標(biāo)準(zhǔn)酒店股份投資合作合同文本
- 2025年公共安全視頻監(jiān)控系統(tǒng)分包安裝合同書
- 2025年英語合同模板大全
- 2025年城市擴建征收土地合同范文
- 2025年臨時電源項目協(xié)議
- 2025年建筑施工安全保險合同格式
- 高中英語高考讀后續(xù)寫巧用動作鏈專項練習(xí)(附參考答案和解析)
- MSOP(測量標(biāo)準(zhǔn)作業(yè)規(guī)范)測量SOP
- 肝癌個案護(hù)理課件
- 鄉(xiāng)鎮(zhèn)人大代表選舉結(jié)果情況報告單
- BOPP雙向拉伸薄膜及膠帶生產(chǎn)項目環(huán)境影響報告
- 《公路橋梁抗震設(shè)計規(guī)范》(2231-01-2020)
- 新技術(shù)和新項目準(zhǔn)入制度及要點解讀
- 員工待崗管理辦法
- 新學(xué)期新氣象PPT
- 天津高考英語詞匯3500
- 教育的第三只眼
評論
0/150
提交評論