Git版本控制器使用總結性梳理


 

Git為何物?
Git 是什么?大家肯定會說不就是版本控制器嘛,是的Git是目前世界上最先進的分布式版本控制系統(沒有之一)。
1)那什么是版本控制器?
舉個簡單的例子,比如我們用Word寫文章,那你一定有這樣的經歷:比如增加一個段落你得復制一份,你刪除一個段落你又得復制一份,防止下次又要修改保留上次你要刪除的段落。最后一個接一個的版本,你復制了很多版本,最后可能你自己都不知道修改了哪些?嘿嘿,然后你只能一個一個的找,太麻煩了,若是有東西幫你管理那應該多好。
2)分布式管理
你寫的文章或書,你肯定會給你朋友或者其他人看,讓他們給你建議並做相應的修改,然后他們用郵件或U盤再發給你,你再合並修改一下,真是麻煩,於是你想,如果有一個軟件,不但能自動幫我記錄每次文件的改動,還可以讓朋友之間協作編輯,這樣就不用自己管理一堆類似的文件了,也不需要把文件傳來傳去。如果想查看某次改動,只需要在軟件看一眼就可以,豈不是很方便?這個軟件用起來就應該像這個樣子,能記錄每次文件的改動:

版本 用戶 說明 修改日期
1 user1 增加一行內容 2014/4/10 10:22
2 user2 修改一行內容 2014/4/10 13:12
3 user3 刪除幾個字 2014/4/15 20:42
4 user2 增加某個內容 2014/4/20 16:32

Git 的誕生
簡單說:Linus開發Linux內核,需要版本控制器,於是開發了Git。下面是開發周期:
1)2005/4/3 開發;
2)2005/4/6 發布;
3)2005/4/7 管理自身;
4)2005/6/16 管理Kernel2.6.12。
大牛是怎么定義的呢?大家可以體會一下。哈哈^_^…… Git 迅速成為最流行的分布式版本控制系統,尤其是2008年,GitHub網站上線了,它為開源項目免費提供Git存儲,無數開源項目開始遷移至GitHub,包括jQuery,PHP,Ruby等等。至於Git與GitHub的關系,會再下面的文章里說明。

集中管理 VS 分布式管理
Linus一直痛恨的CVS及SVN都是集中式的版本控制系統,而Git是分布式版本控制系統,集中式和分布式版本控制系統有什么區別呢? 下面我們來看看兩張圖:
1)集中管理

集中式版本控制系統,版本庫是集中存放在中央服務器的,而干活的時候,用的都是自己的電腦,所以要先從中央服務器取得最新的版本,然后開始干活,干完活了,再把自己的活推送給中央服務器。中央服務器就好比是一個圖書館,你要改一本書,必須先從圖書館借出來,然后回到家自己改,改完了,再放回圖書館。

缺點:
集中式版本控制系統最大的毛病就是必須聯網才能工作,如果在局域網內還好,帶寬夠大,速度夠快,可如果在互聯網上,遇到網速慢的話,可能提交一個10M~20M的文件就需要10分鍾甚至更多時間,這還不得把人給急死啊。

2)分布式管理

那分布式版本控制系統與集中式版本控制系統有何不同呢?首先,分布式版本控制系統沒有“中央服務器”,每個人的電腦上都是一個完整的版本庫,這樣,你工作的時候,就不需要聯網了,因為版本庫就在你自己的電腦上。既然每個人電腦上都有一個完整的版本庫,那多個人如何協作呢?比方說你在自己電腦上改了文件fiel,你的同事也在他的電腦上改了文件file,這時,你們倆之間只需把各自的修改推送給對方,就可以互相看到對方的修改了。

和集中式版本控制系統相比,分布式版本控制系統的安全性要高很多,因為每個人電腦里都有完整的版本庫,某一個人的電腦壞掉了不要緊,隨便從其他人那里復制一個就可以了。而集中式版本控制系統的中央服務器要是出了問題,所有人都沒法干活了。
在實際使用分布式版本控制系統的時候,其實很少在兩人之間的電腦上推送版本庫的修改,因為可能你們倆不在一個局域網內,兩台電腦互相訪問不了,也可能今天你的同事病了,他的電腦壓根沒有開機。因此,分布式版本控制系統通常也有一台充當“中央服務器”的電腦,但這個服務器的作用僅僅是用來方便“交換”大家的修改,沒有它大家也一樣干活,只是交換修改不方便而已。如上圖!

