初識Git 基本的使用操作

拜水:問道發表於2020-10-19

介紹

  • Git 是一個開源的分散式版本控制系統,用於敏捷高效地處理任何或小或大的專案。
  • Git 是 Linus Torvalds 為了幫助管理 Linux 核心開發而開發的一個開放原始碼的版本控制軟體。
  • Git 與常用的版本控制工具 CVS, Subversion 等不同,它採用了分散式版本庫的方式,不必伺服器端軟體支援。

基本操作

完成安裝之後,就可以使用命令列的 git 工具(已經自帶了 ssh 客戶端)了,另外還有一個圖形介面的 Git 專案管理工具。在開始選單裡找到"Git"->“Git Bash”,會彈出 Git 命令視窗,你可以在該視窗進行 Git 操作。
在這裡插入圖片描述
Git 提供了一個叫做 git config 的工具,專門用來配置或讀取相應的工作環境變數。這些環境變數,決定了 Git 在各個環節的具體工作方式和行為。這些變數可以存放在以下三個不同的地方:

  • /etc/gitconfig 檔案:系統中對所有使用者都普遍適用的配置。若使用 git config 時用 --system 選項,讀寫的就是這個檔案。
  • ~/.gitconfig 檔案:使用者目錄下的配置檔案只適用於該使用者。若使用 git config 時用 --global 選項,讀寫的就是這個檔案。
  • 當前專案的 Git 目錄中的配置檔案(也就是工作目錄中的 .git/config 檔案):這裡的配置僅僅針對當前專案有效。每一個級別的配置都會覆蓋上層的相同配置,所以 .git/config 裡的配置會覆蓋 /etc/gitconfig 中的同名變數。
    在 Windows 系統上,Git 會找尋使用者主目錄下的 .gitconfig 檔案。主目錄即 $HOME 變數指定的目錄,一般都是 C:\Documents and Settings$USER。此外,Git 還會嘗試找尋 /etc/gitconfig 檔案,只不過看當初 Git 裝在什麼目錄,就以此作為根目錄來定位。

使用者配置

配置個人的使用者名稱稱和電子郵件地址:
在這裡插入圖片描述
如果用了 --global 選項,那麼更改的配置檔案就是位於你使用者主目錄下的那個,以後你所有的專案都會預設使用這裡配置的使用者資訊。如果要在某個特定的專案中使用其他名字或者電郵,只要去掉 --global 選項重新配置即可,新的設定儲存在當前專案的 .git/config 檔案裡。

文字編輯器

設定Git預設使用的文字編輯器, 一般可能會是 Vi 或者 Vim。如果你有其他偏好,比如 Emacs 的話,可以重新設定:
在這裡插入圖片描述

差異分析工具

還有一個比較常用的是,在解決合併衝突時使用哪種差異分析工具。比如要改用 vimdiff 的話:
在這裡插入圖片描述
Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合併工具的輸出資訊。當然,你也可以指定使用自己開發的工具。

檢視配置資訊

要檢查已有的配置資訊,可以使用 git config --list 命令:
在這裡插入圖片描述
有時候會看到重複的變數名,那就說明它們來自不同的配置檔案(比如 /etc/gitconfig 和 ~/.gitconfig),不過最終 Git 實際採用的是最後一個。這些配置我們也可以在 ~/.gitconfig 或 /etc/gitconfig 看到,顯示內容如下所示:
在這裡插入圖片描述

Git工作區、暫存區和版本庫

我們先來理解下 Git 工作區、暫存區和版本庫概念:

  • 工作區:就是你在電腦裡能看到的目錄。
  • 暫存區:英文叫 stage 或 index。一般存放在 .git 目錄下的 index 檔案(.git/index)中,所以我們把暫存區有時也叫作索引(index)。
  • 版本庫:工作區有一個隱藏目錄 .git,這個不算工作區,而是 Git 的版本庫。
    下面這個圖展示了工作區、版本庫中的暫存區和版本庫之間的關係:
    在這裡插入圖片描述

