git 基本使用手冊

yongxue發表於2020-07-06

初步設定

安裝好 Git 後,第一步是設定 Git 的使用者名稱和郵箱,如果沒有設定使用者名稱和郵箱是無法提交版本的,如下設定:

# 設定使用者名稱
$ git config --global user.name "username"

# 設定使用者郵箱
$ git config --global user.email "useremail@163.com"

然後是 其他設定

初始化專案

在安裝並配置好 Git 的使用者名稱和郵箱後,我們可以開始初始化專案的版本庫,初始化專案版本庫只需在專案目錄下執行如下命令:

# 該命令為初始化版本庫
$ git init

Laravel

執行 git init 後會在該專案目錄下生成 .git 的隱藏目錄, 該目錄用於存放版本管理資訊。

跟蹤檔案

初始化好專案後或修改檔案後,就可以將檔案進行跟蹤提交到快取區,以備下次提交到版本庫中,如下操作將檔案或目錄提交到快取區中。

# 提交檔案
$ git add filename

# 提交目錄
$ git add dirname/

# 或提交全部
$ git add .

Laravel

將檔案提交到快取區後,下一步就是將快取區的內容提交到版本庫中。

提交到版本庫

當完成某個功能並使用 git add 將檔案新增到快取區後,接下來就是把這個功能提交到版本庫中了, 使用如下命令:

# 將前面跟蹤到快取區的檔案提交到版本庫
$ git commit -m '功能描述'

Laravel

這樣就完成了將程式碼跟蹤到版本庫中的操作了,然後就可以將原生程式碼 推送到遠端倉庫 分享給其他人了。

修改上一個版本資訊

有時候我們提交完了才發現漏掉了幾個檔案沒有新增,或者提交資訊寫錯了。此時,可以執行帶有 --amend 選項的提交命令嘗試重新提交:

$ git commit --amend

這個命令會將快取區中的檔案提交。如果自上次提交以來你還未做任何修改(例如,在上次提交後馬上執行了此命令),那麼快照會保持不變,所修改的只是提交資訊。
文字編輯器啟動後,可以看到之前的提交資訊。編輯後儲存會覆蓋原來的提交資訊。

如果提交後發現忘記了快取某些需要的修改,可以像下面這樣操作:

# 提交版本
$ git commit -m 'initial commit'
# 重新新增檔案
$ git add forgotten_file
# 修改上一個版本並重新提交
$ git commit --amend
# 注意如果上一個版本已推送到遠端倉庫,禁止這樣操作,否則你會被打殘的。

檢視檔案狀態

當你需要提交版本庫時,應當先使用 git status 確認當前檔案的跟蹤狀態。
如下命令:

# 該命令檢視檔案跟蹤的狀態, 哪些檔案已跟蹤哪些檔案未跟蹤。
$ git status

注意:當將檔案提交到版本庫中後,使用 git status 是檢視不到已提交到版本庫中的資訊的,當快取區資訊為空時表示已沒有修改檔案可提交了。

忽略檔案

一般總會有些檔案無需納入 Git 的管理,也不希望它們總出現在未跟蹤檔案列表。通常都是些自動生成的檔案,比如日誌檔案,或者編譯過程中建立的臨時檔案等。在這種情況下,可以建立一個名為 .gitignore 的檔案,列出要忽略的檔案模式。

示例:

$ cat .gitignore
TEST.md
*.log

第一行告訴 Git 忽略 TEST.md 檔案。第二行告訴 Git 忽略所有以 .log 結尾的檔案。要養成一開始就設定好 .gitignore 檔案的習慣,以免將來誤提交這類無用的檔案。

檔案 .gitignore 的格式規範如下:

  • 所有空行或者以 # 開頭的行都會被 Git 忽略。
  • 可以使用標準的 glob 模式匹配。
  • 匹配模式可以以/開頭防止遞迴。
  • 匹配模式可以以/結尾指定目錄。
  • 要忽略指定模式以外的檔案或目錄,可以在模式前加上驚歎號!取反。