Git特點

1)分布式
2)存儲快照而非差異
3)本地有完全的版本庫,幾乎所有操作都在本地
4)有內在的一致性,SHA1
5)優秀的分支管理
6)支持各種協同模式
7)開源,有一些第三方軟件可整合使用,幾乎所有操作都是

與CVS/SVN,Git 的優勢
1)支持離線開發,離線Repository(倉庫)
2)強大的分支功能,適合多個獨立開發者協作
3)速度塊

為什么選擇Git來控制版本,理由如下:

1)快速 
如果你每移動一下鼠標都要等待五秒,是不是很受不了?版本控制也是一樣的,每一個命令多那么幾秒鍾,一天下來也會浪費你不少時間。Git的操作非常快速,你可以把時間用在別的更有意義的地方。 
2)離線工作 
在沒有網絡的情況下如何工作?如果你用SVN或者CVS的話就很麻煩。而Git可以讓你在本地做所有操作,提交代碼,查看歷史,合並,創建分支等等。 
3)回退 
人難免犯錯。我很喜歡Git的一點就是你可以“undo”幾乎所有的命令。你可以用這個功能來修正你剛剛提交的代碼中的一個問題或者回滾整個代碼提交操作。你甚至可以恢復一個被刪除的提交,因為在后端,Git幾乎不做任何刪除操作。
4)省心 
你有沒有丟失過版本庫?我有,而那種頭疼的感覺現在還記憶猶新。而用Git的話,我就不必擔心這個問題,因為任何一個人機器上的版本都是一個完整的備份。 
5)選擇有用的代碼提交 
當你把紐帶,冰塊還有西紅柿一起扔進攪拌機的時候至少有兩個問題。第一,攪拌過后,沒有人知道之前扔進去了些什么東西。第二,你不能回退,重新把西紅柿拿出來。同樣的,當你提交了一堆無關的更改,例如功能A加強,新增功能B,功能C修復,想要理清這一堆代碼到底干了什么是很困難的。當然,當發現功能A出問題的時候,你無法單獨回滾功能A。Git可以通過創建“顆粒提交”,幫你解決這個問題。“staging area”的概念可以讓你決定到底那些東西需要提交,或者更新,精確到行。
6)自由選擇工作方式 
使用Git,你可以同時和多個遠程代碼庫連接,“rebase”而不是"merge"甚至只連接某個模塊。但是你也可以選擇一個中央版本庫,就像SVN那樣。你依然可以利用Git的其他優點。 
7)保持工作獨立 
把不同的問題分開處理將有助於跟蹤問題的進度。當你在為功能A工作的時候,其他人不應該被你還沒有完成的代碼所影響。分支是解決這個問題的辦法。雖然其他的版本控制軟件業有分支系統,但是Git是第一個把這個系統變得簡單而快速的系統。
8)隨大流 
雖然只有死於才隨着波浪前進,但是很多時候聰明的程序員也是隨大流的。越來越多的公司,開源項目使用Git,包括Ruby On Rails,jQuery,Perl,Debian,Linux Kernel等等。擁有一個強大的社區是很大的優勢,有很多教程、工具。

Git原理

1)四種基本類型
BLOB:  每個blob代表一個(版本的)文件,blob只包含文件的數據,而忽略文件的其他元數據,如名字、路徑、格式等。
TREE:  每個tree代表了一個目錄的信息,包含了此目錄下的blobs,子目錄(對應於子trees),文件名、路徑等元數據。因此,對於有子目錄的目錄,git相當於存儲了嵌套的trees。
COMMIT:每個commit記錄了提交一個更新的所有元數據,如指向的tree,父commit,作者、提交者、提交日期、提交日志等。每次提交都指向一個tree對象,記錄了當次提交時的目錄信息。一個commit可以有多個(至少一個)父commits。
TAG:   ag用於給某個上述類型的對象指配一個便於開發者記憶的名字, 通常用於某次commit。