圖中左側為工作區,右側為版本庫。在版本庫中標記為 “index” 的區域是暫存區(stage/index),標記為 “master” 的是 master 分支所代表的目錄樹。
圖中我們可以看出此時 “HEAD” 實際是指向 master 分支的一個"遊標"。所以圖示的命令中出現 HEAD 的地方可以用 master 來替換。
圖中的 objects 標識的區域為 Git 的物件庫,實際位於 “.git/objects” 目錄下,裡面包含了建立的各種物件及內容。
當對工作區修改(或新增)的檔案執行 git add 命令時,暫存區的目錄樹被更新,同時工作區修改(或新增)的檔案內容被寫入到物件庫中的一個新的物件中,而該物件的ID被記錄在暫存區的檔案索引中。
當執行提交操作(git commit)時,暫存區的目錄樹寫到版本庫(物件庫)中,master 分支會做相應的更新。即 master 指向的目錄樹就是提交時暫存區的目錄樹。
當執行 git reset HEAD 命令時,暫存區的目錄樹會被重寫,被 master 分支指向的目錄樹所替換,但是工作區不受影響。
當執行 git rm --cached 命令時,會直接從暫存區刪除檔案,工作區則不做出改變。
當執行 git checkout . 或者 git checkout – 命令時,會用暫存區全部或指定的檔案替換工作區的檔案。這個操作很危險,會清除工作區中未新增到暫存區的改動。
當執行 git checkout HEAD . 或者 git checkout HEAD 命令時,會用 HEAD 指向的 master 分支中的全部或者部分檔案替換暫存區和以及工作區中的檔案。這個命令也是極具危險性的,因為不但會清除工作區中未提交的改動,也會清除暫存區中未提交的改動。

建立倉庫

Git 使用 git init 命令來初始化一個 Git 倉庫,Git 的很多命令都需要在 Git 的倉庫中執行,所以 git init 是使用 Git 的第一個命令。在執行完成 git init 命令後,Git 倉庫會生成一個 .git 目錄,該目錄包含了資源的所有後設資料,其他的專案目錄保持不變。
使用當前目錄作為Git倉庫,我們只需使它初始化。git init該命令執行完後會在當前目錄生成一個 .git 目錄。使用我們指定目錄作為Git倉庫,命令為git init newrepo。
在這裡插入圖片描述
初始化後,會在 newrepo 目錄下會出現一個名為 .git 的目錄,所有 Git 需要的資料和資源都存放在這個目錄中。如果當前目錄下有幾個檔案想要納入版本控制,需要先用 git add 命令告訴 Git 開始對這些檔案進行跟蹤,然後提交。
我們使用 git clone 從現有 Git 倉庫中拷貝專案(類似 svn checkout)。克隆倉庫的命令格式為:我們使用 git clone 從現有 Git 倉庫中拷貝專案(類似 svn checkout)。克隆倉庫的命令格式為:git clone 如果我們需要克隆到指定的目錄,可以使用以下命令格式:git clone 比如,要克隆 Ruby 語言的 Git 程式碼倉庫 Grit,可以用下面的命令:
$ git clone git://github.com/schacon/grit.git
執行該命令後,會在當前目錄下建立一個名為grit的目錄,其中包含一個 .git 的目錄,用於儲存下載下來的所有版本記錄。如果要自己定義要新建的專案目錄名稱,可以在上面的命令末尾指定新的名字:
$ git clone git://github.com/schacon/grit.git mygrit

基本操作

Git 的工作就是建立和儲存你專案的快照及與之後的快照進行對比。本章將對有關建立與提交你的專案快照的命令作介紹。Git 常用的是以下 6 個命令:git clone、git push、git add 、git commit、git checkout、git pull。
在這裡插入圖片描述
git init - 初始化倉庫。
git add . - 新增檔案到暫存區。
git commit - 將暫存區內容新增到倉庫中。
在這裡插入圖片描述

