git 基礎知識
Git 的工作流程涉及多個“空間”或區域,這些空間用於管理文件的狀態和版本。以下是 Git 中主要的空間及其作用:
1. 工作區(Working Directory / Working Tree)
- 定義:你當前在項目中編輯的文件所在的目錄。
-
特點:
- 包含實際的文件內容。
- 是你進行開發、修改代碼的地方。
-
狀態:
- 文件可以是
unmodified(未修改)、modified(已修改)或untracked(未跟蹤)。
- 文件可以是
2. 暫存區 / 緩存區(Staging Area / Index)
- 定義:一個臨時存儲區域,用於準備下一次提交的內容。
-
作用:
- 使用
git add <file>將修改從工作區添加到暫存區。 - 提交時 (
git commit),Git 會將暫存區中的內容打包成一個新的提交對象。
- 使用
-
特點:
- 允許你選擇性地提交部分更改。
- 是 Git 版本控制的核心機制之一。
3. 本地倉庫(Local Repository)
- 定義:
.git目錄,包含所有 Git 提交歷史、對象、引用等。 -
特點:
- 所有提交 (
commit) 都保存在這裏。 - 是分佈式版本控制系統的核心,支持離線操作。
- 所有提交 (
- 查看提交歷史:
git log
4. 遠程倉庫(Remote Repository)
- 定義:託管在遠程服務器上的 Git 倉庫,如 GitHub、GitLab 等。
-
常見操作:
git push:將本地提交推送到遠程倉庫。git pull:拉取遠程更新併合併到本地分支。git fetch:獲取遠程提交但不自動合併。
5. Git 對象數據庫(Object Database)
- 定義:位於
.git/objects目錄,存儲所有 Git 對象(blob、tree、commit、tag)。 -
類型:
blob:表示文件內容。tree:表示目錄結構。commit:表示一次提交記錄。tag:表示標籤(輕量標籤或附註標籤)。
6. HEAD 指針
- 定義:指向當前所在分支或提交的指針。
-
狀態:
- 正常情況下指向一個分支(如
refs/heads/main)。 - 如果處於分離 HEAD 狀態,則直接指向某個具體的提交。
- 正常情況下指向一個分支(如
常見命令與空間關係
| 命令 | 影響的空間 |
|---|---|
git add . |
將工作區的所有修改添加到暫存區 |
git commit |
將暫存區的內容提交到本地倉庫 |
git status |
查看工作區和暫存區的狀態差異 |
git reset |
將暫存區或本地倉庫的內容重置回退 |
git checkout -- <file> |
丟棄工作區的修改,恢復為暫存區或本地倉庫中的版本 |
git stash |
將工作區和暫存區的修改臨時保存 |
示例流程圖(簡化)
工作區 (Working Directory)
↓ git add
暫存區 (Staging Area)
↓ git commit
本地倉庫 (.git)
↓ git push
遠程倉庫 (Remote Repository)
通過理解這些空間的概念,可以更好地掌握 Git 的版本控制機制,並更有效地使用 git diff、git add -p、git reset 等高級功能。
commit 提交
最佳實踐:commit early,commit often
git提交的兩步流程
## 工作區-->暫存區
git status
git add <file_name>
git add -A
git add . 當前目錄及其子目錄
## 提交文件+提交消息
git commit -m 'comment'
branch 分支
lines of development
分支是指向提交(commit)的可移動指針
HEAD 指向分支的指針
減少對git checkout的使用
Tracked file 1:unmodified 2:modified 通過git status 查看狀態
- git branch 查看分支
- git branch <branch_name> 創建分支
- git switch <branch_name> 切換分支
- git switch -c <branch_name> 創建並切換
merge 合併
merge
fast-forward merge(快進合併)
A --- B --- C (main)
\
D --- E (feature-branch)
如果目標分支(如 main)是當前分支的直接祖先(即沒有分叉),Git 會直接將指針向前移動(快進),不會創建新的合併提交。
git switch main
git merge feture-branch 後
A --- B --- C --- D --- E (main)
可作用git merge --no-ff feature-branch 禁用快進合併(no-ff強制創建,即使可以快進),保留完整的路徑
A --- B --- C ------------ F (main)
\ /
D --- E ---- (feature-branch)
three-way merge(三方合併)
A --- B --- C (main)
\
D --- E (feature)
A 是 main 和 feature 的共同祖先(base)。
B 和 C 是 main 的改動(ours)。
D 和 E 是 feature 的改動(theirs)。
git merge 生成一個新的 合併提交(F),
git switch main
git merge feature-branch /git merge --no--ff feature-branch
A --- B --- C ------------ F (main)
\ /
D --- E -- ----------- (feature)
pull
git pull 與 git fetch 選擇問題
1:若本地分枝與遠程分支沒有分叉,git pull進行快速合併
2:否則分兩步走 ,先git fetch,然後視情況做--no-rebase or rebase
變基
rebase,變基,可以直接理解為改變基底。feature分支是基於master分支的B拉出來的分支,feature的基底是B。而master在B之後有新的提交,就相當於此時要用master上新的提交來作為feature分支的新基底。實際操作為把B之後feature的提交先暫存下來,然後刪掉原來這些提交,再找到master的最新提交位置,把存下來的提交再接上去(接上去是逐個和新基底處理衝突的過程),如此feature分支的基底就相當於變成了M而不是原來的B了。(注意,如果master上在B以後沒有新提交,那麼就還是用原來的B作為基,rebase操作相當於無效,此時和git merge就基本沒區別了,差異只在於git merge會多一條記錄Merge操作的提交記錄)
如下圖所示,rebase會產生新的提交。會得新生成提交hash值