2)工作區(Working Dir),提交區/暫存區(stage/index),版本庫 

 

Git的安裝

不同的系統不同的安裝命令,centos系統下直接yum就可以。
[root@master-node ~]# yum install -y git
安裝完成后,還需要最后一步設置,在命令行輸入:
[root@master-node ~]#git config --global user.email "you@example.com"
[root@master-node ~]#git config --global user.name "Your Name"
因為Git是分布式版本控制系統,所以,每個機器都必須自報家門:你的名字和Email地址。你也許會擔心,如果有人故意冒充別人怎么辦?這個不必擔心,首先我們相信大家都是善良無知的群眾,其次,真的有冒充的也是有辦法可查的。
注意:
git config命令的--global參數,用了這個參數,表示你這台機器上所有的Git倉庫都會使用這個配置,當然也可以對某個倉庫指定不同的用戶名和Email地址。

Git常用的命令(即git + 下面的參數組成的命令):

add           添加文件內容至索引
bisect       通過二分查找定位引入 bug 的變更
branch     列出、創建或刪除分支
checkout  檢出一個分支或路徑到工作區
clone       克隆一個版本庫到一個新目錄
commit    記錄變更到版本庫
diff          顯示提交之間、提交和工作區之間等的差異
fetch       從另外一個版本庫下載對象和引用
grep        輸出和模式匹配的行
init         創建一個空的 Git 版本庫或重新初始化一個已存在的版本庫
log         顯示提交日志
merge    合並兩個或更多開發歷史
mv        移動或重命名一個文件、目錄或符號鏈接
pull       獲取並合並另外的版本庫或一個本地分支
push     更新遠程引用和相關的對象
rebase  本地提交轉移至更新后的上游分支中
reset    重置當前HEAD到指定狀態
rm       從工作區和索引中刪除文件
show    顯示各種類型的對象
status  顯示工作區狀態
tag      創建、列出、刪除或校驗一個GPG簽名的 tag 對象

創建版本庫

什么是版本庫呢?版本庫又名倉庫,英文名repository,你可以簡單理解成一個目錄,這個目錄里面的所有文件都可以被Git管理起來,每個文件的修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以“還原”。
所以,創建一個版本庫非常簡單,首先,選擇一個合適的地方,創建一個空目錄:

第一步:創建一個倉庫的目錄
[root@master-node /]# mkdir git_test
[root@master-node /]# cd git_test/
[root@master-node git_test]# pwd
/git_test

第二步:通過git init 命令把這個目錄變成git可以管理的倉庫
[root@master-node git_test]# git init
初始化空的 Git 版本庫於 /git_test/.git/
[root@master-node git_test]# ls -al
總用量 12
drwxr-xr-x 3 root root 4096 5月 10 13:53 .
drwxr-xr-x. 19 root root 4096 5月 10 13:50 ..
drwxr-xr-x 7 root root 4096 5月 10 13:53 .git
瞬間Git就把倉庫建好了,而且告訴你是一個空的倉庫(empty Git repository),細心的讀者可以發現當前目錄下多了一個.git的目錄,這個目錄是Git來跟蹤管理版本庫的,沒事千萬不要手動修改這個目錄里面的文件,不然改亂了,就把Git倉庫給破壞了。也不一定必須在空目錄下創建Git倉庫,選擇一個已經有東西的目錄也是可以的。

第三步:把文件添加到版本庫
首先這里再明確一下,所有的版本控制系統,其實只能跟蹤文本文件的改動,比如TXT文件,網頁,所有的程序代碼等等,Git也不例外。版本控制系統可以告訴你每次的改動,比如在第5行加了一個單詞“Linux”,在第8行刪了一個單詞“Windows”。而圖片、視頻這些二進制文件,雖然也能由版本控制系統管理,但沒法跟蹤文件的變化,只能把二進制文件每次改動串起來,也就是只知道圖片從100KB改成了120KB,但到底改了啥,版本控制系統不知道,也沒法知道。

現在我們編寫一個readme.txt文件,內容如下
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
一定要放到git_test目錄下面,子目錄也可以,放到其他地方git找不到文件。