提交與修改

Git 的工作就是建立和儲存你的專案的快照及與之後的快照進行對比。下表列出了有關建立與提交你的專案的快照的命令:

  • git add 新增檔案到倉庫
  • git status 檢視倉庫當前的狀態,顯示有變更的檔案。
  • git diff 比較檔案的不同,即暫存區和工作區的差異。
  • git commit 提交暫存區到本地倉庫。
  • git reset 回退版本。
  • git rm 刪除工作區檔案。
  • git mv 移動或重新命名工作區檔案。

提交日誌

  • git log 檢視歷史提交記錄
  • git blame 以列表形式檢視指定檔案的歷史修改記錄

遠端操作

  • git remote 遠端倉庫操作
  • git fetch 從遠端獲取程式碼庫
  • git pull 下載遠端程式碼併合並
  • git push 上傳遠端程式碼併合並

分支管理

列出分支

幾乎每一種版本控制系統都以某種形式支援分支。使用分支意味著你可以從開發主線上分離開來,然後在不影響主線的同時繼續工作。有人把 Git 的分支模型稱為必殺技特性,而正是因為它,將 Git 從版本控制系統家族裡區分出來。建立分支命令:
git branch (branchname)
切換分支命令:
git checkout (branchname)
當你切換分支的時候,Git 會用該分支的最後提交的快照替換你的工作目錄的內容, 所以多個分支不需要多個目錄。合併分支命令:
git merge
你可以多次合併到統一分支, 也可以選擇在合併之後直接刪除被併入的分支。
開始前我們先建立一個測試目錄:
$ mkdir gitdemo
$ cd gitdemo/
$ git init
Initialized empty Git repository…
$ touch README
$ git add README
$ git commit -m ‘第一次版本提交’
[master (root-commit) 3b58100] 第一次版本提交
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README
沒有引數時,git branch 會列出你在本地的分支。
在這裡插入圖片描述
此例的意思就是,我們有一個叫做 master 的分支,並且該分支是當前分支。當你執行 git init 的時候,預設情況下 Git 就會為你建立 master 分支。如果我們要手動建立一個分支。執行 git branch (branchname) 即可。
現在我們可以看到,有了一個新分支 testing。當你以此方式在上次提交更新之後建立了新分支,如果後來又有更新提交, 然後又切換到了 testing 分支,Git 將還原你的工作目錄到你建立分支時候的樣子。
接下來我們將演示如何切換分支,我們用 git checkout (branch) 切換到我們要修改的分支。
$ ls
README
$ echo ‘runoob.com’ > test.txt
$ git add .
$ git commit -m ‘add test.txt’
[master 3e92c19] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
$ ls
README test.txt
$ git checkout testing
Switched to branch ‘testing’
$ ls
README
當我們切換到 testing 分支的時候,我們新增的新檔案 test.txt 被移除了。切換回 master 分支的時候,它們有重新出現了。
$ git checkout master
Switched to branch ‘master’
$ ls
README test.txt
我們也可以使用 git checkout -b (branchname) 命令來建立新分支並立即切換到該分支下,從而在該分支中操作。
$ git checkout -b newtest
Switched to a new branch ‘newtest’
$ git rm test.txt
rm ‘test.txt’
$ ls
README
$ touch runoob.php
$ git add .
$ git commit -am ‘removed test.txt、add runoob.php’
[newtest c1501a2] removed test.txt、add runoob.php
2 files changed, 1 deletion(-)
create mode 100644 runoob.php
delete mode 100644 test.txt
$ ls
README runoob.php
$ git checkout master
Switched to branch ‘master’
$ ls
README test.txt
如你所見,我們建立了一個分支,在該分支的上移除了一些檔案 test.txt,並新增了 runoob.php 檔案,然後切換回我們的主分支,刪除的 test.txt 檔案又回來了,且新增加的 runoob.php 不存在主分支中。使用分支將工作切分開來,從而讓我們能夠在不同開發環境中做事,並來回切換。

