Learn git the easy way- 一文入門 git 常用操作

Git 是一個開源的分佈式版本控制系統,用於敏捷高效地處理任何或小或大的項目。

Git 配置

Git 提供了 git config 命令,用來配置或讀取相應的工作環境變量。

這些變量可以存放在以下三個不同的地方:

配置個人用戶名和電子郵件地址,這是爲了在每次提交代碼時記錄提交者的信息:

git config --global user.name "runoob"
git config --global user.email test@runoob.com

Git 設置全局 socks 代理:

git config --global http.proxy 'socks5://用戶名:密碼@代理地址:端口'
git config --global https.proxy 'socks5://用戶名:密碼@代理地址:端口'

可以使用 git config --list 命令查看已有的配置信息。

Git 工作流程

a) 克隆倉庫

首先需要將遠程倉庫克隆到本地:

git clone https://github.com/username/repo.git
cd repo

b) 創建新分支

爲了避免直接在 main 或 master 分支上進行開發,通常會創建一個新的分支:

git checkout -b new-feature

c) 暫存文件

將修改過的文件添加到暫存區,以便進行下一步的提交操作:

# 添加特定文件的改動
git add filename
# 添加暫存區文件的改動
git add -u
# 添加當前目錄下的所有文件的改動到暫存區,但不包括全新的文件
git add .
# 添加所有已跟蹤文件的改動到暫存區,同時將新文件添加到暫存區
git add -A

d) 提交更改

將暫存區的更改提交到本地倉庫,並添加提交信息:

git commit -m "Add new feature"

e) 推送更改

在推送本地更改之前,最好從遠程倉庫拉取最新的更改,以避免衝突:

# 在主分支上工作
git pull origin main
# 在新的分支上工作
git pull origin new-feature

將本地的提交推送到遠程倉庫:

git push origin new-feature

f) 創建 Pull Request(PR)

在 GitHub 或其他託管平臺上創建 Pull Request,邀請團隊成員進行代碼審查。PR 合併後,你的更改就會合併到主分支。

在 PR 審覈通過併合並後,可以將遠程倉庫的主分支合併到本地分支:

git checkout main
git pull origin main
git merge new-feature

g) 刪除分支

如果不再需要新功能分支,可以將其刪除:

git branch -d new-feature

或者從遠程倉庫刪除分支:

git push origin --delete new-feature

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

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

a) 工作區(Working Directory)

工作區是本地計算機上的項目目錄,在這裏可以進行文件的創建、修改和刪除操作。工作區包含了當前項目的所有文件和子目錄。

b) 暫存區(Staging Area)

暫存區是一個臨時存儲區域,它包含了即將被提交到版本庫中的文件快照,在提交之前,你可以選擇性地將工作區中的修改添加到暫存區。常用命令:

git ls-files

查看暫存區的文件:

git ls-files
# 只列出已跟蹤的文件
git ls-files -t
# 只列出未跟蹤的文件
git ls-files -o
# 顯示文件的狀態信息,包括文件的模式和SHA-1哈希值
git ls-files -s

git add

添加文件到暫存區:

# 添加特定文件的改動
git add filename
# 添加暫存區文件的改動
git add -u
# 添加當前目錄下的所有文件的改動到暫存區,但不包括全新的文件
git add .
# 添加所有已跟蹤文件的改動到暫存區,同時將新文件添加到暫存區
git add -A

git mv

用於在 Git 倉庫中重命名或移動文件。該命令會創建一個新的文件(目錄),並將其添加到暫存區,同時刪除舊的文件(目錄)。使用 git mv 可以保持文件的歷史記錄,即使文件名變了,也能追蹤到之前的歷史記錄。

git mv [file] [newfile]

git rm

從暫存區中刪除文件:

# 從工作區和暫存區刪除文件,本地文件被刪除
git rm -r filename
# 從暫存區刪除文件,本地文件還在,只是不希望該文件被版本控制
git rm -r --cached filename

git status

查看上次提交之後是否有對文件進行再次修改:

$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   README
    new file:   hello.php

git status 命令會顯示以下信息:

c) 版本庫(Repository)

版本庫包含項目的所有版本歷史記錄。

每次提交都會在版本庫中創建一個新的快照,這些快照是不可變的,確保了項目的完整歷史記錄。常用命令:

git commit

將暫存區的更改提交到本地版本庫:

git commit -m "Commit message"

git log

查看提交歷史:

git log
# 以簡潔的一行格式顯示提交信息
git log --oneline
# 顯示最近的5次提交
git log -n 5
# 顯示自指定日期之後的提交
git log --since="2024-01-01"
# 顯示指定日期之前的提交
git log --until="2024-07-01"
# 只顯示某個作者的提交
git log --author="Author Name"
# 不顯示合併提交
git log --no-merges
# 顯示簡略統計信息,包括修改的文件和行數
git log --stat

git reset