把一個文件放到Git倉庫只需要兩步。
1)用命令git add告訴git,把文件添加到倉庫
[root@master-node git_test]# git add readme.txt
執行上面的命令,沒有任何的顯示就對了。Linux的哲學思想:沒有消息就是最好的消息,說明添加成功。
2)用命令git commit告訴git,把文件提交到倉庫
[root@master-node git_test]# git commit -m "cgt write a readme file"
[master(根提交) 87818f5] cgt write a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt

簡單解釋一下git commit命令,-m后面輸入的是本次提交的說明,可以輸入任意內容,當然最好是有意義的,這樣你就能從歷史記錄里方便地找到改動記錄。
嫌麻煩不想輸入-m "xxx"行不行?確實有辦法可以這么干,但是強烈不建議你這么干,因為輸入說明對自己對別人閱讀都很重要。實在不想輸入說明的童鞋請自行Google,我不告訴你這個參數。
git commit命令執行成功后會告訴你,1個文件被改動(我們新添加的readme.txt文件),插入了兩行內容(readme.txt有兩行內容)。

為什么Git添加文件需要add,commit一共兩步呢?因為commit可以一次提交很多文件,所以你可以多次add不同的文件,比如:
[root@master-node git_test]# touch file1 file2 file3
[root@master-node git_test]# ls
file1 file2 file3 readme.txt
[root@master-node git_test]# git add file1 file2 file3
[root@master-node git_test]# git commit -m "add 3 files"
[master 827526e] add 3 files
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file1
create mode 100644 file2
create mode 100644 file3

再次插足一下,說明一下git的工作流:

你的本地倉庫由 git 維護的三棵"樹"組成。第一個是你的 工作目錄,它持有實際文件;第二個是 暫存區(staging),它像個緩存區域,臨時保存你的改動;最后是 HEAD,它指向你最后一次提交的結果。
你可以提出更改(把它們添加到暫存區),使用如下命令:
git add <filename>
git add *
這是 git 基本工作流程的第一步;使用如下命令以實際提交改動:
git commit -m "代碼提交信息"
現在,你的改動已經提交到了 HEAD,但是還沒到你的遠端倉庫。

回滾-讓去哪就去哪

前面已經創建了一個readme.txt文件,現在我們對他進行一些改動操作。
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
執行git status 
[root@master-node git_test]# git status
# 位於分支 master
# 尚未暫存以備提交的變更:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工作區的改動)
#
# 修改: readme.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
git status命令可以讓我們時刻掌握倉庫當前的狀態,上面的命令告訴我們,readme.txt被修改過了,但還沒有准備提交的修改。
雖然Git告訴我們readme.txt被修改了,但如果能看看具體修改了什么內容,自然是很好的。比如你第二天上班時,已經記不清上次怎么修改的readme.txt,所以,需要用git diff這個命令看看,然后add之后在看一下status,是顯示要commit的文件,現在再回想一下那個工作流圖
[root@master-node git_test]# git diff
diff --git a/readme.txt b/readme.txt
index b7cffdb..43b7253 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,3 @@
Git is veryt good tool
auth :cgt
+date:2016-5-10
[root@master-node git_test]# git add readme.txt
[root@master-node git_test]# git status
# 位於分支 master
# 要提交的變更:
# (使用 "git reset HEAD <file>..." 撤出暫存區)
#
# 修改: readme.txt
接下來進行commit操作
[root@master-node git_test]# git commit -m "add date"
[master de00305] add date
1 file changed, 1 insertion(+)
提交之后,在查看status
[root@master-node git_test]# git status
# 位於分支 master
無文件要提交,干凈的工作區

版本的回退

現在,你已經學會了修改文件,然后把修改提交到Git版本庫,現在,再練習一次,修改readme.txt文件如下:
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
version:1
[root@master-node git_test]# git add readme.txt
[root@master-node git_test]# git commit -m "version"
[master 8b7d4ee] version
1 file changed, 1 insertion(+)

