您好,登錄后才能下訂單哦!
Git 的誕生
很多人都知道, Linus 在 1991 年創(chuàng)建了開源的 Linux,從此, Linux 系統(tǒng)不斷發(fā)展,已經(jīng)成為最大的服務(wù)器系統(tǒng)軟件了。Linus雖然創(chuàng)建了Linux,但Linux的壯大是靠全世界熱心的志愿者參與的,這么多人在世界各地為L(zhǎng)inux編寫代碼,那 Linux 的代碼是如何管理的呢?
事實(shí)是,在 2002 年以前,世界各地的志愿者把源代碼文件通過 diff 的方式發(fā)給 Linus,然后由 Linus本人通過手工方式合并代碼!
你也許會(huì)想,為什么 Linus 不把 Linux 代碼放到版本控制系統(tǒng)里呢?不是有 CVS、 SVN 這些免費(fèi)的版本控制系統(tǒng)嗎?因?yàn)?Linus 堅(jiān)定地反對(duì) CVS 和 SVN,這些集中式的版本控制系統(tǒng)不但速度慢,而且必須聯(lián)網(wǎng)才能使用。有一些商用的版本控制系統(tǒng),雖然比 CVS、 SVN 好用,但那是付費(fèi)的,和 Linux 的開源精神不符。
不過,到了 2002 年, Linux 系統(tǒng)已經(jīng)發(fā)展了十年了,代碼庫之大讓 Linus 很難繼續(xù)通過手工方式管理了,社區(qū)的弟兄們也對(duì)這種方式表達(dá)了強(qiáng)烈不滿,于是 Linus 選擇了一個(gè)商業(yè)的版本控制系統(tǒng) BitKeeper,
BitKeeper 的東家 BitMover 公司出于人道主義精神,授權(quán) Linux 社區(qū)免費(fèi)使用這個(gè)版本控制系統(tǒng)。安定團(tuán)結(jié)的大好局面在 2005 年就被打破了,原因是 Linux 社區(qū)牛人聚集,不免沾染了一些梁山好漢的江湖習(xí)氣。開發(fā) Samba 的 Andrew 試圖破解 BitKeeper 的協(xié)議(這么干的其實(shí)也不只他一個(gè)),被BitMover 公司發(fā)現(xiàn)了(監(jiān)控工作做得不錯(cuò)?。?,于是 BitMover 公司怒了,要收回 Linux 社區(qū)的免費(fèi)使
用權(quán)。
Linus 可以向 BitMover 公司道個(gè)歉,保證以后嚴(yán)格管教弟兄們,嗯,這是不可能的。實(shí)際情況是這樣的:Linus 花了兩周時(shí)間自己用 C 寫了一個(gè)分布式版本控制系統(tǒng),這就是 Git!一個(gè)月之內(nèi), Linux 系統(tǒng)的
源碼已經(jīng)由 Git 管理了!牛是怎么定義的呢?大家可以體會(huì)一下。Git 迅速成為最流行的分布式版本控制系統(tǒng),尤其是 2008 年, GitHub 網(wǎng)站上線了,它為開源項(xiàng)目免費(fèi)提供 Git 存儲(chǔ),無數(shù)開源項(xiàng)目開始遷移至 GitHub,包括 jQuery, PHP, Ruby 等等。
歷史就是這么偶然,如果不是當(dāng)年 BitMover 公司威脅 Linux 社區(qū),可能現(xiàn)在我們就沒有免費(fèi)而超級(jí)好用的 Git 了。
集中式 vs 分布式
Linus 一直痛恨的 CVS 及 SVN 都是集中式的版本控制系統(tǒng),而 Git 是分布式版本控制系統(tǒng),集中式和分布式版本控制系統(tǒng)有什么區(qū)別呢?
先說集中式版本控制系統(tǒng),版本庫是集中存放在中央服務(wù)器的,而干活的時(shí)候,用的都是自己的電腦,所以要先從中央服務(wù)器取得最新的版本,然后開始干活,干完活了,再把自己的活推送給中央服務(wù)器。中央服務(wù)器就好比是一個(gè)圖書館,你要改一本書,必須先從圖書館借出來,然后回到家自己改,改完了,再放回圖書館
集中式版本控制系統(tǒng)最大的毛病就是必須聯(lián)網(wǎng)才能工作,如果在局域網(wǎng)內(nèi)還好,帶寬夠大,速度夠快,可如果在互聯(lián)網(wǎng)上,遇到網(wǎng)速慢的話,可能提交一個(gè) 10M 的文件就需要 5 分鐘,這還不得把人給憋死啊。
那分布式版本控制系統(tǒng)與集中式版本控制系統(tǒng)有何不同呢?首先,分布式版本控制系統(tǒng)根本沒有“中央服務(wù)器”,每個(gè)人的電腦上都是一個(gè)完整的版本庫,這樣,你工作的時(shí)候,就不需要聯(lián)網(wǎng)了,因?yàn)榘姹編炀驮谀阕约旱碾娔X上。既然每個(gè)人電腦上都有一個(gè)完整的版本庫,那多個(gè)人如何協(xié)作呢?比方說你在自己電腦上改了文件 A,你的同事也在他的電腦上改了文件 A,這時(shí),你們倆之間只需把各自的修改推送給對(duì)方,就可以互相看到對(duì)方的修改了。和集中式版本控制系統(tǒng)相比,分布式版本控制系統(tǒng)的安全性要高很多,因?yàn)槊總€(gè)人電腦里都有完整的版本庫,某一個(gè)人的電腦壞掉了不要緊,隨便從其他人那里復(fù)制一個(gè)就可以了。而集中式版本控制系統(tǒng)的中央服務(wù)器要是出了問題,所有人都沒法干活了。
在實(shí)際使用分布式版本控制系統(tǒng)的時(shí)候,其實(shí)很少在兩人之間的電腦上推送版本庫的修改,因?yàn)榭赡苣銈儌z不在一個(gè)局域網(wǎng)內(nèi),兩臺(tái)電腦互相訪問不了,也可能今天你的同事病了,他的電腦壓根沒有開機(jī)。因此,分布式版本控制系統(tǒng)通常也有一臺(tái)充當(dāng)“中央服務(wù)器”的電腦,但這個(gè)務(wù)器的作用僅僅是用來方便“交換”大家的修改, 沒有它大家也一樣干活,只是交換修改不方便而已。
當(dāng)然, Git 的優(yōu)勢(shì)不單是不必聯(lián)網(wǎng)這么簡(jiǎn)單,后面我們還會(huì)看到 Git 極其強(qiáng)大的分支管理,把 SVN 等
遠(yuǎn)遠(yuǎn)拋在了后面。
CVS 作為最早的開源而且免費(fèi)的集中式版本控制系統(tǒng),直到現(xiàn)在還有不少人在用。由于 CVS 自身設(shè)
計(jì)的問題,會(huì)造成提交文件不完整,版本庫莫名其妙損壞的情況。同樣是開源而且免費(fèi)的 SVN 修正了
CVS 的一些穩(wěn)定性問題,是目前用得最多的集中式版本庫控制系統(tǒng)。
除了免費(fèi)的外,還有收費(fèi)的集中式版本控制系統(tǒng),比如 IBM 的 ClearCase(以前是 Rational 公司的,
被 IBM 收購了),特點(diǎn)是安裝比 Windows 還大,運(yùn)行比蝸牛還慢,能用 ClearCase 的一般是世界 500
強(qiáng),他們有個(gè)共同的特點(diǎn)是財(cái)大氣粗,或者人傻錢多。
微軟自己也有一個(gè)集中式版本控制系統(tǒng)叫 VSS,集成在 Visual Studio 中。由于其反人類的設(shè)計(jì),連微
軟自己都不好意思用了。
分布式版本控制系統(tǒng)除了 Git 以及促使 Git 誕生的 BitKeeper 外,還有類似 Git 的 Mercurial 和 Bazaar
等。這些分布式版本控制系統(tǒng)各有特點(diǎn),但最快、最簡(jiǎn)單也最流行的依然是 Git!
最早 Git 是在 Linux 上開發(fā)的,很長(zhǎng)一段時(shí)間內(nèi), Git 也只能在 Linux 和 Unix 系統(tǒng)上跑。不過,慢慢地有人把它移植
到了 Windows 上?,F(xiàn)在, Git 可以在 Linux、 Unix、 Mac 和 Windows 這幾大平臺(tái)上正常運(yùn)行了。
在 Linux 上安裝 Git
yum -y install git
20 mkdir /xgp 創(chuàng)建所需目錄
21 git init git初始化
創(chuàng)建用戶名郵箱
26 git config --global user.name "admin"
27 git config --global user.email "admin@admin"
把文件添加到版本庫
現(xiàn)在我們編寫三個(gè)xgp.txt 文件,內(nèi)容如下
23 vim xgp1.txt #xgp1
24 vim xgp2.txt #xgp2
25 vim xgp3.txt #xgp3
第一步,用命令 git add 告訴 Git,把文件添加到倉庫:
28 git add xgp1.txt xgp2.txt xgp3.txt
第二步,用命令 git commit 告訴 Git,把文件提交到倉庫:
29 git commit -m "第一次提交"
查看提交信息
52 cd ./git
53 ls -a
57 cat logs/refs/heads/master
58 cat HEAD
小結(jié)
現(xiàn)在總結(jié)一下今天學(xué)的兩點(diǎn)內(nèi)容:
初始化一個(gè) Git 倉庫,使用 git init 命令。
添加文件到 Git 倉庫,分兩步:
? 第一步,使用命令 git add <file>,注意,可反復(fù)多次使用,添加多個(gè)文件;
? 第二步,使用命令 git commit,完成。
我們已經(jīng)成功地添加并提交了一個(gè) readme.txt 文件,現(xiàn)在,是時(shí)候繼續(xù)工作了,于是,我們繼續(xù)修改 xgp.txt 文件,改成如下內(nèi)容:
xgp1
回退測(cè)試
現(xiàn)在,運(yùn)行 git status 命令看看結(jié)果:
git status 命令可以讓我們時(shí)刻掌握倉庫當(dāng)前的狀態(tài),上面的命令告訴我們, readme.txt 被修改過了,但還沒有準(zhǔn)備提交的修改
雖然 Git 告訴我們 xgp1.txt 被修改了,但如果能看看具體修改了什么內(nèi)容,自然是很好的。比如你休假兩周從國(guó)外回來,第一天上班時(shí),已經(jīng)記不清上次怎么修改的 readme.txt,所以,需要用 git diff 這個(gè)命令看看:
git diff 顧名思義就是查看 difference,顯示的格式正是 Unix 通用的 diff 格式,可以從上面的命令輸出看到,我們第一行添加了一個(gè)”回退測(cè)試”
知道了對(duì) readme.txt 作了什么修改后,再把它提交到倉庫就放心多了,提交修改和提交新文件是一樣的兩步,第一步是 git add:
git add xgp1.txt
同樣沒有任何輸出。在執(zhí)行第二步 git commit 之前,我們?cè)龠\(yùn)行 git status 看看當(dāng)前倉庫的狀態(tài):
git status 告訴我們,將要被提交的修改包括 xgp.txt,下一步,就可以放心地提交了:
git commit -m "第二次提交"
提交后,我們?cè)儆?git status 命令看看倉庫的當(dāng)前狀態(tài):
小結(jié)
要隨時(shí)掌握工作區(qū)的狀態(tài),使用 git status 命令。
如果 git status 告訴你有文件被修改過,用 git diff 可以查看修改內(nèi)容。
為什么說 Git 管理的是修改,而不是文件呢?我們還是做實(shí)驗(yàn)。第一步,對(duì) xgp1.txt 做一個(gè)修改,比如加一行內(nèi)容:
[root@localhost xgp]# cat xgp1.txt
xgp1
回退測(cè)試
xgp666
xgpniubi
然后,添加:
93 git add xgp1.txt
94 git status
然后,再修改 readme.txt:
[root@localhost xgp]# cat xgp1.txt
xgp1
回退測(cè)試
xgp666
xgpniubi
1
提交:
[root@localhost xgp]# git commit -m "第四次提交"
[master 31cb090] 第四次提交
1 file changed, 1 insertion(+)
提交后,再看看狀態(tài):
咦,怎么第二次的修改沒有被提交?
別激動(dòng),我們回顧一下操作過程:
第一次修改 -> git add -> 第二次修改 -> git commit
你看,我們前面講了, Git 管理的是修改,當(dāng)你用 git add 命令后,在工作區(qū)的第一次修改被放入暫存區(qū), 準(zhǔn)備提交,
但是,在工作區(qū)的第二次修改并沒有放入暫存區(qū),所以, git commit 只負(fù)責(zé)把暫存區(qū)的修改提交了,也就是第一次的
修改被提交了,第二次的修改不會(huì)被提交。
提交后,用 git diff HEAD -- readme.txt 命令可以查看工作區(qū)和版本庫里面最新版本的區(qū)別:
可見,第二次修改確實(shí)沒有被提交。
那怎么提交第二次修改呢?你可以繼續(xù) git add 再 git commit,也可以別著急提交第一次修改,先 git add 第二次修
改,再 git commit,就相當(dāng)于把兩次修改合并后一塊提交了:
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
好,現(xiàn)在,把第二次修改提交了,然后開始小結(jié)。
小結(jié)
現(xiàn)在,你又理解了 Git 是如何跟蹤修改的,每次修改,如果不 add 到暫存區(qū),那就不會(huì)加入到 commit 中。
自然,你是不會(huì)犯錯(cuò)的。不過現(xiàn)在是凌晨?jī)牲c(diǎn),你正在趕一份工作報(bào)告,你在 readme.txt 中添加了一行:
[root@localhost xgp]# cat xgp1.txt
xgp1
回退測(cè)試
xgp666
xgpniubi
1
22222
在你準(zhǔn)備提交前,一杯咖啡起了作用,你猛然發(fā)現(xiàn)了“stupid boss”可能會(huì)讓你丟掉這個(gè)月的獎(jiǎng)金!既然錯(cuò)誤發(fā)現(xiàn)得很及時(shí),就可以很容易地糾正它。你可以刪掉最后一行,手動(dòng)把文件恢復(fù)到上一個(gè)版本的狀態(tài)。如果
用 git status 查看一下:
你可以發(fā)現(xiàn), Git 會(huì)告訴你, git checkout -- file 可以丟棄工作區(qū)的修改:
git checkout -- xgp1.txt
[root@localhost xgp]# cat xgp1.txt
xgp1
回退測(cè)試
xgp666
xgpniubi
1
慶幸的是,在 commit 之前,你發(fā)現(xiàn)了這個(gè)問題。用 git status 查看一下,修改只是添加到了暫存區(qū),還沒有提交:
Git 同樣告訴我們,用命令 git reset HEAD file 可以把暫存區(qū)的修改撤銷掉(unstage),重新放回工作區(qū):
[root@localhost xgp]# git reset HEAD xgp1.txt
重置后撤出暫存區(qū)的變更:
M xgp1.txt
git reset 命令既可以回退版本,也可以把暫存區(qū)的修改回退到工作區(qū)。當(dāng)我們用 HEAD 時(shí),表示最新的版本。
再用 git status 查看一下,現(xiàn)在暫存區(qū)是干凈的,工作區(qū)有修改:
還記得如何丟棄工作區(qū)的修改嗎?
整個(gè)世界終于清靜了!
現(xiàn)在,假設(shè)你不但改錯(cuò)了東西,還從暫存區(qū)提交到了版本庫,怎么辦呢?還記得版本回退一節(jié)嗎? 可以回退到上一個(gè)版本。不過,這是有條件的,就是你還沒有把自己的本地版本庫推送到遠(yuǎn)程。還記得 Git 是分布式版本控制系統(tǒng)嗎?我們后面會(huì)講到遠(yuǎn)程版本庫,一旦你把“stupid boss”提交推送到遠(yuǎn)程版本庫,你就真的慘了……
小結(jié)
又到了小結(jié)時(shí)間。
場(chǎng)景 1:當(dāng)你改亂了工作區(qū)某個(gè)文件的內(nèi)容,想直接丟棄工作區(qū)的修改時(shí),用命令 git checkout -- file。
場(chǎng)景 2:當(dāng)你不但改亂了工作區(qū)某個(gè)文件的內(nèi)容,還添加到了暫存區(qū)時(shí),想丟棄修改,分兩步,第一步用命令 git reset
HEAD file,就回到了場(chǎng)景 1, 第二步按場(chǎng)景 1 操作。
場(chǎng)景 3:已經(jīng)提交了不合適的修改到版本庫時(shí),想要撤銷本次提交,參考版本回退一節(jié),不過前提是沒有推送到遠(yuǎn)程
庫。
在 Git 中,刪除也是一個(gè)修改操作,我們實(shí)戰(zhàn)一下,先添加一個(gè)新文件 test.txt 到 Git 并且提交:
[root@localhost xgp]# vim test.txt
[root@localhost xgp]# cat test.txt
qqqqqqqqqqqq
[root@localhost xgp]# git add test.txt
[root@localhost xgp]# git commit -m "第一次"
[master f9688d7] 第一次
1 file changed, 1 insertion(+)
create mode 100644 test.txt
一般情況下,你通常直接在文件管理器中把沒用的文件刪了,或者用 rm 命令刪了:
這個(gè)時(shí)候, Git 知道你刪除了文件,因此,工作區(qū)和版本庫就不一致了, git status 命令會(huì)立刻告訴你哪些文件被刪除了:
現(xiàn)在你有兩個(gè)選擇,一是確實(shí)要從版本庫中刪除該文件,那就用命令 git rm 刪掉,并且 git commit:
現(xiàn)在,文件就從版本庫中被刪除了。
另一種情況是刪錯(cuò)了,因?yàn)榘姹編炖镞€有呢,所以可以很輕松地把誤刪的文件恢復(fù)到最新版本:
$ git checkout -- test.txt
git checkout 其實(shí)是用版本庫里的版本替換工作區(qū)的版本,無論工作區(qū)是修改還是刪除,都可以“一鍵還原”。
小結(jié)
命令 git rm 用于刪除一個(gè)文件。如果一個(gè)文件已經(jīng)被提交到版本庫,那么你永遠(yuǎn)不用擔(dān)心誤刪,但是要小心,你只
能恢復(fù)文件到最新版本,你會(huì)丟失最近一次提交后你修改的內(nèi)容。
第1步:創(chuàng)建SSH Key。在用戶主目錄下,看看有沒有.ssh目錄,如果有,再看看這個(gè)目錄下有沒有 id_rsa 和 id_rsa.pub 這兩個(gè)文件, 如果已經(jīng)有了,可直接跳到下一步。如果沒有,打開 Shell (Windows 下打開 Git Bash),創(chuàng)建 SSH Key:
ssh-keygen -t rsa -C 2877364346@qq.com
你需要把郵件地址換成你自己的郵件地址,然后一路回車,使用默認(rèn)值即可,由于這個(gè) Key 也不是用于軍事目的,
所以也無需設(shè)置密碼。
如果一切順利的話,可以在用戶主目錄里找到.ssh 目錄,里面有 id_rsa 和 id_rsa.pub 兩個(gè)文件,這兩個(gè)就是 SSH Key
的秘鑰對(duì), id_rsa 是私鑰,不能泄露出去, id_rsa.pub 是公鑰,可以放心地告訴任何人。
第 2 步:登陸 GitHub,打開“Account settings”, “SSH Keys”頁面:
然后,點(diǎn)“Add SSH Key”,填上任意 Title,在 Key 文本框里粘貼 id_rsa.pub 文件的內(nèi)容:
為什么 GitHub 需要 SSH Key 呢?因?yàn)?GitHub 需要識(shí)別出你推送的提交確實(shí)是你推送的,而不是別人冒充的,而Git 支持 SSH 協(xié)議,所以, GitHub 只要知道了你的公鑰,就可以確認(rèn)只有你自己才能推送。
從遠(yuǎn)程庫克隆
現(xiàn)在的情景是,你已經(jīng)在本地創(chuàng)建了一個(gè) Git 倉庫后,又想在 GitHub 創(chuàng)建一個(gè) Git 倉庫,并且讓這兩個(gè)倉庫進(jìn)行遠(yuǎn)程同步,這樣, GitHub 上的倉庫既可以作為備份,又可以讓其他人通過該倉庫來協(xié)作,真是一舉多得。
首先,登陸 GitHub,然后,在右上角找到“Create a new repo”按鈕,創(chuàng)建一個(gè)新的倉庫
目前,在 GitHub 上的這個(gè) learngit 倉庫還是空的, GitHub 告訴我們,可以從這個(gè)倉庫克隆出新的倉庫,也可以把一個(gè)已有的本地倉庫與之關(guān)聯(lián),然后,把本地倉庫的內(nèi)容推送到 GitHub 倉庫。
現(xiàn)在,遠(yuǎn)程庫已經(jīng)準(zhǔn)備好了,下一步是用命令 git clone 克隆一個(gè)本地庫:
git clone git@github.com:xgp666/xgp.git
注意把 Git 庫的地址換成你自己的,然后進(jìn)入 gitskills 目錄看看,已經(jīng)有 README.md 文件了。
如果有多個(gè)人協(xié)作開發(fā),那么每個(gè)人各自從遠(yuǎn)程克隆一份就可以了。
你也許還注意到, GitHub 給出的地址不止一個(gè),還可以用 https://github.com/michaelliao/gitskills.git 這樣的地
址。實(shí)際上, Git 支持多種協(xié)議,默認(rèn)的 git://使用 ssh,但也可以使用 https 等其他協(xié)議。
使用 https 除了速度慢以外,還有個(gè)最大的麻煩是每次推送都必須輸入口令,但是在某些只開放 http 端口的公司內(nèi)
部就無法使用 ssh 協(xié)議而只能用 https。
測(cè)試:在遠(yuǎn)程庫創(chuàng)建一個(gè)文件
[root@localhost xgp]# vim index.html
[root@localhost xgp]# cat index.html
Qqqqq
[root@localhost xgp]# git add index.html
[root@localhost xgp]# git commit -m "123"
[master 65e2ec7] 123
1 file changed, 1 insertion(+)
create mode 100644 index.html
[root@localhost xgp]# git push origin master (默認(rèn)是master)
瀏覽器查看
小結(jié)
要克隆一個(gè)倉庫,首先必須知道倉庫的地址,然后使用 git clone 命令克隆。
Git 支持多種協(xié)議,包括 https,但通過 ssh 支持的原生 git 協(xié)議速度最快。
現(xiàn)在的情景是,你已經(jīng)在本地創(chuàng)建了一個(gè) Git 倉庫后,又想在 GitHub 創(chuàng)建一個(gè) Git 倉庫,并且讓這兩個(gè)倉庫進(jìn)行遠(yuǎn)
程同步,這樣, GitHub 上的倉庫既可以作為備份,又可以讓其他人通過該倉庫來協(xié)作,真是一舉多得。
目前,在 GitHub 上的這個(gè) learngit 倉庫還是空的, GitHub 告訴我們,可以從這個(gè)倉庫克隆出新的倉庫,也可以把一個(gè)已有的本地倉庫與之關(guān)聯(lián),然后,把本地倉庫的內(nèi)容推送到 GitHub 倉庫。
現(xiàn)在,我們根據(jù) GitHub 的提示,在本地的 learngit 倉庫下運(yùn)行命令:
git remote add origin git@github.com:xgp666/xgp.git
下一步,就可以把本地庫的所有內(nèi)容推送到遠(yuǎn)程庫上:
1.git branch --set-upstream-to=origin/master master
2.git fetch
3.再次執(zhí)行g(shù)it branch --set-upstream-to=origin/master master
4.git push origin master
5.git pull
6.
[root@localhost xhp]# vim aa.txt
[root@localhost xhp]# git add *
[root@localhost xhp]# git commit -m "4"
[master 2f77003] 4
[root@localhost xhp]# git status
! 位于分支 master
! 您的分支領(lǐng)先 'origin/master' 共 3 個(gè)提交。
! (使用 "git push" 來發(fā)布您的本地提交)
!
無文件要提交,干凈的工作區(qū)
7.git push origin master
瀏覽器查看
從現(xiàn)在起,只要本地作了提交,就可以通過命令:
$ git push origin master
把本地 master 分支的最新修改推送至 GitHub,現(xiàn)在,你就擁有了真正的分布式版本庫!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。