所謂的 glob 模式是指 shell 所使用的簡化了的正規表示式。 星號 * 匹配零個或多個任意字元; [abc] 匹配任何一個列在方括號中的字元( 這個例子要麼匹配一個a , 要麼匹配一個b, 要麼匹配一個c); 問號 ? 只匹配一個任意字元; 如果在方括號中使用短劃線分隔兩個字元, 表示所有在這兩個字元範圍內的都可以匹配( 比如 [0-9] 表示匹配所有 0 到 9 的數字 )。 使用兩個星號 * 表示匹配任意中間目錄, 比如 a/**/z 可以匹配 a/z, a/b/z 或 a/b/c/z 等。

GitHub 有一個十分詳細的針對數十種專案及語言的 .gitignore 檔案列表,可以在 GitHub 找到它.

檢視歷史提交記錄

需要檢視歷史的提交列表資訊使用 git log 命令。

# 檢視提交的版本列表
$ git log

可以使用 -p 顯示每次提交的內容差異,也可以加上 -2 來僅顯示最近兩次提交:

$ git log -p -2

如果想看到每次提交的簡略的統計資訊,可以使用 --stat 選項:

$ git log --stat

或者檢視某個檔案的提交列表:

$ git log filename

工作區/快取區

工作區(Working Directory)
工作區就是你修改檔案下的目錄就是一個工作區, 工作區有一個隱藏目錄 .git, 這個不算工作區, 而是 git 的版本庫。
Git 的版本庫裡存了很多東西,其中最重要的就是稱為 stage(或者叫index)的快取區,還有 Git 為我們自動建立的第一個分支 master,以及指向 master 的一個指標叫 HEAD。

檔案往 git 版本庫提交的時候,分兩步執行。

  • 第一步 git add 把檔案提交到快取區.
  • 第二步 git commit -m '****' 把快取區內容提交到版本庫分支。

如下圖提交流程:

Laravel
Laravel

注意: 修改的檔案只有 git add 提交到快取區後才能被 git commit -m '***' 提交到版本庫裡, 否則工作區的內容是提交不到版本庫內。

檢視已快取/未快取資訊

有時候我們需要檢視修改了檔案的哪些內容,可以使用以下命令檢視。

$ git diff filename

如果要檢視快取區內與上次提交之間的差別呢?這就需要使用到 --cached 引數:

$ git diff --cached

注意:當將檔案提交到版本庫中後,使用 git diffgit diff --cached 也不會有任何輸出.

還可以使用 git diff 來檢視兩個分支的差異。
命令如下:

# 該命令是分支和分支的比較
$ git diff <分支名稱> <分支名稱>

如果需要檢視當前工作區和最新的版本的區別,則可以使用如下命令:

# 檢視當前 filename 檔案在工作區與最新版本的一個區別
$ git diff HEAD -- filename

撤銷修改

當我們在專案中新增了功能修改而後又不需要此次修改的時候,我們就需要將當前的修改全部撤銷或撤銷部分檔案修改。

撤銷快取區的修改

當修改已提交到快取區後需要使用 git reset HEAD filename 命令將檔案撤回到工作區:

# 將快取區的 file.txt 檔案撤回到工作區中
$ git reset HEAD file.txt

將修改撤回到工作區中後,到這裡還沒有將修改的內容徹底撤回。只是在提交版本庫的時候不會將快取區撤回的內容提交到版本庫中,但是修改內容依然還在,只是在工作區中而已。

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

撤銷工作區修改

下面就是撤回在工作區中的修改內容。
當修改後的內容在工作區中不需要的時候,使用 git checkout -- filename 命令將工作區中的修改檔案內容撤銷掉。

丟棄工作區的修改:

# 丟棄 file.txt 檔案中的修改
$ git checkout -- file.txt

git checkout -- file.txt 意思就是把 file.txt 檔案在工作區的修改全部撤銷, 這裡有兩種情況:

  • 一種是 file.txt 自修改後還沒有被放到快取區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
  • 一種是 file.txt 已經新增到快取區後,又作了修改,現在,撤銷修改就回到新增到快取區後的狀態。總之,就是讓這個檔案回到最近一次 git commitgit add 時的狀態。

移除檔案

從版本庫中移除檔案

要從 Git 中移除某個檔案, 就必須要從已跟蹤檔案清單中移除(確切地說, 是從快取區域移除)然後提交。
可以用 git rm 命令完成此項工作, 並連帶從工作目錄中刪除指定的檔案, 這樣以後就不會出現在未跟蹤檔案清單中了。