回退版本,可以指定退回某一次提交的版本。它可以通過改變 HEAD 指針來修改歷史提交記錄,影響暫存區和工作區。命令語法格式如下:

git reset [--soft | --mixed | --hard] [HEAD]
# 回退上上上一個版本
git reset --hard HEAD~3
# 回退到某個版本
git reset --hard bae128
# 將本地的狀態回退到和遠程的一樣
git reset --hard origin/main

HEAD 說明:

可以使用 ~ 數字表示:

git diff

用於比較不同狀態下的文件差異。

(1) 查看工作區和上次提交的差異:

git diff

這將顯示自上次提交以來對所有文件所做的更改。

(2) 查看暫存區和上次提交的差異:

git diff --staged

這將顯示已經添加到暫存區但尚未提交的更改。

(3) 查看特定提交 / 分支與當前工作區的差異:

git diff commitA
git diff branch

(4) 只顯示發生變化的文件名:

git diff --name-only

(5) 顯示文件名和變化狀態:

git diff --name-status

(6) 顯示簡要的統計信息:

git diff --stat

該命令會列出所有修改過的文件及其狀態(如新增、修改、刪除),但不會顯示具體的改動內容。

(7) 比較兩次提交的差異:

git diff commitA commitB

這裏 commitA 和 commitB 可以是提交哈希值、分支名或標籤名等。

git diff的輸出可以被重定向到其他工具進行進一步處理。

git diff commitA commitB > diff_result.txt

可以將差異結果輸出到一個文件,然後使用文本編輯器來查看。或者使用專門的差異分析工具,如 meld、kdiff3 等,結合 git difftool 命令來進行更直觀的圖形化差異比較。

(8) 比較兩個分支的差異:

git diff branch1 branch2

這裏將顯示 branch1 和 branch2 分支之間的差異。

(9) 比較兩個提交之間特定文件的差異:

git diff commitA commitB path/to/file

這將顯示在提交 commitA 和 commitB 之間,文件 path/to/file 的差異。

(10) 比較兩個分支之間特定目錄的差異:

git diff branch1 branch2 path/to/directory/

這將顯示分支 branch1 和 branch2 之間,目錄 path/to/directory/ 的差異。

Git 遠程操作

常用命令:

git remote

用於管理 Git 倉庫中的遠程倉庫。常見用法:

git fetch

用於從遠程倉庫獲取最新的歷史記錄和數據,但不會自動合併或更改項目當前的工作目錄和暫存區。這個命令將遠程倉庫的更新信息下載存儲在本地倉庫的 .git 目錄中,但不會影響工作目錄或暫存區。

# 獲取所有遠程分支的更新
git fetch
# 獲取特定遠程倉庫的所有分支的更新
git fetch <remote>
# 獲取特定遠程倉庫的特定分支的更新
git fetch <remote> <branch>

在獲取遠程分支數據後,可以執行以下命令合併到當前分支:

git merge <remote>/<branch>

如果想從遠程倉庫的特定分支拉取代碼,並更新至本地分支:

git fetch origin main:brantest

這個命令會將遠程倉庫的 main 分支的內容更新到本地的 brantest 分支。如果本地還沒有 brantest 分支,Git 會自動創建一個新的分支。

git pull

用於從遠程倉庫獲取代碼併合併到本地分支。這個命令其實是 git fetch 和 git merge 的簡寫,先從遠程倉庫獲取最新的提交記錄,然後將這些提交記錄合併到項目當前的分支中。

git pull <remote> <branch>
git pull origin main

這會拉取遠程 main 分支的最新更改併合併到當前分支中。

git pull origin main:brantest

這會拉取遠程 main 分支的最新更改,併合併到本地的 brantest 分支,如果本地不存在 brantest 分支,Git 會自動創建它。

git push

用於將本地倉庫的更改(commit)上傳到遠程倉庫。

git push <remote> <local_branch>:<remote_branch>

將本地的 main 分支推送到 origin 遠程存儲庫的 main 分支:

git push origin main

相等於:

git push origin main:main

如果本地版本與遠程版本有差異,但又要強制推送可以使用 --force 參數:

git push --force origin main

刪除遠程分支可以使用 --delete 參數,以下命令表示刪除遠程的 main 分支:

git push --delete origin main

推送所有本地分支到遠程倉庫,可以使用 --all 選項:

git push --all origin

如果想要推送當前分支到遠程倉庫並跟蹤它,可以使用 -u 選項:

git push -u origin main

這樣會將本地的 main 分支與遠程倉庫 origin 關聯,之後只需 git push。

git submodule

用於管理包含其他 Git 倉庫的項目。這個命令對於大型項目或需要將外部庫集成到項目中的情況非常有用。通過使用子模塊,你可以將外部庫作爲你的項目的一部分來管理,而不必將其直接合併到主倉庫中。

a) 初始化子模塊
git submodule init