刪除分支

刪除分支命令:
git branch -d (branchname)
例如我們要刪除 testing 分支:
$ git branch
*master
testing
$ git branch -d testing
Deleted branch testing (was 85fc7e7).
$ git branch
*master

合併分支

一旦某分支有了獨立內容,你終究會希望將它合併回到你的主分支。 你可以使用以下命令將任何分支合併到當前分支中去:
git merge
$ git branch
*master
newtest
$ ls
README test.txt
$ git merge newtest
Updating 3e92c19…c1501a2
Fast-forward
runoob.php | 0
test.txt | 1 -
2 files changed, 1 deletion(-)
create mode 100644 runoob.php
delete mode 100644 test.txt
$ ls
README runoob.php
以上例項中我們將 newtest 分支合併到主分支去,test.txt 檔案被刪除。合併完後就可以刪除分支:
$ git branch -d newtest
Deleted branch newtest (was c1501a2).
刪除後, 就只剩下 master 分支了:
$ git branch
*master

合併衝突

合併並不僅僅是簡單的檔案新增、移除的操作,Git 也會合並修改。
$ git branch
*master
$ cat runoob.php
首先,我們建立一個叫做 change_site 的分支,切換過去,我們將 runoob.php 內容改為:

<?php echo 'runoob'; ?>

建立 change_site 分支:
$ git checkout -b change_site
Switched to a new branch ‘change_site’
$ vim runoob.php
$ head -3 runoob.php

<?php echo 'runoob'; ?>

$ git commit -am ‘changed the runoob.php’
[change_site 7774248] changed the runoob.php
1 file changed, 3 insertions(+)
將修改的內容提交到 change_site 分支中。 現在,假如切換回 master 分支我們可以看內容恢復到我們修改前的(空檔案,沒有程式碼),我們再次修改 runoob.php 檔案。
$ git checkout master
Switched to branch ‘master’
$ cat runoob.php
$ vim runoob.php # 修改內容如下
$ cat runoob.php

<?php echo 1; ?>

$ git diff
diff --git a/runoob.php b/runoob.php
index e69de29…ac60739 100644
— a/runoob.php
+++ b/runoob.php
@@ -0,0 +1,3 @@
+<?php
+echo 1;
+?>
$ git commit -am ‘修改程式碼’
[master c68142b] 修改程式碼
1 file changed, 3 insertions(+)
現在這些改變已經記錄到我的 “master” 分支了。接下來我們將 “change_site” 分支合併過來。
$ git merge change_site
Auto-merging runoob.php
CONFLICT (content): Merge conflict in runoob.php
Automatic merge failed; fix conflicts and then commit the result.
$ cat runoob.php # 代開檔案,看到衝突內容

<?php <<<<<<< HEAD echo 1; echo 'runoob'; >>>>>>> change_site ?>

我們將前一個分支合併到 master 分支,一個合併衝突就出現了,接下來我們需要手動去修改它。
$ vim runoob.php
$ cat runoob.php

<?php echo 1; echo 'runoob'; ?>

$ git diff
diff --cc runoob.php
index ac60739,b63d7d7…0000000
— a/runoob.php
+++ b/runoob.php
@@@ -1,3 -1,3 +1,4 @@@

<?php +echo 1; + echo 'runoob'; ?>

在 Git 中,我們可以用 git add 要告訴 Git 檔案衝突已經解決
$ git status -s
UU runoob.php
$ git add runoob.php
$ git status -s
M runoob.php
$ git commit
[master 88afe0e] Merge branch ‘change_site’
現在我們成功解決了合併中的衝突,並提交了結果。

以上便是Git的基本是使用操作,有關Git深入學習的知識我後期會做一個專門的介紹。

相關文章