如果只是簡單地從工作目錄中手工刪除檔案,執行 git status 時就會在 “Changes not staged for commit” 部分(也就是 未快取清單)看到:

$ rm TESTS.md

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
        deleted:    TESTS.md
no changes added to commit (use "git add" and/or "git commit -a")

然後再執行 git rm 記錄此次移除檔案的操作:

$ git rm TESTS.md
rm 'TESTS.md'

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        deleted:    TESTS.md

下一次提交時, 該檔案就不再納入版本管理了。如果刪除之前修改過並且已經放到快取區域的話,則必須要用強制刪除選項 -f (譯註:即 force 的首字母)。這是一種安全特性, 用於防止誤刪還沒有新增到快照的資料, 這樣的資料不能被 Git 恢復。

還有一種情況是, 把檔案從 Git 倉庫中刪除(亦即從快取區域移除), 但需要保留在當前工作目錄中。為達到這一目的, 使用 --cached 選項:

# 只是從倉庫記錄中刪除
$ git rm --cached README.md

git rm 命令後面可以列出檔案或者目錄的名字,也可以使用 glob 模式。比如說:

$ git rm log/\*.log

版本回退

在我們的專案中,當釋出一個新版本後發現有嚴重的BUG時,我們就需要將專案回退到穩定的舊版本中,或者是我們提交的新版本功能已經不需要了,這時我們也需要將版本回退掉。
接下來開始講解如何回退版本。

回退到指定版本

首先要講的是最簡單的一個回退到上一個版本命令 git reset --hard HEAD^,該命令只是單純的將版本回退到上一個版本中。

# 回退到上一個版本中
$ git reset --hard HEAD^

如果需要回退到再上一個版本中只需在 HEAD 的後面再加一個 ^ 符號即可,如下。

# 回退到上上一個版本中
$ git reset --hard HEAD^^

需要回退到上幾個版本就可以在 HEAD 後面加幾個 ^

如果要回退到 10 或 100 個以上版本中該如何呢?我們可以寫成這樣 HEAD~100

# 回退到前100個版本中
$ git reset --hard HEAD~100

或者使用 commit id 回退到指定的版本中。

$ git reset --hard 1094a

回退檔案到指定版本

當在專案開發中提交一個版本後發現該版本中有幾個檔案的修改已經不需要了,我們可以使用 git checkout <commit id> filename 命令來單獨來回退指定檔案的版本,而不影響整個提交的版本。

# 回退 index.txt 檔案至 2dc9de54f352e754 版本
$ git checkout 2dc9de54f352e754 index.txt

# 回退後需要提交新版本
$ git commit -m "回退檔案"

也可回退整個目錄,只需將 index.txt 檔名改成目錄名即可。

回退遠端倉庫的版本

刪除最後一次提交:

# 回退一次提交
$ git revert HEAD
# 推送分支
$ git push origin master

使用 revert 回退還可以使用以下方式:

# 回退到上上個版本
$ git revert HEAD^

# 回退到3個版本前
$ git revert HEAD~3

# 回退到指定的 commit id
$ git revert 0818bad

回退版本強制推送:

# 回退版本
$ git reset --hard HEAD^

# 強制推送 master 分支
$ git push origin master -f

不推薦使用該方式,強制推送會導致專案的其他人合併混亂。

遠端倉庫管理

克隆遠端倉庫

在一個專案需要多人協助開發時就需要用到遠端倉庫,將遠端倉庫的程式碼下載到本地可以使用 git clone 命令。

$ git clone https://github.com/xueyong-q/docker-database.git

克隆時還可以指定在本地克隆後的專案名稱。

$ git clone https://github.com/xueyong-q/docker-database.git MyProject

克隆後會將程式碼儲存在 MyProject 目錄下,也可以將 MyProject 換成 . 表示克隆到當前目錄下。

關聯遠端倉庫

有時候我們會先在本地新建好專案,然後再新建倉庫,這樣的話就需要將本地的專案關聯到新倉庫中:

$ git remote add origin https://github.com/xueyong-q/docker-database.git

關聯好遠端倉庫後,下一步就是把本地倉庫內容推送到遠端倉庫:

# 第一次推送遠端倉庫時需要加上 -u 引數
$ git push -u origin master

