作為一個程序猿,如果說你對這個GitHub不了解考余,那么就很尷尬了先嬉!
學(xué)會使用這個東東是很有必要的!
至于為什么往下看就是了楚堤。
如果看完疫蔓,你有了想法,就去試著去GitHub注冊個賬號身冬,然后安裝一下衅胀,再試著操作一遍!
注:以下命令是在Linux環(huán)境下的命令酥筝,記得哦拗小,不過也是可以在windows安裝好的Git Bash中使用,挺方便的樱哼!
Git的誕生
同生活中的許多偉大事件一樣哀九,Git 誕生于一個極富紛爭大舉創(chuàng)新的年代。1991年搅幅,Linus創(chuàng)建了開源的Linux阅束,并且有著為數(shù)眾多的參與者。雖然有世界各地的志愿者為Linux編寫代碼茄唐,但是絕大多數(shù)的 Linux 內(nèi)核維護(hù)工作都花在了提交補(bǔ)丁和保存歸檔的繁瑣事務(wù)上(1991-2002年間)息裸。在這期間,所有的源代碼都是由Linus手工合并沪编。因為Linus堅定地反對CVS和SVN呼盆,這些集中式的版本控制系統(tǒng)(集中式和分布式我們會在接下來的內(nèi)容講解)不但速度慢,而且必須聯(lián)網(wǎng)才能使用蚁廓。雖然有一些商用的版本控制系統(tǒng)访圃,比CVS、SVN好用相嵌,但那是付費(fèi)的腿时,和Linux的開源精神不符况脆。
不過,到了2002 年批糟,Linux系統(tǒng)已經(jīng)發(fā)展了十年了格了,代碼庫之大讓Linus很難繼續(xù)通過手工方式管理了,社區(qū)的弟兄們也對這種方式表達(dá)了強(qiáng)烈不滿徽鼎,于是整個項目組啟用了一個商業(yè)版本的分布式版本控制系統(tǒng) BitKeeper 來管理和維護(hù)代碼盛末。BitKeeper的東家BitMover公司出于人道主義精神,授權(quán)Linux社區(qū)免費(fèi)使用這個版本控制系統(tǒng)否淤。安定團(tuán)結(jié)的大好局面在2005年被打破悄但,開發(fā)BitKeeper 的商業(yè)公司同 Linux 內(nèi)核開源社區(qū)的合作關(guān)系結(jié)束,原因是Linux社區(qū)牛人聚集叹括,開發(fā)Samba的Andrew試圖破解BitKeeper的協(xié)議算墨,這么干的其實也不只他一個,但是被BitMover公司發(fā)現(xiàn)了汁雷,于是BitMover公司收回了Linux社區(qū)的免費(fèi)使用權(quán)净嘀。這就迫使Linux開源社區(qū)( 特別是Linux的締造者 Linus Torvalds )不得不吸取教訓(xùn),只有開發(fā)一套屬于自己的版本控制系統(tǒng)才不至于重蹈覆轍侠讯。
他們對新的系統(tǒng)制訂了若干目標(biāo):速度 挖藏、 簡單的設(shè)計 、 對非線性開發(fā)模式的強(qiáng)力支持(允許上千個并行開發(fā)的分支)厢漩、完全分布式膜眠、有能力高效管理類似 Linux 內(nèi)核一樣的超大規(guī)模項目(速度和數(shù)據(jù)量)。自誕生于 2005 年以來溜嗜,Git 日臻成熟完善宵膨,迅速成為最流行的分布式版本控制系統(tǒng),在高度易用的同時炸宵,仍然保留著初期設(shè)定的目標(biāo)辟躏。它的速度飛快,極其適合管理大項目土全,它還有著令人難以置信的非線性分支管理系統(tǒng)筛婉,可以應(yīng)付各種復(fù)雜的項目開發(fā)需求禾蚕。2008年,GitHub網(wǎng)站上線了竿裂,它為開源項目免費(fèi)提供Git存儲扼褪,無數(shù)開源項目開始遷移至GitHub玄坦,包括jQuery敬尺,PHP肢执,Ruby等等。
歷史就是這么偶然,如果不是當(dāng)年BitMover公司威脅Linux社區(qū)篱蝇,可能現(xiàn)在我們就沒有免費(fèi)而超級好用的Git了贺待。
Linus一直痛恨的CVS及SVN都是集中式的版本控制系統(tǒng)徽曲,而Git是分布式版本控制系統(tǒng)零截,集中式和分布式版本控制系統(tǒng)有什么區(qū)別呢?
先說集中式版本控制系統(tǒng)秃臣,版本庫是集中存放在中央服務(wù)器的涧衙,而大家工作的時候,用的都是自己的電腦奥此,所以要先從中央服務(wù)器取得最新的版本弧哎,然后開始工作,工作完成稚虎,再把自己的修訂推送給中央服務(wù)器撤嫩。這類系統(tǒng),都有一個單一的集中管理的服務(wù)器蠢终,保存所有文件的修訂版本序攘,而協(xié)同工作的人們都通過客戶端連到這臺服務(wù)器,取出最新的文件或者提交更新寻拂。
那分布式版本控制系統(tǒng)與集中式版本控制系統(tǒng)有何不同呢程奠?首先,分布式版本控制系統(tǒng)根本沒有“中央服務(wù)器”祭钉,每個人的電腦上都是一個完整的版本庫瞄沙,這樣,你工作的時候慌核,就不需要聯(lián)網(wǎng)了距境,因為版本庫就在你自己的電腦上。既然每個人電腦上都有一個完整的版本庫垮卓,那多個人如何協(xié)作呢垫桂?比方說你在自己電腦上改了文件A,你的同事也在他的電腦上改了文件A扒接,這時伪货,你們倆之間只需把各自的修改推送給對方,就可以互相看到對方的修改了钾怔。
和集中式版本控制系統(tǒng)相比碱呼,分布式版本控制系統(tǒng)的安全性要高很多,因為每個人電腦里都有完整的版本庫宗侦,某一個人的電腦壞掉了不要緊愚臀,隨便從其他人那里復(fù)制一個就可以了。而集中式版本控制系統(tǒng)的中央服務(wù)器要是出了問題矾利,所有人都沒法干活了姑裂。
在實際使用分布式版本控制系統(tǒng)的時候馋袜,其實很少在兩人之間的電腦上推送版本庫的修改,因為可能你們倆不在一個局域網(wǎng)內(nèi)舶斧,兩臺電腦互相訪問不了欣鳖,也可能今天你的同事病了,他的電腦壓根沒有開機(jī)茴厉。因此泽台,分布式版本控制系統(tǒng)通常也有一臺充當(dāng)“中央服務(wù)器”的電腦,但這個服務(wù)器的作用僅僅是用來方便“交換”大家的修改矾缓,沒有它大家也一樣干活怀酷,只是交換修改不方便而已。
許多這類系統(tǒng)都可以指定和若干不同的遠(yuǎn)端代碼倉庫進(jìn)行交互嗜闻。籍此蜕依,你就可以在同一個項目中,分別和不同工作小組的人相互協(xié)作琉雳。你可以根據(jù)需要設(shè)定不同的協(xié)作流程样眠,比如層次模型式的工作流,而這在以前的集中式系統(tǒng)中是無法實現(xiàn)的咐吼。
Git的配置
使用Git的第一件事就是設(shè)置你的名字和email,這些就是你在提交commit時的簽名吹缔,每次提交記錄里都會包含這些信息。使用git config命令進(jìn)行配置:
$ git?config --global user.name "Scott Chacon"
$ git?config --global user.email "schacon@gmail.com"
執(zhí)行了上面的命令后,會在家目錄(/home/shiyanlou)下建立一個叫.gitconfig?的文件(該文件為隱藏文件锯茄,需要使用ls -al查看到). 內(nèi)容一般像下面這樣厢塘,可以使用vim或cat查看文件內(nèi)容:
$ cat ~/.gitconfig
[user]
????????email = schacon@gmail.com
????????name = Scott Chacon
上面的配置文件就是Git全局配置的文件,一般配置方法是git config --global <配置名稱> <配置的值>肌幽。
如果你想使項目里的某個值與前面的全局設(shè)置有區(qū)別(例如把私人郵箱地址改為工作郵箱)晚碾,你可以在項目中使用git config?命令不帶?--global?選項來設(shè)置. 這會在你當(dāng)前的項目目錄下創(chuàng)建?.git/config,從而使用針對當(dāng)前項目的配置喂急。
獲得一個Git倉庫
既然我們現(xiàn)在把一切都設(shè)置好了格嘁,那么我們需要一個Git倉庫。有兩種方法可以得到它:一種是從已有的Git倉庫中clone (克隆廊移,復(fù)制)糕簿;還有一種是新建一個倉庫,把未進(jìn)行版本控制的文件進(jìn)行版本控制
Clone一個倉庫
為了得到一個項目的拷貝(copy),我們需要知道這個項目倉庫的地址(Git URL). Git能在許多協(xié)議下使用狡孔,所以Git URL可能以ssh://, http(s)://, git://. 有些倉庫可以通過不只一種協(xié)議來訪問懂诗。
我們在github.com上提供了一個名字為gitproject的供大家測試的公有倉庫,這個倉庫可以使用下面方式進(jìn)行clone:
clone 操作完成后苗膝,會發(fā)現(xiàn)當(dāng)前目錄下多了一個gitproject文件夾殃恒,這個文件夾里的內(nèi)容就是我們剛剛clone下來的代碼。由于當(dāng)前`gitproject僅是測試項目,里面僅有一個README.md文件离唐。
$?cd?gitproject/
(master)$?ls
README.md
細(xì)心的同學(xué)可以發(fā)現(xiàn)在命令提示符$前面多了個(master)病附。這是由于實驗樓的Linux使用的是zsh Shell,zsh會判斷當(dāng)前的目錄是否有Git倉庫亥鬓,如果是的話則自動把目前所在的git分支顯示在提示符中完沪。Git 分支的概念我們會在稍后介紹。
初始化一個新的倉庫
可以對一個已存在的文件夾用下面的命令讓它置于Git的版本控制管理之下贮竟。
創(chuàng)建代碼目錄project:
$?cd?/home/shiyanlou/
$?mkdir project
進(jìn)入到代碼目錄丽焊,創(chuàng)建并初始化Git倉庫:
$?cd?project
$?git init
Git會輸出:
Initialized empty Git repository in?/home/shiyanlou/project/.git/
通過ls -la命令會發(fā)現(xiàn)project目錄下會有一個名叫.git?的目錄被創(chuàng)建较剃,這意味著一個倉庫被初始化了咕别。可以進(jìn)入到.git目錄查看下有哪些內(nèi)容写穴。
正常的工作流程
git的基本流程如下:
1.?創(chuàng)建或修改文件
2.?使用git add命令添加新創(chuàng)建或修改的文件到本地的緩存區(qū)(Index)
3.?使用git commit命令提交到本地代碼庫
4.?(可選惰拱,有的時候并沒有可以同步的遠(yuǎn)端代碼庫)使用git push命令將本地代碼庫同步到遠(yuǎn)端代碼庫
創(chuàng)建和修改文件
進(jìn)入我們剛才建立的project目錄,分別創(chuàng)建文件file1啊送,file2偿短,file3:
$?cd?project
$?touch file1 file2 file3
修改文件,可以使用vim編輯內(nèi)容馋没,也可以直接echo添加測試內(nèi)容昔逗。
$ echo "test"?>> file1
$ echo "test"?>> file2
$ echo "test"?>> file3
此時可以使用git status命令查看當(dāng)前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)
可以發(fā)現(xiàn),有三個文件處于untracked狀態(tài)篷朵,下一步我們就需要用git add命令將他們加入到緩存區(qū)(Index)勾怒。
使用git add加入緩存區(qū)
使用git add命令將新建的文件添加到:
$ git add?file1 file2 file3
然后再次執(zhí)行g(shù)it status就會發(fā)現(xiàn)新的變化:
$ git status
On branch master
Initial commit
Changes to?be committed:
????(use?"git rm --cached <file>..."?to?unstage)
???????new?file: file1
???????new?file: file2
???????new?file: file3
你現(xiàn)在為commit做好了準(zhǔn)備,你可以使用?git diff?命令再加上?--cached?參數(shù)声旺,看看緩存區(qū)中哪些文件被修改了笔链。進(jìn)入到git diff --cached界面后需要輸入q才可以退出:
$ git diff --cached
如果沒有--cached參數(shù),git diff?會顯示當(dāng)前你所有已做的但沒有加入到索引里的修改腮猖。
如果你要做進(jìn)一步的修改, 那就繼續(xù)做, 做完后就把新修改的文件加入到緩存區(qū)中鉴扫。
使用git commit提交修改
當(dāng)所有新建,修改的文件都被添加到了緩存區(qū)澈缺,我們就要使用git commit提交到本地倉庫:
$ git commit -m "add 3 files"
需要使用-m添加本次修改的注釋坪创,完成后就會記錄一個新的項目版本。除了用git add?命令姐赡,我們還可以用下面的命令將所有沒有加到緩存區(qū)的修改也一起提交莱预,但-a命令不會添加新建的文件。
$ git commit -a?-m "add 3 files"
再次輸入git status查看狀態(tài)雏吭,會發(fā)現(xiàn)當(dāng)前的代碼庫已經(jīng)沒有待提交的文件了锁施,緩存區(qū)已經(jīng)被清空。
至此,我們完成了第一次代碼提交悉抵,這次提交的代碼中我們創(chuàng)建了三個新文件肩狂。需要注意的是如果是修改文件,也需要使用git add命令添加到緩存區(qū)才可以提交姥饰。如果是刪除文件傻谁,則直接使用git rm命令刪除后會自動將已刪除文件的信息添加到緩存區(qū),git commit提交后就會將本地倉庫中的對應(yīng)文件刪除列粪。
這時如果我們希望將本地倉庫關(guān)聯(lián)到遠(yuǎn)端服務(wù)器审磁,我們可以使用?git remote?命令,不同于剛剛的?git clone?命令岂座,直接將遠(yuǎn)端的倉庫克隆下來态蒂。 我們當(dāng)前的倉庫是使用?git init?初始化的本地倉庫,所以我們需要將本地倉庫與遠(yuǎn)程倉庫關(guān)聯(lián)费什,使用如下命令(需要修改下面的遠(yuǎn)程倉庫地址為自己的倉庫地址):
對于上述命令而言钾恢,git remote add?命令用于添加遠(yuǎn)程主機(jī),origin?是主機(jī)名鸳址,此處我們可以自定義瘩蚪,不一定非要使用?origin,而
是我自己的遠(yuǎn)程倉庫稿黍,此處需要替換為自己的遠(yuǎn)程倉庫地址
這個時候如果本地的倉庫連接到了遠(yuǎn)程Git服務(wù)器疹瘦,可以使用下面的命令將本地倉庫同步到遠(yuǎn)端服務(wù)器:
# 需要輸入倉庫對應(yīng)的用戶名和密碼
$ git push?origin master
分支與合并
Git 的分支可以讓你在主線(master分支)之外進(jìn)行代碼提交,同時又不會影響代碼庫主線巡球。分支的作用體現(xiàn)在多人協(xié)作開發(fā)中言沐,比如一個團(tuán)隊開發(fā)軟件,你負(fù)責(zé)獨立的一個功能需要一個月的時間來完成辕漂,你就可以創(chuàng)建一個分支呢灶,只把該功能的代碼提交到這個分支,而其他同事仍然可以繼續(xù)使用主線開發(fā)钉嘹,你每天的提交不會對他們造成任何影響鸯乃。當(dāng)你完成功能后,測試通過再把你的功能分支合并到主線跋涣。
創(chuàng)建分支
一個Git倉庫可以維護(hù)很多開發(fā)分支∮現(xiàn)在我們來創(chuàng)建一個新的叫 experimental的分支:
$ git branch experimental
運(yùn)行g(shù)it branch命令可以查看當(dāng)前的分支列表,以及目前的開發(fā)環(huán)境處在哪個分支上:
$?git branch
?experimental
* master
切換分支
experimental 分支是你剛才創(chuàng)建的陈辱,master分支是Git系統(tǒng)默認(rèn)創(chuàng)建的主分支奖年。星號標(biāo)識了你當(dāng)工作在哪個分支下,輸入git checkout 分支名可以切換到其他分支:
$ git checkout experimental
Switched to?branch 'experimental'
切換到experimental分支沛贪,切換完成后陋守,先編輯里面的一個文件震贵,再提交(commit)改動,最后切換回 “master”分支:
# 修改文件file1
$ echo "update"?>> file1
# 查看當(dāng)前狀態(tài)
$ git status
# 添加并提交file1的修改
$ git add file1
$ git commit -m "update file1"
# 查看file1的內(nèi)容
$ cat file1
test
update
# 切換到master分支
$ git checkout master
查看下file1中的內(nèi)容會發(fā)現(xiàn)剛才做的修改已經(jīng)看不到了水评。因為剛才的修改時在experimental分支下猩系,現(xiàn)在切換回了master分支,目錄下的文件都是master分支上的文件了中燥。
合并分支
現(xiàn)在可以在master分支下再作一些不同的修改:
# 修改文件file2
$ echo "update again"?>> file2
# 查看當(dāng)前狀態(tài)
$ git status
# 添加并提交file2的修改
$ git add file2
$ git commit -m "update file2 on master"
# 查看file2的內(nèi)容
$ cat file2
test
update again
這時寇甸,兩個分支就有了各自不同的修改,分支的內(nèi)容都已經(jīng)不同疗涉,如何將多個分支進(jìn)行合并呢拿霉?
可以通過下面的git merge命令來合并experimental到主線分支master:
# 切換到master分支
$ git checkout master
# 將experimental分支合并到master
$?git merge -m 'merge experimental branch' experimental
-m參數(shù)仍然是需要填寫合并的注釋信息。
由于兩個 branch 修改了兩個不同的文件咱扣,所以合并時不會有沖突绽淘,執(zhí)行上面的命令后合并就完成了。
如果有沖突偏窝,比如兩個分支都改了一個文件 file3收恢,則合并時會失敗。首先我們在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
# 提交到experimental分支
$ git commit -a -m 'update file3 on experimental'
切換到master進(jìn)行合并:
$ 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)容。
可以看到?jīng)_突的內(nèi)容都被添加到了file3中熏矿,我們使用vim編輯這個文件已骇,去掉git自動產(chǎn)生標(biāo)志沖突的<<<<<<等符號后,根據(jù)需要只保留我們需要的內(nèi)容后保存票编,然后使用git add file3和git commit命令來提交合并后的file3內(nèi)容褪储,這個過程是手動解決沖突的流程。
# 編輯沖突文件
$ vim file3
# 提交修改后的文件
$ git add file3
$ git commit -m 'merge file3'
刪除分支
當(dāng)我們完成合并后慧域,不再需要experimental時鲤竹,可以使用下面的命令刪除:
$ git branch -d experimental
git branch -d只能刪除那些已經(jīng)被當(dāng)前分支的合并的分支. 如果你要強(qiáng)制刪除某個分支的話就用git branch –D
撤銷一個合并
如果你覺得你合并后的狀態(tài)是一團(tuán)亂麻,想把當(dāng)前的修改都放棄昔榴,你可以用下面的命令回到合并之前的狀態(tài):
$ git reset --hard HEAD^
# 查看file3的內(nèi)容辛藻,已經(jīng)恢復(fù)到合并前的master上的文件內(nèi)容
$ cat file3
查看日志
git log命令可以顯示所有的提交(commit):
$?git log
如果提交的歷史紀(jì)錄很長,回車會逐步顯示互订,輸入q可以退出吱肌。
git log有很多選項,可以使用git help log查看仰禽,例如下面的命令就是找出所有從"v2.5“開始在 fs 目錄下的所有 Makefile 的修改(這個只是舉例氮墨,不用操作):
$?git log?v2.5.. Makefile fs/
Git會根據(jù)git log命令的參數(shù)纺蛆,按時間順序顯示相關(guān)的提交(commit)。
日志統(tǒng)計
git log命令可以顯示所有的提交(commit):
$?git log
如果提交的歷史紀(jì)錄很長规揪,回車會逐步顯示犹撒,輸入q可以退出。
git log有很多選項粒褒,可以使用git help log查看识颊,例如下面的命令就是找出所有從"v2.5“開始在 fs 目錄下的所有 Makefile 的修改(這個只是舉例,不用操作):
$?git log?v2.5.. Makefile fs/
Git會根據(jù)git log命令的參數(shù)奕坟,按時間順序顯示相關(guān)的提交(commit)祥款。
格式化日志
你可以按你的要求來格式化日志輸出。--pretty?參數(shù)可以使用若干表現(xiàn)格式月杉,如oneline:
$ git log?--pretty=oneline
或者你也可以使用?short?格式:
$ git log?--pretty=short
你也可用medium,full,fuller,email?或raw刃跛。 如果這些格式不完全符合你的需求, 你也可以用--pretty=format參數(shù)定義格式苛萎。
--graph?選項可以可視化你的提交圖(commit graph)桨昙,會用ASCII字符來畫出一個很漂亮的提交歷史(commit history)線:
$ git log?--graph --pretty=oneline
日志排序
日志記錄可以按不同的順序來顯示。如果你要指定一個特定的順序腌歉,可以為git log命令添加順序參數(shù)蛙酪。
按默認(rèn)情況,提交會按逆時間順序顯示翘盖,可以指定--topo-order參數(shù)桂塞,讓提交按拓?fù)漤樞騺盹@示(就是子提交在它們的父提交前顯示):
$ git log?--pretty=format:'%h?: %s' --topo-order?--graph
你也可以用?--reverse參數(shù)來逆向顯示所有提交日志。
總結(jié)命令
本節(jié)講解了幾個基本命令:
·?git config:配置相關(guān)信息
·?git clone:復(fù)制倉庫
·?git init:初始化倉庫
·?git add:添加更新內(nèi)容到索引中
·?git diff:比較內(nèi)容
·?git status:獲取當(dāng)前項目狀況
·?git commit:提交
·?git branch:分支相關(guān)
·?git checkout:切換分支
·?git merge:合并分支
·?git reset:恢復(fù)版本
·?git log:查看日志