目前我們已經提交了三次,暫時你還能記住,但是在實際工作中我們是記不住的,不然要版本控制系統干什么。版本控制系統肯定有某個命令可以告訴我們歷史記錄,在Git中,我們用git log命令查看:
[root@master-node git_test]# git log
commit 8b7d4eebe4e03809162f8193d6b2338926896ab4
Author: caoxiaojian <1099415469@qq.com>
Date: Tue May 10 14:59:16 2016 +0800
version
commit de003058c91312f695b57f42724f826f6ef42f17
Author: caoxiaojian <1099415469@qq.com>
Date: Tue May 10 14:52:10 2016 +0800
add date
commit 827526ee243c93bfaf8f4f2f9dc22d31325cb47a
Author: caoxiaojian <1099415469@qq.com>
Date: Tue May 10 14:23:08 2016 +0800
add 3 files
commit 87818f5454a2bc41cfbeca4b923a510d11fe72ac
Author: caoxiaojian <1099415469@qq.com>
Date: Tue May 10 14:19:08 2016 +0800
cgt write a readme file
git log 顯示從最近到最遠的提交日志,我們可以看到四次提交,最近的一次是version,上一次是date,最早的一次是cgt write a readme file 。

如果嫌輸出的信息太多,可以使用--pretty=oneline
[root@master-node git_test]# git log --pretty=oneline
8b7d4eebe4e03809162f8193d6b2338926896ab4 version
de003058c91312f695b57f42724f826f6ef42f17 add date
827526ee243c93bfaf8f4f2f9dc22d31325cb47a add 3 files
87818f5454a2bc41cfbeca4b923a510d11fe72ac cgt write a readme file

需要友情提示的是,你看到的一大串8b7d4eebe4e03809162f8193d6b2338926896ab4類似的是commit id(版本號),和SVN不一樣,Git的commit id不是1,2,3……遞增的數字,而是一個SHA1計算出來的一個非常大的數字,用十六進制表示,而且你看到的commit id和我的肯定不一樣,以你自己的為准。為什么commit id需要用這么一大串數字表示呢?因為Git是分布式的版本控制系統,后面我們還要研究多人在同一個版本庫里工作,如果大家都用1,2,3……作為版本號,那肯定就沖突了。

現在開始回滾,
准備把readme.txt回退到上一個版本,也就是“date”的那個版本,怎么做呢?
首先,Git必須知道當前版本是哪個版本,在Git中,用HEAD表示當前版本,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一樣),上一個版本就是HEAD^,上上一個版本就是HEAD^^,當然往上100個版本寫100個^比較容易數不過來,所以寫成HEAD~100。
回滾,我們可以使用git reset這個命令

[root@master-node git_test]# git reset --hard HEAD^
HEAD 現在位於 de00305 add date
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
可以看出,他沒有version那行,說明回滾成功。

再來看git log 
[root@master-node git_test]# git log
commit de003058c91312f695b57f42724f826f6ef42f17
Author: caoxiaojian <1099415469@qq.com>
Date: Tue May 10 14:52:10 2016 +0800
add date
commit 827526ee243c93bfaf8f4f2f9dc22d31325cb47a
Author: caoxiaojian <1099415469@qq.com>
Date: Tue May 10 14:23:08 2016 +0800
add 3 files
commit 87818f5454a2bc41cfbeca4b923a510d11fe72ac
Author: caoxiaojian <1099415469@qq.com>
Date: Tue May 10 14:19:08 2016 +0800
cgt write a readme file
沒有了之前的version,那我要怎么才能恢復呢,回你的終端上,看看version的commit id,我們找到了:
8b7d4eebe4e03809162f8193d6b2338926896ab4 version,執行恢復。恢復的時候ID不需要寫全部的。
[root@master-node git_test]# git reset --hard 8b7d4eebe4
HEAD 現在位於 8b7d4ee version
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
version:1

回滾原理解析:
Git的版本回退速度非常快,因為Git在內部有個指向當前版本的HEAD指針,當你回退版本的時候,Git僅僅是把HEAD從當前的version,指到date

回滾后