把本地庫的內容推送到遠端,用 git push 命令,實際上是把當前分支 master 推送到遠端。
第一次推送 master 分支時,加上 -u 引數,Git 不但會把本地的 master 分支內容推送的遠端新的 master 分支,還會把本地的 master 分支和遠端的 master 分支關聯起來,在以後的推送或者拉取時就可以簡化命令。

現在只要本地做了提交, 下次就可以使用如下命令推送到遠端倉庫了:

$ git push origin master

當遠端倉庫有新的修改時可以使用 git pull 命令同步併合並下來。
當多人協作時,提交到遠端倉庫前,最好使用 git pull 合併遠端倉庫的修改再提交到遠端倉庫。
當多人協作時可能會遇到提交衝突,使用 git pull 合併遠端倉庫可以在本地解決衝突再提交到遠端倉庫。

更換遠端倉庫

當我們需要將舊專案更換到一個新的倉庫中時,就只需將本地專案的遠端倉庫地址更換為新倉庫地址即可。

# 更換遠端地址
$ git remote set-url origin https://github.com/xueyong-q/docker-nginx-php.git

# 然後推送分支
$ git push -u origin master

分支管理

Git 的分支模型這一特性,使的 Git 能從眾多版本控制系統中脫穎而出。Git 處理分支的方式是難以置信的輕量,建立分支幾乎能在瞬間完成,不同分支之間切換也是一樣便捷的, Git 鼓勵在工作流中頻繁的使用分支與合併。

檢視專案分支列表命令:

$ git branch

分支前面有一個 * 號表示當前所在的分支。

建立分支

簡單建立分支命令 git branch <分支名稱>

# 新建 develop 分支
$ git branch develop

建立並切換分支命令 git checkout -b <分支名稱>

# 建立並切換到 develop 分支
$ git checkout -b develop

合併分支

簡單的合併一個分支,如這裡有兩個分支 master、develop,當前所在分支為 master 需要合併 develop 分支的內容:

# 將 develop 分支的內容合併到 master 分支上
$ git merge develop

解決合併衝突

當兩個分支都有不一樣的提交時合併分支就有可能會產生衝突。當產生衝突後可使用 git status 檢視衝突的檔案,在檔案內, Git 用 <<<<<<<,=======,>>>>>>> 標記出不同分支的內容需要我們手動去修改,然後儲存提交。

刪除分支

刪除一個分支使用如下命令。

# 刪除 develop 分支
$ git branch -d develop

如果一個分支有修改內容還未提交或有內容未合併,則無法直接刪除,如果確定需要刪除則使用 -D 引數來強制刪除。

# 強制刪除 develop 分支
$ git branch -D develop

關聯遠端分支

為了方便推送程式碼和拉取程式碼,可以將本地的分支與遠端倉庫的分支進行關聯。關聯遠端分支命令 git branch --set-upstream-to=origin/<遠端分支名稱> <本地分支名稱>

# 將本地的 develop 分支與遠端的 develop 分支關聯
$ git branch --set-upstream-to=origin/develop develop

分支管理策略

  • master 分支應該是非常穩定的,也就是僅用來發布穩定的版本,不能在上面進行工作。
  • develop 分支用於新功能測試分支,將新開發的功能或修復的 BUG 合併到該分支進行測試,待穩定後合併到 master 分支中。
  • mydev 你的開發分支,就是你在本地幹活的分支,分支名稱可以自定義。

BUG分支

bug 修復時的臨時分支。
當需要修復一個 bug, 而當前工作分支還沒提交時, 可以使用 stash 功能把當前工作區 “儲藏” 起來,等以後恢復後繼續工作。

# 暫存當前的修改
$ git stash

然後建立一個分支來修復 bug。
修復 bug 後就可以恢復剛剛暫存的修改繼續工作。

# 檢視剛剛儲存的工作區
$ git stash list

# 恢復,但是恢復後,stash 內容並不刪除
$ git stash apply

# 恢復的同時把 stash 內容也刪了
$ git stash pop

# 可以多次 stash,恢復的時候,先用 git stash list 檢視,然後恢復指定的 stash,用命令
# 恢復 stash@{0} 條目
$ git stash apply stash@{0}

顯示儲存項中記錄的更改內容

# 檢視 stash@{1} 條目內的修改內容
$ git stash show -p stash@{1}

