Learn git the easy way- 一文入門 git 常用操作
Git 是一個開源的分佈式版本控制系統,用於敏捷高效地處理任何或小或大的項目。
Git 配置
Git 提供了 git config
命令,用來配置或讀取相應的工作環境變量。
這些變量可以存放在以下三個不同的地方:
-
•
/etc/gitconfig
文件:系統中對所有用戶都普遍適用的配置。若使用git config
時用--system
選項,讀寫的就是這個文件。 -
•
~/.gitconfig
文件:用戶目錄下的配置文件,只適用於該用戶。若使用git config
時用--global
選項,讀寫的就是這個文件。 -
•
.git/config
文件:這裏的配置僅僅針對當前項目有效。每一個級別的配置都會覆蓋上層的相同配置,所以.git/config
裏的配置會覆蓋/etc/gitconfig
中的同名變量。
配置個人用戶名和電子郵件地址,這是爲了在每次提交代碼時記錄提交者的信息:
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 工作區、暫存區和版本庫概念:
-
• 工作區: 就是你在電腦裏能看到的目錄。
-
• 暫存區: 英文叫 stage 或 index。一般存放在 .git 目錄下的 index 文件(.git/index)中,所以我們把暫存區有時也叫作索引(index)。
-
• 版本庫: 工作區有一個隱藏目錄 .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 命令會顯示以下信息:
-
• 當前分支的名稱。
-
• 未提交的修改:顯示已暫存但未使用
git commit
提交的文件列表。 -
• 未暫存的修改:顯示已修改但尚未使用
git add
添加到暫存區的文件列表。 -
• 未跟蹤的文件:顯示尚未納入版本控制的新文件列表。
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]
-
•
--soft
:僅重置 HEAD 指針,保留暫存區和工作區的更改。適用於需要保留修改但重新提交的情況。 -
•
--mixed
:默認選項,重置 HEAD 指針,將暫存區的內容恢復到指定提交狀態,但保留工作區的更改。適用於撤銷暫存操作但保留工作區更改的情況。 -
•
--hard
:重置 HEAD 指針,暫存區和工作區丟棄所有未提交的更改。適用於確定不再需要本地更改的情況。
# 回退上上上一個版本
git reset --hard HEAD~3
# 回退到某個版本
git reset --hard bae128
# 將本地的狀態回退到和遠程的一樣
git reset --hard origin/main
HEAD 說明:
-
• HEAD 表示當前版本
-
• HEAD^ 上一個版本
-
• HEAD^^ 上上一個版本
-
• HEAD^^^ 上上上一個版本
-
• 以此類推 ...
可以使用 ~ 數字表示:
-
• HEAD~0 表示當前版本
-
• HEAD~1 上一個版本
-
• HEAD~2 上上一個版本
-
• HEAD~3 上上上一個版本
-
• 以此類推 ...
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 remote
:列出當前倉庫中已配置的遠程倉庫。 -
•
git remote -v
:列出當前倉庫中已配置的遠程倉庫,並顯示它們的 URL。 -
•
git remote add <remote_name> <remote_url>
:添加一個新的遠程倉庫。指定遠程倉庫的名稱和 URL,將其添加到當前倉庫中。 -
•
git remote rename <old_name> <new_name>
:將已配置的遠程倉庫重命名。 -
•
git remote remove <remote_name>
:從當前倉庫中刪除指定的遠程倉庫。 -
•
git remote set-url <remote_name> <new_url>
:修改指定遠程倉庫的 URL。 -
•
git remote show <remote_name>
:顯示指定遠程倉庫的詳細信息,包括 URL 和跟蹤分支。
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>
-
•
remote
是遠程存儲庫的名稱,默認爲origin
。 -
•
branch
是遠程分支的名稱,默認爲main
或master
。
git pull origin main
這會拉取遠程 main
分支的最新更改併合併到當前分支中。
git pull origin main:brantest
這會拉取遠程 main
分支的最新更改,併合併到本地的 brantest
分支,如果本地不存在 brantest
分支,Git 會自動創建它。
git push
用於將本地倉庫的更改(commit)上傳到遠程倉庫。
git push <remote> <local_branch>:<remote_branch>
-
•
remote
是遠程存儲庫的名稱,默認爲origin
。 -
•
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 <path>
:將子模塊從.git/config
文件中移除,並刪除子模塊目錄中的文件。 -
•
git rm <path>
:將子模塊的引用從主倉庫中刪除,並提交更改。
常見用法:從主倉庫中移除一個子模塊。
git submodule deinit libfoo
git rm libfoo
rm -rf .git/modules/libfoo
e) 列出子模塊
git submodule
列出當前倉庫中的所有子模塊,以及它們的提交哈希和路徑。
f) 更新所有子模塊
git submodule update --recursive --remote
-
•
--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
時要遵循的順序:
-
• 將修改保存到分支 A 工作區
-
• 運行
git stash
-
• 簽出分支 B
-
• 修正 B 分支的 bug
-
• 提交併推送 (可選) 至遠程
-
• 切回分支 A
-
• 運行
git stash pop
來恢復工作區暫存的改動
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