然后順便把工作區的文件更新了。所以你讓HEAD指向哪個版本號,你就把當前版本定位在哪。
到了這里肯定有童鞋要問,那我要是不知道我前面的ID了,我去哪里回滾,我是不是該收拾工位回滾到家中了,git早就替你想好了,可以使用git reflog,把之前的ID都顯示出來
[root@master-node git_test]# git reflog
8b7d4ee HEAD@{0}: reset: moving to 8b7d4eebe4
de00305 HEAD@{1}: reset: moving to HEAD^
8b7d4ee HEAD@{2}: commit: version
de00305 HEAD@{3}: commit: add date
827526e HEAD@{4}: commit: add 3 files
87818f5 HEAD@{5}: commit (initial): cgt write a readme file

工作區和暫存區
不知道你是不是理解了我之前說的那個工作流,咱們這里再來啰嗦一遍。
Git和其他版本控制系統如svn不同之處是有暫存區的概念

先弄清楚這幾個名次
工作區:
就是在你的電腦里能看到的目錄,比如咱們創建的git_test

版本庫:
工作區中有一個隱藏目錄.git(之前已經給童鞋們提到過這個文件),它不算工作區,而是git的版本庫。

git的版本庫里面存放了很多的東西,其中最重要的就是稱為stage(index)的暫存區,還有git為我們自動創建的第一個分支master,以及指向master的一個指針叫head。

當我們在工作區創建了文件后,執行add后,再來看這個圖

當你執行commit后,暫存區的內容就沒有

管理修改

為什么Git比其他版本控制系統設計得優秀,因為Git跟蹤並管理的是修改,而非文件。
你會問,什么是修改?比如你新增了一行,這就是一個修改,刪除了一行,也是一個修改,更改了某些字符,也是一個修改,刪了一些又加了一些,也是一個修改,甚至創建一個新文件,也算一個修改。
為什么說Git管理的是修改,而不是文件呢?我們還是做實驗。第一步,對readme.txt做一個修改,第二步,添加到暫存區。第三步,查看狀態
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
version:1
modify----------1
[root@master-node git_test]# git add readme.txt
[root@master-node git_test]# git status
# 位於分支 master
# 要提交的變更:
# (使用 "git reset HEAD <file>..." 撤出暫存區)
#
# 修改: readme.txt
#
第四步,再次編輯readme.txt,然后直接commit,再次查看status