從儲存條目列表中刪除一個儲存條目:

# 刪除 stash@{1} 條目
$ git stash drop stash@{1}

清除所有儲藏條目:

# 注意這會清除所有的條目
$ git stash clear

Feature分支

新增一個新功能,最好新建一個 feature 分支,在上面開發。
在開發完成併合並後,即可將該分支刪除。

標籤管理

為專案打標籤:

# 新增簡單標籤 v1.0
$ git tag v1.0

# 新增附註標籤
$ git tag -a v1.0.0 -m '標籤說明'

# 檢視所有標籤
$ git tag

# 檢視v1.0標籤詳細資訊
$ git show v1.0

一般我們打標籤時應該選擇使用附註標籤。

子模組

當一個專案需要分成多個倉庫來管理時,就需要使用 Git 的子模組來管理更方便。

新增子模組

可以透過在 git submodule add 命令後面加上想要跟蹤的專案的相對或絕對 URL 來新增新的子模組。

# 在當前目錄下新增一個名為 DbConnector 的子模組
$ git submodule add https://github.com/chaconinc/DbConnector

# 新增後就可以初始化配置並將程式碼拉取下來
$ git submodule init

# 抓取並檢出子模組
$ git submodule update

這樣子模組就新增完成。

也可將子模組新增到其他目錄下:

# 在當前的 base 目錄下新增一個名為 DbConnector 的子模組
$ git submodule add https://github.com/chaconinc/DbConnector base/DbConnector

如果這時執行 git status,你會注意到幾件事。

$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
  new file: .gitmodules
  new file: DbConnector

新增子模組後新增了 .gitmodulesDbConnector 這兩個檔案,然後將它們提交至版本庫中即可。

同步子模組

在克隆一個包含子模組的新專案後,子模組中是空的需要我們去手動拉取。
必須執行兩個命令:git submodule init 用來初始化本地配置檔案,而 git submodule update 則從該專案中抓取所有資料並檢出父專案中列出的合適的提交。

# 初始化本地配置,如已初始化則可以跳過
$ git submodule init

# 抓取並檢出子模組
$ git submodule update

目錄轉換為子模組

在需要將目錄轉換為子模組時需要注意,一定先從 git 倉庫中刪除該檔案或目錄:

# 先從倉庫刪除該目錄
$ git rm -r DbConnector

# 然後在當前目錄下新增一個名為 DbConnector 的子模組
$ git submodule add https://github.com/chaconinc/DbConnector

其他設定

生成SSH金鑰

本地生成 SSH 金鑰

$ ssh-keygen -t rsa

執行以上命令會在使用者 home 目錄下的 .ssh 目錄中生成 id_rsaid_rsa.pub 檔案, 其中 id_rsa 為私鑰 id_rsa.pub 為公鑰, 把 d_rsa.pub 的內容新增到倉庫平臺的 SSH 證照配置中。 這樣推送程式碼至遠端倉庫就不需要使用密碼.

CRLF換行符

windows 系統下請設定:

# 提交時轉換成 LF,簽出時轉換為 CRLF
$ git config --global core.autocrlf true

Linux & Mac 系統下配置:

# 表示檢出時不轉換,提交時轉換為 LF
$ git config --global core.autocrlf input

檢視版本狀態中文無法顯示

在 Windows 平臺下執行 git status 中文轉義致亂碼的解決方案。
core.quotepath 設為 false 的話,就不會對 0x80 以上的字元進行 quote。中文顯示正常。

$ git config --global core.quotepath false

版本庫許可權跟蹤設定

當開啟版本庫許可權跟蹤時,修改了檔案的許可權 Git 會對其進行跟蹤。
當關閉版本庫許可權跟蹤時,只修改了檔案的許可權 Git 就不會對其進行跟蹤。

# 當前版本庫設定
$ git config core.filemode false

# 全域性設定
$ git config --global core.filemode false

Git快取GitHub登入憑據

在終端下使用 HTTPS 克隆的 GitHub 倉庫推送程式碼時經常會彈出要我們登入,下面我們可以設定憑據快取來減少登入次數。

設定 Git 快取憑據:

$ git config --global credential.helper cache

也可以設定快取憑據時間。

$ git config --global credential.helper 'cache --timeout=3600' # 這裡快取一小時

學習資料

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章