這個命令會初始化配置文件中的所有子模塊。它會根據 .gitmodules 文件中的信息設置子模塊的 URL 和路徑,但不會下載子模塊的內容。

常見用法:在克隆了一個包含子模塊的倉庫後,運行子命令來初始化子模塊。

git clone <repo-url>
cd <repo-dir>
git submodule init
git submodule update
b) 更新子模塊
git submodule update

這個命令會從子模塊的遠程倉庫中拉取子模塊的內容,並將其更新到 .gitmodules 文件中指定的提交。

c) 添加子模塊
git submodule add <repo-url> [<path>]

這個命令會將指定的 Git 倉庫作爲子模塊添加到當前倉庫中。

<repo-url> 是子模塊的倉庫地址,<path> 是子模塊在主倉庫中的路徑(可選,如果不指定,默認使用子模塊倉庫的名稱作爲路徑)。

常見用法:將外部庫作爲子模塊添加到項目中。

git submodule add https://github.com/example/libfoo.git libfoo
d) 移除子模塊
git submodule deinit <path>
git rm <path>

常見用法:從主倉庫中移除一個子模塊。

git submodule deinit libfoo
git rm libfoo
rm -rf .git/modules/libfoo
e) 列出子模塊
git submodule

列出當前倉庫中的所有子模塊,以及它們的提交哈希和路徑。

f) 更新所有子模塊
git submodule update --recursive --remote

Git 分支管理

Git 分支管理是 Git 強大功能之一,能夠讓多個開發人員並行工作,開發新功能、修復 bug 或進行實驗,而不會影響主代碼庫。

a) 創建分支

創建新分支並切換到該分支:

git checkout -b <branchname>

切換分支:

git checkout <branchname>

當切換分支的時候,Git 會用該分支最後提交的快照替換項目工作目錄的內容,所以多個分支不需要多個目錄。

在切換分支前,最好確保當前分支所做的修改已經提交,否則會報錯。

但我們有時可能會遇到這樣的情況,正在 dev 分支開發新功能,做到一半時團隊成員反饋一個 bug,需要馬上解決,但新功能又暫時不想提交,這時就可以使用 git stash 命令將 dev 分支的工作區和暫存區保存起來,然後切換到另一個分支去修改 bug,修改完提交後再切回 dev 分支,使用 git stash pop 來恢復之前的進度繼續開發新功能。下面是使用 git stash 時要遵循的順序:

b) 查看分支

查看所有本地分支:

git branch

查看所有遠程分支:

git branch -r

查看所有本地和遠程分支:

git branch -a

c) 合併分支

將其他分支合併到當前分支:

git merge <branchname>

例如,切換到 main 分支併合並 deploy 分支:

git checkout main
git merge deploy

當合並過程中出現衝突時,Git 會標記衝突文件,需要手動解決衝突。

打開衝突文件,按照標記解決衝突。完成後:

git add <conflict-file>
git commit

d) 刪除分支

刪除本地分支:

git branch -d <branchname>

強制刪除未合併的分支:

git branch -D <branchname>

刪除遠程分支:

git push origin --delete <branchname>

e) 拉取分支

拉取遠程分支 origin/main 的最新提交併合併至本地當前分支:

git pull origin main

本地提交前報錯

有時候在本地提交代碼前想使用 git pull 拉取遠程倉庫更新時會報錯:

error: Your local changes to the following files would be overwritten by merge:
    README.md
Please commit your changes or stash them before you merge.
Aborting

說明本地當前修改的代碼和別人修改提交到遠程倉庫的代碼有衝突,可以使用
git stash 來解決:

(1) 存儲本地工作區修改的代碼:

git stash

(2) 拉取遠程分支代碼:

git pull origin main
 * branch            main       -> FETCH_HEAD
Updating e021282..42c2045
Fast-forward
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

這時已經不報錯了,能正常 pull 下來。

(3) 把本地存儲的代碼釋放出來:

git stash pop
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md

發現在 README.md 文件裏會有衝突,我們手動解決下衝突,就可以正常添加和提交了。

本地提交後報錯

有時候在本地工作區修改代碼提交後,拉取遠程分支最新提交時會報錯:

git pull origin main
......
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint: 
hint:   git config pull.rebase false  # merge (the default strategy)
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint: 
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.

這說明本地分支和遠程分支的提交歷史發生了分叉(Divergent Branches),即雙方都有對方沒有的新提交(Commit)。Git 無法自動決定如何合併兩者的差異,需要用戶明確指定合併策略。

可以通過生成一個新的合併提交(Merge Commit)來整合本地和遠程的提交歷史:

git pull --no-rebase origin main

若存在代碼合併衝突,手動修改衝突文件後進行提交即可。

或者通過配置設置全局默認行爲(合併提交):

git config --global pull.rebase false
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/lwvPTHxWSfs9XsTSaFT64Q