Git
Git是什么?
Git是目前世界上最先進(jìn)的分布式版本控制系統(tǒng)(沒(méi)有之一)。
誕生
……
Linus花了兩周時(shí)間自己用C寫(xiě)了一個(gè)分布式版本控制系統(tǒng),這就是Git!
……
參考
https://www.liaoxuefeng.com/wiki/896043488029600
?
在Ubuntu上安裝Git
首先,你可以試著輸入git,看看系統(tǒng)有沒(méi)有安裝Git
$ git
Theprogram 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
$ sudo apt-get install git
創(chuàng)建版本庫(kù)
什么是版本庫(kù)呢?版本庫(kù)又名倉(cāng)庫(kù),英文名repository,你可以簡(jiǎn)單理解成一個(gè)目錄,這個(gè)目錄里面的所有文件都可以被Git管理起來(lái),每個(gè)文件的修改、刪除,Git都能跟蹤,以便任何時(shí)刻都可以追蹤歷史,或者在將來(lái)某個(gè)時(shí)刻可以“還原”。
第一步,創(chuàng)建一個(gè)版本庫(kù)非常簡(jiǎn)單,首先,選擇一個(gè)合適的地方,創(chuàng)建一個(gè)空目錄:
$ sudo mkdir -p /var/www/git
第二步,通過(guò)git init命令把這個(gè)目錄初始化為Git的倉(cāng)庫(kù):
$ cd /var/www/git
$ sudo git init
Initialized empty Git repository in /var/www/git/.git/
Git建立好了一個(gè)空的倉(cāng)庫(kù)。?
把文件添加到版本庫(kù)
首先這里再明確一下,所有的版本控制系統(tǒng),其實(shí)只能跟蹤文本文件的改動(dòng),比如:TXT文件,網(wǎng)頁(yè),所有的程序代碼等等,Git也不例外。
版本控制系統(tǒng)可以告訴你每次的改動(dòng),比如在第5行加了一個(gè)單詞“Linux”,在第8行刪了一個(gè)單詞“Windows”。
但圖片、視頻這些二進(jìn)制文件,雖然也能由版本控制系統(tǒng)管理,但沒(méi)法跟蹤文件的變化,只能把二進(jìn)制文件每次改動(dòng)串起來(lái),也就是只知道圖片從100KB改成了120KB,但到底改了啥,版本控制系統(tǒng)不知道,也沒(méi)法知道。
不幸的是,Microsoft的Word格式是二進(jìn)制格式,因此,版本控制系統(tǒng)是沒(méi)法跟蹤Word文件的改動(dòng)的,前面我們舉的例子只是為了演示,如果要真正使用版本控制系統(tǒng),就要以純文本方式編寫(xiě)文件。
因?yàn)槲谋臼怯芯幋a的,比如中文有常用的GBK編碼,日文有Shift_JIS編碼,如果沒(méi)有歷史遺留問(wèn)題,強(qiáng)烈建議使用標(biāo)準(zhǔn)的UTF-8編碼,所有語(yǔ)言使用同一種編碼,既沒(méi)有沖突,又被所有平臺(tái)所支持。
言歸正傳,現(xiàn)在我們編寫(xiě)一個(gè)readme.txt文件,一定要放到learngit目錄下(子目錄也行),內(nèi)容如下:
$ cd /var/www/git
$ sudo vi x.txt
Git is aversion control system.
Git is free software.
第一步,用命令git add告訴Git,把文件添加到倉(cāng)庫(kù)中的暫存區(qū)(stage)
$ sudo git add x.txt
第二步,用命令git commit告訴Git,把文件提交到倉(cāng)庫(kù)(master):
$ sudo git commit -m "wrote a x file"
*** Please tell me who you are.
Run
? git config --global user.email "you@example.com"
? git config --global user.name "Your Name"
to set your account's default identity.
Omit --global to set the identity only in this repository.
fatal: unable to auto-detect email address (got 'root@hunter.(none)')
$ sudo git commit -m "wrote a x file"
[master (root-commit) a2d5804] wrote a x file ?
1 file changed, 2 insertions(+) ?
create mode 100644 x.txt
On branch master
nothing to commit, working tree clean
簡(jiǎn)單解釋一下git commit命令,-m后面輸入的是本次提交的說(shuō)明,可以輸入任意內(nèi)容,當(dāng)然最好是有意義的,這樣你就能從歷史記錄里方便地找到改動(dòng)記錄。
git commit命令執(zhí)行成功后會(huì)告訴你,
1 file changed:1個(gè)文件被改動(dòng)(我們新添加的x.txt文件);
2 insertions:插入了兩行內(nèi)容(x.txt有兩行內(nèi)容)。
為什么Git添加文件需要add,commit一共兩步呢?因?yàn)閏ommit可以一次提交很多文件,所以你可以多次add不同的文件,比如:
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."
時(shí)光穿梭機(jī)
我們已經(jīng)成功地添加并提交了一個(gè)x.txt文件,現(xiàn)在,是時(shí)候繼續(xù)工作了,于是,我們繼續(xù)修改x.txt文件,改成如下內(nèi)容:
Git is adistributed version control system.
Git is free software.
運(yùn)行g(shù)it status命令看看結(jié)果:
$ git status
On branch master
Changes not staged for commit:
? (use "git add ..." to update what will be committed)
? (use "git checkout -- ..." to discard changes in working directory)
modified:? x.txt
no changes added to commit (use "git add" and/or "git commit -a")
上面的命令輸出告訴我們,x.txt被修改過(guò)了,但還沒(méi)有準(zhǔn)備提交的修改。
雖然Git告訴我們x.txt被修改了,用git diff這個(gè)命令查看哪里被修改了:
Git is adistributed version control system.
$ git diff x.txt
diff --git a/x.txt b/x.txt
index 71e87b0..96c4da4 100644
--- a/x.txt
+++ b/x.txt
@@ -1,2 +1,2 @@
-Git is aversion control system.
+Git is adistributed version control system.
?Git is free software.
提交修改后的文件
$ sudo git add x.txt
$ sudo git commit -m "distributed"
[master eb73f77] distributed
?1 file changed, 1 insertion(+), 1 deletion(-)
日志
$ git log
commitde7a75c11e737925ddd25008c774d5d7d06c7be5
Author:LearnGit
Date:?? Wed Jul 3 23:06:25 2019 +0800
??? distributed
commit ca91d6c09c7eede5f5c09dcdc2cedef87bfea5bf
Author:LearnGit
Date:?? Wed Jul 3 22:50:13 2019 +0800
??? distributed
commitc1cf56d4d7fa4aca0440ea9cc43621d2c7456443
Author:LearnGit
Date:?? Wed Jul 3 22:20:27 2019 +0800
wrote areadme file
日志加參數(shù)
$ git log--pretty=oneline
eb73f777542fed5803e340de0106ff86ba617290 (HEAD -> master) distributed
1afa098e10b436ddda7f48da3ed63776ea1141ef distributed
8691734ccb275193eb03a3c58ba5f7ed706653a1 wrote a readme file
返回上一個(gè)版本
$ git reset --hard HEAD^
HEAD is now at ca91d6c distributed
Git必須知道當(dāng)前版本是哪個(gè)版本,在Git中,用HEAD表示當(dāng)前版本,也就是最新的提交1094adb...(注意我的提交ID和你的肯定不一樣),上一個(gè)版本就是HEAD^,上上一個(gè)版本就是HEAD^^,當(dāng)然往上100個(gè)版本寫(xiě)成HEAD~100。
跳到某個(gè)版本
$ git reset --hard
de7a75
HEAD isnow at de7a75c distributed
Git的history
$ git reflog
激活虛擬主機(jī)。
【遠(yuǎn)程倉(cāng)庫(kù)】
到目前為止,我們已經(jīng)掌握了如何在Git倉(cāng)庫(kù)里對(duì)一個(gè)文件進(jìn)行時(shí)光穿梭,你再也不用擔(dān)心文件備份或者丟失的問(wèn)題了。
可是有用過(guò)集中式版本控制系統(tǒng)SVN的童鞋會(huì)站出來(lái)說(shuō),這些功能在SVN里早就有了,沒(méi)看出Git有什么特別的地方。
沒(méi)錯(cuò),如果只是在一個(gè)倉(cāng)庫(kù)里管理文件歷史,Git和SVN真沒(méi)啥區(qū)別。為了保證你現(xiàn)在所學(xué)的Git物超所值,將來(lái)絕對(duì)不會(huì)后悔,同時(shí)為了打擊已經(jīng)不幸學(xué)了SVN的童鞋,本章開(kāi)始介紹Git的殺手級(jí)功能之一(注意是之一,也就是后面還有之二,之三……):遠(yuǎn)程倉(cāng)庫(kù)。
Git是分布式版本控制系統(tǒng),同一個(gè)Git倉(cāng)庫(kù),可以分布到不同的機(jī)器上。怎么分布呢?最早,肯定只有一臺(tái)機(jī)器有一個(gè)原始版本庫(kù),此后,別的機(jī)器可以“克隆”這個(gè)原始版本庫(kù),而且每臺(tái)機(jī)器的版本庫(kù)其實(shí)都是一樣的,并沒(méi)有主次之分。
你肯定會(huì)想,至少需要兩臺(tái)機(jī)器才能玩遠(yuǎn)程庫(kù)不是?但是我只有一臺(tái)電腦,怎么玩?
其實(shí)一臺(tái)電腦上也是可以克隆多個(gè)版本庫(kù)的,只要不在同一個(gè)目錄下。不過(guò),現(xiàn)實(shí)生活中是不會(huì)有人這么傻的在一臺(tái)電腦上搞幾個(gè)遠(yuǎn)程庫(kù)玩,因?yàn)橐慌_(tái)電腦上搞幾個(gè)遠(yuǎn)程庫(kù)完全沒(méi)有意義,而且硬盤(pán)掛了會(huì)導(dǎo)致所有庫(kù)都掛掉,所以我也不告訴你在一臺(tái)電腦上怎么克隆多個(gè)倉(cāng)庫(kù)。
實(shí)際情況往往是這樣,找一臺(tái)電腦充當(dāng)服務(wù)器的角色,每天24小時(shí)開(kāi)機(jī),其他每個(gè)人都從這個(gè)“服務(wù)器”倉(cāng)庫(kù)克隆一份到自己的電腦上,并且各自把各自的提交推送到服務(wù)器倉(cāng)庫(kù)里,也從服務(wù)器倉(cāng)庫(kù)中拉取別人的提交。
完全可以自己搭建一臺(tái)運(yùn)行Git的服務(wù)器,不過(guò)現(xiàn)階段,為了學(xué)Git先搭個(gè)服務(wù)器絕對(duì)是小題大作。好在這個(gè)世界上有個(gè)叫GitHub的神奇的網(wǎng)站,從名字就可以看出,這個(gè)網(wǎng)站就是提供Git倉(cāng)庫(kù)托管服務(wù)的,所以,只要注冊(cè)一個(gè)GitHub賬號(hào),就可以免費(fèi)獲得Git遠(yuǎn)程倉(cāng)庫(kù)。
在繼續(xù)閱讀后續(xù)內(nèi)容前,請(qǐng)自行注冊(cè)GitHub賬號(hào)。
由于你的本地Git倉(cāng)庫(kù)和GitHub倉(cāng)庫(kù)之間的傳輸是通過(guò)SSH加密的,所以,需要一點(diǎn)設(shè)置:
第1步:創(chuàng)建SSH Key。在用戶(hù)主目錄下,看看有沒(méi)有.ssh目錄,如果有,再看看這個(gè)目錄下有沒(méi)有id_rsa和id_rsa.pub這兩個(gè)文件,如果已經(jīng)有了,可直接跳到下一步。如果沒(méi)有,打開(kāi)Shell(Windows下打開(kāi)Git Bash),創(chuàng)建SSH Key:
$ ssh-keygen -t rsa -C "youremail@example.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/~/.ssh/id_rsa):? ? ? ? ?
Enter passphrase (empty for no passphrase):?
Enter same passphrase again:?
Your identification has been saved in /home/~/.ssh/id_rsa.
Your public key has been saved in /home/~/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:*
你需要把郵件地址換成你自己的郵件地址,然后一路回車(chē),使用默認(rèn)值即可,由于這個(gè)Key也不是用于軍事目的,所以也無(wú)需設(shè)置密碼。
如果一切順利的話,可以在用戶(hù)主目錄里找到.ssh目錄,里面有id_rsa和id_rsa.pub兩個(gè)文件,這兩個(gè)就是SSH Key的秘鑰對(duì),id_rsa是私鑰,不能泄露出去,id_rsa.pub是公鑰,可以放心地告訴任何人。
第2步:登陸GitHub,打開(kāi)“Account settings”,“SSH Keys”頁(yè)面:
然后,點(diǎn)“Add SSH Key”,填上任意Title,在Key文本框里粘貼id_rsa.pub文件的內(nèi)容
【添加遠(yuǎn)程庫(kù)】
現(xiàn)在的情景是,你已經(jīng)在本地創(chuàng)建了一個(gè)Git倉(cāng)庫(kù)后,又想在GitHub創(chuàng)建一個(gè)Git倉(cāng)庫(kù),并且讓這兩個(gè)倉(cāng)庫(kù)進(jìn)行遠(yuǎn)程同步,這樣,GitHub上的倉(cāng)庫(kù)既可以作為備份,又可以讓其他人通過(guò)該倉(cāng)庫(kù)來(lái)協(xié)作,真是一舉多得。
首先,登陸GitHub,然后,在右上角找到“Create a new repo”按鈕,創(chuàng)建一個(gè)新的倉(cāng)庫(kù):
目前,在GitHub上的這個(gè)BenBen倉(cāng)庫(kù)還是空的,GitHub告訴我們,可以從這個(gè)倉(cāng)庫(kù)克隆出新的倉(cāng)庫(kù),也可以把一個(gè)已有的本地倉(cāng)庫(kù)與之關(guān)聯(lián),然后,把本地倉(cāng)庫(kù)的內(nèi)容推送到GitHub倉(cāng)庫(kù)。
usage: git remote add [<options>] <name> <url>
? ? -f, --fetch? ? ? ? ? fetch the remote branches
? ? --tags? ? ? ? ? ? ? ? import all tags and associated objects when fetching
? ? ? ? ? ? ? ? ? ? ? ? ? or do not fetch any tag at all (--no-tags)
? ? -t, --track ? branch(es) to track
? ? -m, --master
? ? ? ? ? ? ? ? ? ? ? ? ? master branch
? ? --mirror[=]
? ? ? ? ? ? ? ? ? ? ? ? ? set up remote as a mirror to push to or fetch from
現(xiàn)在,我們根據(jù)GitHub的提示,在本地的BenBen倉(cāng)庫(kù)下運(yùn)行命令:
$ sudo git remote add origin git@github.com:qu6zhi/x.git
請(qǐng)千萬(wàn)注意,把上面的qu6zhi替換成你自己的GitHub賬戶(hù)名,否則,你在本地關(guān)聯(lián)的就是我的遠(yuǎn)程庫(kù),關(guān)聯(lián)沒(méi)有問(wèn)題,但是你以后推送是推不上去的,因?yàn)槟愕腟SH Key公鑰不在我的賬戶(hù)列表中。
添加后,遠(yuǎn)程庫(kù)的名字就是origin,這是Git默認(rèn)的叫法,也可以改成別的,但是origin這個(gè)名字一看就知道是遠(yuǎn)程庫(kù)。
下一步,就可以把本地庫(kù)的所有內(nèi)容推送到遠(yuǎn)程庫(kù)上:
$ sudo git push -u origin master
把本地庫(kù)的內(nèi)容推送到遠(yuǎn)程,用git push命令,實(shí)際上是把當(dāng)前分支master推送到遠(yuǎn)程。
由于遠(yuǎn)程庫(kù)是空的,我們第一次推送master分支時(shí),加上了-u參數(shù),Git不但會(huì)把本地的master分支內(nèi)容推送的遠(yuǎn)程新的master分支,還會(huì)把本地的master分支和遠(yuǎn)程的master分支關(guān)聯(lián)起來(lái),在以后的推送或者拉取時(shí)就可以簡(jiǎn)化命令。