[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
version:1
modify----------1
modify----------2
[root@master-node git_test]# git commit -m "modify"
[master 766baac] modify
1 file changed, 1 insertion(+)
[root@master-node git_test]# git status
# 位於分支 master
# 尚未暫存以備提交的變更:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工作區的改動)
#
# 修改: readme.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
發現第二次的修改沒有commit,那是因為你沒有add

提交后,用git diff HEAD -- readme.txt命令可以查看工作區和版本庫里面最新版本的區別:

[root@master-node git_test]# git diff HEAD -- readme.txt
diff --git a/readme.txt b/readme.txt
index 4416460..07c12e7 100644
--- a/readme.txt
+++ b/readme.txt
@@ -3,3 +3,4 @@ auth :cgt
date:2016-5-10
version:1
modify----------1
+modify----------2

撤銷修改

編輯了readme,
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
version:1
modify----------1
modify----------2
caoxiaojian is xiaojianjian
已經編輯完成,忽然發現了問題,最后一行,道出了筆者的心聲。既然已經發現錯誤,那就很容易糾正它,你可以刪除掉最后一行,手動把文件恢復到上一個版本的狀態,如果用git status查看一下,

[root@master-node git_test]# git status
# 位於分支 master
# 尚未暫存以備提交的變更:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工作區的改動)
#
# 修改: readme.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
你可以發現上面提示你使用 "git checkout -- <file>..." 丟棄工作區的改動,那我們執行下

[root@master-node git_test]# git checkout -- readme.txt
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
version:1
modify----------1
已經回來了。

命令git checkout -- readme.txt意思就是,把readme.txt文件在工作區的修改全部撤銷,這里有兩種情況:
一種是readme.txt自修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
一種是readme.txt已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。
總之,就是讓這個文件回到最近一次git commit或git add時的狀態。
git checkout -- file命令中的--很重要,沒有--,就變成了“切換到另一個分支”的命令,我們在后面的分支管理中會再次遇到git checkout命令。
剛剛咱們沒有將修改提交到暫存區,那假如你提交到了呢??????你說咋整呢?????是不是嚇尿了????
[root@master-node git_test]# cat readme.txt
Git is veryt good tool
auth :cgt
date:2016-5-10
version:1
modify----------1
caoxiaojian is xiaojianjian
[root@master-node git_test]# git add readme.txt
[root@master-node git_test]# git status
# 位於分支 master
# 要提交的變更:
# (使用 "git reset HEAD <file>..." 撤出暫存區)
# 修改: readme.txt
你要是聰明的話,你應該已經知道要怎么做了。。。。對是的,就是你想的那樣。

[root@master-node git_test]# git reset HEAD readme.txt
重置后撤出暫存區的變更:
M readme.txt
[root@master-node git_test]# git status
# 位於分支 master
# 尚未暫存以備提交的變更:
# (使用 "git add <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工作區的改動)
#
# 修改: readme.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
已經退出了暫存區。你可能要問,那要是已經commit了呢??你小子膽子還真不小啊,教你一招,之前不是講過回滾嘛,直接回滾。不過這個也是有條件的,就是你還沒有把自己的本地版本庫推送到遠程。Git是一個分布式版本控制,他還有遠程版本庫,一旦你提交到遠程版本庫,那你就可以git go home

刪除文件

先創建文件,后add,在commit,然后刪除工作區的文件
[root@master-node git_test]# cat test.txt
qwertyuiop[
adfghjjljh
fdgscvxz
[root@master-node git_test]# git add test.txt
[root@master-node git_test]# git commit -m "del test"
[master 63d3bf7] del test
1 file changed, 3 insertions(+)
create mode 100644 test.txt
[root@master-node git_test]# rm -rf test.txt
[root@master-node git_test]# git status
# 位於分支 master
# 尚未暫存以備提交的變更:
# (使用 "git add/rm <file>..." 更新要提交的內容)
# (使用 "git checkout -- <file>..." 丟棄工作區的改動)
#
# 修改: readme.txt
# 刪除: test.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
現在你有兩個選擇,一是確實要從版本庫中刪除該文件,那就用命令git rm刪掉,並且git commit:
[root@master-node git_test]# git rm test.txt
rm 'test.txt'
[root@master-node git_test]# git commit -m "remove test.txt"
[master 5f04ee2] remove test.txt
1 file changed, 3 deletions(-)
delete mode 100644 test.txt
現在文件就從版本庫中徹底的刪除了。

命令git rm用於刪除一個文件。如果一個文件已經被提交到版本庫,那么你永遠不用擔心誤刪,但是要小心,你只能恢復文件到最新版本,你會丟失最近一次提交后你修改的內容。

另一種情況是刪錯了,因為版本庫里還有呢,所以可以很輕松地把誤刪的文件恢復到最新版本:

使用

git checkout -- test.txt
git checkout其實是用版本庫里的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。

遠程倉庫

可以使用github給我們提供的服務,作為我們的一個遠程倉庫。但是需要做一下的設置。
由於你的本地Git倉庫和GitHub倉庫之間的傳輸是通過SSH加密的,所以我們首先生成秘鑰。

第1步:創建SSH Key。
在用戶主目錄下,看看有沒有.ssh目錄,如果有,再看看這個目錄下有沒有id_rsa和id_rsa.pub這兩個文件,如果已經有了,可直接跳到下一步。如果沒有,打開Shell(Windows下打開Git Bash),創建SSH Key:
ssh-keygen -t rsa -C "youremail@example.com"
你需要把郵件地址換成你自己的郵件地址,然后一路回車,使用默認值即可,由於這個Key也不是用於軍事目的,所以也無需設置密碼。
如果一切順利的話,可以在用戶主目錄里找到.ssh目錄,里面有id_rsa和id_rsa.pub兩個文件,這兩個就是SSH Key的秘鑰對,id_rsa是私鑰,不能泄露出去,id_rsa.pub是公鑰,可以放心地告訴任何人。

第2步:添加公鑰到你的
登陸GitHub,打開“Account settings”,“SSH Keys”頁面,然后將你的key添加上。
為什么GitHub需要SSH Key呢?因為GitHub需要識別出你推送的提交確實是你推送的,而不是別人冒充的,而Git支持SSH協議,所以,GitHub只要知道了你的公鑰,就可以確認只有你自己才能推送。

添加遠程庫
你原本在本地已經創建了一個Git倉庫,現在又想在github上也創建一個倉庫,讓這兩個倉庫可以遠程同步。這樣github的倉庫既可以作為備份,又可以讓其他人通過該倉庫來協作。

第一步:創建一個新的倉庫repository
右上角有個➕,然后現在new repository

然后進入創建頁面

倉庫內容的提交

接下來咱們看如何使用
本地沒有倉庫的情況下,要先創建倉庫。
[root@master-node ~]# mkdir /test
[root@master-node ~]# cd /test
使用git init 創建定義倉庫
[root@master-node ~]# git init
Initialized empty Git repository in C:/Program Files/Git/test/.git/
[root@master-node ~]# ls -al
total 8
drwxr-xr-x 1 cgt 197121 0 五月 16 06:11 ./
drwxr-xr-x 1 cgt 197121 0 五月 16 06:11 ../
drwxr-xr-x 1 cgt 197121 0 五月 16 06:11 .git/

在倉庫中創建一個文件,然后add commit
[root@master-node ~]# echo "# test " >> README.md
[root@master-node ~]# git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory.

[root@master-node ~]# git commit -m "first commit"
[master (root-commit) 7eeb945] first commit
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory.
1 file changed, 1 insertion(+)
create mode 100644 README.md
至此,提交到本地的head中。也就是本地倉庫中,然后從本地倉庫向遠程倉庫提交。

使用remote關聯一個遠程庫,add是定義一個遠程的名稱,默認一般使用origin,后面跟的是遠程倉庫的名稱
[root@master-node ~]# git remote add origin git@github.com:caoxiaojian/test.git
把本地庫的內容推送到遠程,實際上是將本地的當前分支master,推送到遠程
[root@master-node ~]# git push -u origin master
Warning: Permanently added the RSA host key for IP address '192.30.252.128' to the list of known hosts.
Counting objects: 3, done.
Writing objects: 100% (3/3), 210 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:caoxiaojian/test.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
由於遠程庫是空的,我們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令。

再次修改README.md
[root@master-node ~]# echo "# this is my test file " >> README.md
[root@master-node ~]# git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory.
[root@master-node ~]# git commit -m "2 commit"
[master warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory.
80bc0e7] 2 commit
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory.
1 file changed, 1 insertion(+)
[root@master-node ~]# git push origin master
Warning: Permanently added the RSA host key for IP address '192.30.252.120' to the list of known hosts.
Counting objects: 3, done.
Writing objects: 100% (3/3), 257 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:caoxiaojian/test.git
7eeb945..80bc0e7 master -> master
到github下面對應的倉庫里查看

 

 

 

 

每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改

克隆遠程庫
在剛創建的倉庫中創建新文件

創建文件

 創建完成后可以看見你的新文件

因為之前已經創建了test這個本地倉庫,所以先刪除,然后再clone
[root@master-node ~]# rm -rf /test/
[root@master-node ~]# git clone git@github.com:caoxiaojian/test.git
Cloning into 'test'...
Warning: Permanently added the RSA host key for IP address '192.30.252.121' to the list of known hosts.
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 9 (delta 0), reused 6 (delta 0), pack-reused 0
Receiving objects: 100% (9/9), done.
Checking connectivity... done.
[root@master-node ~]# cd /test/
test (master)
[root@master-node ~]# ls
new_file README.md
test (master)
[root@master-node ~]# cat new_file
make a new file for clone test

分支管理
分支在實際中有什么用呢?假設你准備開發一個新功能,但是需要兩周才能完成,第一周你寫了50%的代碼,如果立刻提交,由於代碼還沒寫完,不完整的代碼庫會導致別人不能干活了。如果等代碼全部寫完再一次提交,又存在丟失每天進度的巨大風險。
現在有了分支,就不用怕了。你創建了一個屬於你自己的分支,別人看不到,還繼續在原來的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到開發完畢后,再一次性合並到原來的分支上,這樣,既安全,又不影響別人工作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM