1. 程式人生 > >Git版本管理之旅(二)—— Git基本操作流程及相關命令

Git版本管理之旅(二)—— Git基本操作流程及相關命令

本章繼續上章的型別,介紹基於空專案的版本庫操作,本教程基於Ubuntu

  • 建立版本庫
  • 新增檔案
  • 修改檔案
  • 刪除檔案
  • 版本回退
  • 基本概念
  • 管理以及撤銷修改
  • 新增到遠端倉庫
  • 從遠端倉庫克隆

建立版本庫

版本庫又名倉庫,英文名repository,可以理解成一個目錄,這個目錄裡面的所有檔案都可以被Git管理起來,每個檔案的修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史。

xq@xq-VPCEG17YC:~/git$ pwd
/home/xq/git
xq@xq-VPCEG17YC:~/git$ mkdir test
xq@xq-VPCEG17YC:~/git$ cd test/
xq@xq
-VPCEG17YC:~/git/test$ git init 初始化空的 Git 倉庫於 /home/xq/git/test/.git/ xq@xq-VPCEG17YC:~/git/test$ ls xq@xq-VPCEG17YC:~/git/test$ ls -ah . .. .git

首先新建一個test的資料夾(不一定都是空資料夾,只是託管的檔案自己需要把握),在該目錄下執行git init命令,該目錄就會變成git管理的倉庫。
目錄下多了一個.git的目錄,這個目錄是Git來跟蹤管理版本庫的,不可隨意修改。

新增檔案

xq@xq-VPCEG17YC:~/git/test$ vi hello.txt
xq@xq
-VPCEG17YC:~/git/test$ cat hello.txt this is my first try. xq@xq-VPCEG17YC:~/git/test$ git add hello.txt xq@xq-VPCEG17YC:~/git/test$ git commit -m "add a file[hello.txt]" [master (根提交) b10613a] add a file[hello.txt] 1 file changed, 1 insertion(+) create mode 100644 hello.txt

新建一個hello.txt的檔案
通過git add xxx的命令新增到本地倉庫
通過git commit的命令提交本次修改,-m是本次提交的說明,可以輸入任意內容

修改檔案

xq@xq-VPCEG17YC:~/git/test$ vi hello.txt 
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my second try.
xq@xq-VPCEG17YC:~/git/test$ git status
位於分支 master
尚未暫存以備提交的變更:
  (使用 "git add <檔案>..." 更新要提交的內容)
  (使用 "git checkout -- <檔案>..." 丟棄工作區的改動)

    修改:     hello.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
xq@xq-VPCEG17YC:~/git/test$ git diff
diff --git a/hello.txt b/hello.txt
index df723d7..55ef308 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1 @@
-this is my first try.
+this is my second try.

修改hello.txt檔案
通過git status倉庫當前的狀態
通過git diff比較差異

xq@xq-VPCEG17YC:~/git/test$ git add hello.txt 
xq@xq-VPCEG17YC:~/git/test$ git status
位於分支 master
要提交的變更:
  (使用 "git reset HEAD <檔案>..." 以取消暫存)

    修改:     hello.txt

xq@xq-VPCEG17YC:~/git/test$ git commit -m "update hello.txt"
[master 9d94f3b] update hello.txt
 1 file changed, 1 insertion(+), 1 deletion(-)
xq@xq-VPCEG17YC:~/git/test$ git status
位於分支 master
無檔案要提交,乾淨的工作區

修改之後提交檔案和新增時時一樣的,通過git status檢視各種情況下倉庫的狀態

刪除檔案

本地工作空間刪除檔案 rm xxx
Git知道你刪除了檔案,因此,工作區和版本庫就不一致了,可用git status檢視狀態
如果時本地空間誤刪可用git checkout – xxx從版本庫中檢出到本地;如果是要從版本庫中刪除該檔案,那就用命令git rm刪掉,並且git commit

版本回退

我們再次修改hello.txt然後commit
之後通過git log檢視修改記錄

xq@xq-VPCEG17YC:~/git/test$ git log --pretty=oneline
774045528c64b1b541a045093836c1845f14a908 update again
9d94f3ba85cfac45b0e30010fca1265f15e9aaf7 update hello.txt
b10613a11dbae7c93d2cf49f654ade68ad675030 add a file[hello.txt]

日誌中記錄的hash值,上一章我們解釋過
檔案在儲存到 Git 時,資料都要使用 SHA-1 演算法進行內容的校驗和(checksum)計算,得到一個 SHA-1 雜湊值,作為指紋字串。該字串由 40 個十六進位制字元(0-9 及 a-f)組成,並將此結果作為資料的唯一標識和索引。通過唯一標誌判斷檔案的完整性以及是否變更。所有儲存在 Git 資料庫中的東西都是用此雜湊值來作索引的,而不是靠檔名。

後面記錄的是我們每次commit時的說明

在Git中,用HEAD表示當前版本,也就是最新的提交,上一個版本就是HEAD^,上上一個版本就是HEAD^^,當然往上100個版本寫100個^比較容易數不過來,所以寫成HEAD~100。
以下對應hello.txt的三個版本

  • HEAD –> 774045528c64b1b541a045093836c1845f14a908
  • HEAD^ –> 9d94f3ba85cfac45b0e30010fca1265f15e9aaf7
  • HEAD^^ –> b10613a11dbae7c93d2cf49f654ade68ad675030

我們將版本回退到上一個版本,並檢視檔案,發現確實已經回退。
此時檢視日誌,發現只剩下兩個版本了。此時版本對應如下

  • HEAD –> 9d94f3ba85cfac45b0e30010fca1265f15e9aaf7
  • HEAD^ –> b10613a11dbae7c93d2cf49f654ade68ad675030
xq@xq-VPCEG17YC:~/git/test$ git reset --hard HEAD^
HEAD 現在位於 9d94f3b update hello.txt
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my second try.
xq@xq-VPCEG17YC:~/git/test$ git log  --pretty=oneline
9d94f3ba85cfac45b0e30010fca1265f15e9aaf7 update hello.txt
b10613a11dbae7c93d2cf49f654ade68ad675030 add a file[hello.txt]

當然通過git reset –hard 9d94f3ba85cf(hashId 前幾位也行,系統會自動查詢),也是可以回退的。

如果回退後,又希望恢復到第三個版本怎麼辦呢?git reflog會記錄每一次命令,然後找到對應的hashId恢復就可以啦。

xq@xq-VPCEG17YC:~/git/test$ git reflog
9d94f3b HEAD@{0}: reset: moving to HEAD^
7740455 HEAD@{1}: commit: update again
9d94f3b HEAD@{2}: commit: update hello.txt
b10613a HEAD@{3}: commit (initial): add a file[hello.txt]
xq@xq-VPCEG17YC:~/git/test$ git reset --hard 7740455
HEAD 現在位於 7740455 update again
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my third try.

基本概念

到了這裡我們繼續鞏固上一章的內容,理論+實踐+理論

  • 工作區(Working Directory)
    就是你在電腦裡能看到的目錄,比如我的test資料夾就是一個工作區
  • 版本庫(Repository)
    工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。
    Git的版本庫裡存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動建立的第一個分支master,以及指向master的一個指標叫HEAD。
    Working-Repository

前面講了我們把檔案往Git版本庫裡新增的時候,是分兩步執行的:
第一步是用git add把檔案新增進去,實際上就是把檔案修改新增到暫存區;
第二步是用git commit提交更改,實際上就是把暫存區的所有內容提交到當前分支。

因為我們建立Git版本庫時,Git自動為我們建立了唯一一個master分支,所以,現在,git commit就是往master分支上提交更改。

你可以簡單理解為,需要提交的檔案修改通通放到暫存區,然後,一次性提交暫存區的所有修改。

管理以及撤銷修改

Git比其他版本控制系統設計得優秀,因為Git跟蹤並管理的是修改,而非檔案。

比如你新增了一行,這就是一個修改,刪除了一行,也是一個修改,更改了某些字元,也是一個修改,刪了一些又加了一些,也是一個修改,甚至建立一個新檔案,也算一個修改。

我們修改hello.txt然後git add新增到暫存區,然後再次修改hello.txt,最後執行git commit命令,提交後,用git diff HEAD – hello.txt命令可以檢視工作區和版本庫裡面最新版本的區別,發現並不一致。

原因是:Git管理的是修改,當你用git add命令後,在工作區的第一次修改被放入暫存區,準備提交,但是,在工作區的第二次修改並沒有放入暫存區,所以,git commit只負責把暫存區的修改提交了,也就是第一次的修改被提交了,第二次的修改不會被提交。

xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my third try.
xq@xq-VPCEG17YC:~/git/test$ vi hello.txt 
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my fourth try.
xq@xq-VPCEG17YC:~/git/test$ git add hello.txt 
xq@xq-VPCEG17YC:~/git/test$ vi hello.txt 
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my fifth try.
xq@xq-VPCEG17YC:~/git/test$ git commit -m "stage test"
[master 1a465a0] stage test
 1 file changed, 1 insertion(+), 1 deletion(-)
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my fifth try.
xq@xq-VPCEG17YC:~/git/test$ git status
位於分支 master
尚未暫存以備提交的變更:
  (使用 "git add <檔案>..." 更新要提交的內容)
  (使用 "git checkout -- <檔案>..." 丟棄工作區的改動)

    修改:     hello.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
xq@xq-VPCEG17YC:~/git/test$ git diff HEAD -- hello.txt
diff --git a/hello.txt b/hello.txt
index fd3f316..3d7585b 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1 @@
-this is my fourth try.
+this is my fifth try.

檔案修改錯誤需要撤銷怎麼辦

  • 本地工作區撤銷
    1.檔案還在工作區可以手動修改檔案;
    2.git checkout – file也可以丟棄工作區的修改(命令中的–很重要,沒有–,就變成了“切換到另一個分支”的命令)

    一種是hello.txt自修改後還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;

    一種是hello.txt已經新增到暫存區後,又作了修改,現在,撤銷修改就回到新增到暫存區後的狀態。

    總之,就是讓這個檔案回到最近一次git commit或git add時的狀態。

  • 已經add到暫存區撤銷
    用命令git reset HEAD file可以把暫存區的修改撤銷掉(unstage),重新放回工作區

    git reset命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD時,表示最新的版本

  • 已經commit到版本庫撤銷
    參考《版本回退》小節
xq@xq-VPCEG17YC:~/git/test$ git checkout -- hello.txt
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my fourth try.
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my fifth try.
xq@xq-VPCEG17YC:~/git/test$ git add hello.txt 
xq@xq-VPCEG17YC:~/git/test$ vi hello.txt 
xq@xq-VPCEG17YC:~/git/test$ cat hello.txt 
this is my sixth try.
xq@xq-VPCEG17YC:~/git/test$ git reset HEAD hello.txt
重置後取消暫存的變更:
M   hello.txt

新增到遠端倉庫

Git是分散式版本控制系統,同一個Git倉庫,可以分佈到不同的機器上。別的機器可以“克隆”這個原始版本庫,而且每臺機器的版本庫其實都是一樣的,並沒有主次之分。
單機也是可以克隆多個版本庫,但是毫無意義。我們將GitHub作為伺服器的角色,提供7*24的服務,從GitHub倉庫克隆一份到自己的電腦上,並且各自把各自的提交推送到伺服器倉庫裡,也從伺服器倉庫中拉取別人的提交。

GitHub申請以及SSH祕鑰設定見上一章

我們可以把一個已有的本地倉庫與之關聯,然後,把本地倉庫的內容推送到GitHub倉庫。
在GitHub上新建一個test的版本庫
這裡寫圖片描述

現在,我們根據GitHub的提示,在本地的test倉庫下執行命令:

git remote add origin https://github.com/rickey17/test.git

請千萬注意,把上面的rickey17替換成你自己的GitHub賬戶名,否則,你在本地關聯的就是我的遠端庫,關聯沒有問題,但是你以後推送是推不上去的,因為你的SSH Key公鑰不在我的賬戶列表中。

新增後,遠端庫的名字就是origin,這是Git預設的叫法,也可以改成別的,但是origin這個名字一看就知道是遠端庫。

下一步,就可以把本地庫的所有內容推送到遠端庫上:

git push -u origin master

這樣你就可以在GitHub上看見你的檔案了。

把本地庫的內容推送到遠端,用git push命令,實際上是把當前分支master推送到遠端。

由於遠端庫是空的,我們第一次推送master分支時,加上了-u引數,Git不但會把本地的master分支內容推送的遠端新的master分支,還會把本地的master分支和遠端的master分支關聯起來,在以後的推送或者拉取時就可以簡化命令。

從現在起,只要本地作了提交,就可以通過命令:

git push origin master

把本地master分支的最新修改推送至GitHub,現在,你就擁有了真正的分散式版本庫!

從遠端倉庫克隆

xq@xq-VPCEG17YC:~/git/test$ git status
位於分支 master
您的分支與上游分支 'origin/master' 一致。
尚未暫存以備提交的變更:
  (使用 "git add <檔案>..." 更新要提交的內容)
  (使用 "git checkout -- <檔案>..." 丟棄工作區的改動)

    修改:     hello.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
xq@xq-VPCEG17YC:~/git/test$ git add hello.txt 
xq@xq-VPCEG17YC:~/git/test$ git commit -m "commit to GitHub"
[master 3742dca] commit to GitHub
 1 file changed, 1 insertion(+), 1 deletion(-)
xq@xq-VPCEG17YC:~/git/test$ git push origin master
物件計數中: 3, 完成.
寫入物件中: 100% (3/3), 272 bytes | 0 bytes/s, 完成.
Total 3 (delta 0), reused 0 (delta 0)
To git@github.com:rickey17/test.git
   1a465a0..3742dca  master -> master
xq@xq-VPCEG17YC:~/git/test$ git clone https://github.com/rickey17/test.git
正克隆到 'test'...
remote: Counting objects: 15, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 15 (delta 0), reused 15 (delta 0), pack-reused 0
展開物件中: 100% (15/15), 完成.
檢查連線... 完成。