Git Note
- Git文檔
- Git練習網站
在 Git Base中複製粘貼:
- 複製: 使用 Ctrl + Insert 快捷鍵可以複製選中的文本。
- 粘貼: 使用 Shift + Insert 快捷鍵可以粘貼剪貼板中的內容。
一. 配置
1.1 查看Git所有的配置以及它們所在的文件
$ git config --list --show-origin
1.2 設置你的用户名和郵件地址
$ git config --global user.name "NobodyCares"
$ git config --global user.email 3226234796@qq.com
使用了
--global選項,那麼該命令只需要運行一次,因為之後無論你在該系統上做任何事情, Git 都會使用那些信息
1.3 通過輸入 git config <key>: 來檢查 Git 的某一項配置:
$ git config user.name
NobodyCares
1.4 獲取幫助
$ git help <Key>
$ git <Key> --help
// 例如獲取git config 命令手冊
$ git help config
// 獲取簡明參考幫助
$ git config -h
二. Git基礎
2.1 初始化倉庫
# 在項目中,打開Git Base
$ git init
該命令將創建一個名為
.git的子目錄,這個子目錄含有你初始化的 Git 倉庫中所有的必須文件,這些文件是 Git 倉庫的骨幹。 但是,在這個時候,我們僅僅是做了一個初始化的操作,你的項目裏的文件還沒有被跟蹤。
2.2 克隆倉庫git clone
例如克隆 https://github.com/H-TXSL/Airplane_Games.git
$ git clone https://github.com/H-TXSL/Airplane_Games.git
這會在當前目錄下創建一個名為 “Airplane_Games” 的目錄,並在這個目錄下初始化一個
.git文件夾, 從遠程倉庫拉取下所有數據放入.git文件夾,然後從中讀取最新版本的文件的拷貝。
Git 支持多種數據傳輸協議。
當你克隆一個遠程倉庫時,Git 通常會自動將該遠程倉庫命名為 origin
2.3 忽略文件
- .gitignore 模板集合
- 創建一個名為
.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等
# .gitignore 文件示例
# 忽略所有的 .a 文件
*.a
# 但跟蹤所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略當前目錄下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目錄下名為 build 的文件夾
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目錄及其所有子目錄下的 .pdf 文件
doc/**/*.pdf
2.4 記錄每次更新到倉庫
- 工作目錄下的每一個文件都不外乎這兩種狀態:已跟蹤 或 未跟蹤
Untracked files下為未跟蹤
Changes not staged for commit下,説明已跟蹤文件的內容發生了變化,但還沒有放到暫存區。
Changes to be committed下為處於暫存區
2.4.1 檢查當前文件狀態
$ git status
簡潔輸出
$ git status -s
# 新添加的未跟蹤文件前面有 `??` 標記
# 新添加到暫存區中的文件前面有 `A` 標記
# 修改過的文件前面有 `M` 標記
# 左欄指明瞭暫存區的狀態,右欄指明瞭工作區的狀態
2.4.2 跟蹤新文件或暫存已修改的文件
$ git add <file>
2.4.3 查看已暫存和未暫存的修改
git diff 本身只顯示尚未暫存的改動,而不是自上次提交以來所做的所有改動
- 比較工作區文件與暫存區文件的差異
$ git diff
# 此命令比較的是工作目錄中當前文件和暫存區域快照之間的差異
- 比較暫存區文件與本地Git倉庫的差異
$ git diff --staged ( `--staged` 和 `--cached` 是同義詞)
# 此命令將比對已暫存文件與最後一次提交的文件差異
2.4.4 提交更新
$ git commit -m "要輸入的提交説明"
- 跳過使用暫存區域
給
git commit加上-a選項,Git 就會自動把所有已經跟蹤過的文件暫存起來一併提交,從而跳過git add步驟
$ git commit -a -m "要輸入的提交説明"
2.4.5 移除文件
- 移除工作區文件
# 直接移除
$ rm <file>
# # 工作目錄中刪除文件,同時把刪除動作記錄到暫存區
$ git rm <file>
git rm命令後面可以列出文件或者目錄的名字,也可以使用glob模式
-
移除暫存區文件
# 從暫存區移除文件, 但不刪除工作區文件 $ git rm --cached <files> -
移除Git倉庫文件
$ git rm <file> $ git commit -m "移除信息説明"2.4.6 移動或重命名文件
git mv命令會自動跟蹤文件# 將 name_1 重命名為 name_2 $ git mv <name_1> <name_2>運行
git mv就相當於運行了下面三條命令:
$ mv README.md README
$ git rm README.md
$ git add README
2.5 查看提交歷史
$ git log命令git log的常用選項- 限制
git log輸出的選項
不傳入任何參數的默認情況下,
git log會按時間先後順序列出所有的提交,最近的更新排在最上面。
2.5.1 常用選項
2.5.1.1 顯示每次提交引入的差異
$ git log -p -number
# `-number` 選項來只顯示最近的number次提交
2.5.1.2 快速把握每次提交對文件的修改概況
$ git log --stat
# 修改增刪彙總
2.5.1.3 使用不同於默認格式的方式展示提交歷史
$ git log --pretty=?
# ?為子選項:
# oneline 會將每個提交放在一行顯示
# short 作者和提交信息
# full 作者,提交者,提交信息
# fuller 作者,提交者,提交作者和提交者的時區信息, 提交信息
2.5.1.4 定製記錄的顯示格式
-
git log --pretty=format常用的選項# 例如僅輸出: 作者名 - 作者的電子郵件地址 $ git log --pretty=format:"%an - %ae" -
隱藏合併提交
按照你代碼倉庫的工作流程,記錄中可能有為數不少的合併提交,它們所包含的信息通常並不多。 為了避免顯示的合併提交弄亂歷史記錄,可以為
log加上--no-merges選項。
2.5.2 查看各個分支當前所指的對象
# 提供這一功能的參數是 --decorate
$ git log --oneline --decorate
- 項目分叉歷史
$ git log --oneline --decorate --graph --all
# 輸出你的提交歷史、各個分支的指向以及項目的分支分叉情況。
2.6 撤銷操作
2.6.1 修改提交信息
$ git commit --amend
# 進入文本編譯器中修改提交信息
例如 Vim: 按
i鍵進入插入模式,對提交信息進行修改。修改完成後,按Esc鍵退出插入模式,然後輸入:wq並回車,這會保存修改並退出 Vim
2.6.2 添加遺漏文件到暫存區的信息到最近一次提交
# 先運行 git add <file>
# 再運行 git commit --amend
例如Vim: 這裏不用修改提交信息內容,直接按
Esc鍵退出插入模式(如果處於插入模式的話),然後輸入:wq並回車
2.6.3 取消暫存文件
$ git reset HEAD <file>
2.6.4 撤銷對文件的修改
將文件還原成上次提交時的樣子,Git 會用最近提交的版本覆蓋掉它
$ git checkout -- <file>
2.7 遠程倉庫的使用
2.7.1 添加遠程倉庫
$ git remote add origin <url>
# 起別名
$ git remote add <shortname> <url>
# 可以在命令行中使用字符串 <shortname> 來代替整個 URL
# -u:該選項是 --set - upstream 的縮寫。它的作用是在推送本地分支到遠程倉庫的同時,設置本地分支跟蹤遠程分支。
$ git push -u origin "master"
# 更改遠程倉庫 origin 的 URL 地址
$ git remote set-url origin <url>
2.7.2 查看遠程倉庫
# 顯示需要讀寫遠程倉庫使用的 Git 保存的簡寫與其對應的 URL
$ git remote -v
# 列出遠程倉庫的 URL 與跟蹤分支的信息
$ git remote show <remote>
2.7.3 從遠程倉庫中抓取與拉取
- 抓取
# 這個命令會訪問遠程倉庫,從中拉取所有你還沒有的數據
$ git fetch <remote>
注意 git fetch 命令只會將數據下載到你的本地倉庫——它並不會自動合併或修改你當前的工作
當抓取到新的遠程跟蹤分支時,本地不會自動生成一份可編輯的副本(拷貝),只有一個不可以修改的 <remote>/<branch> 指針
可以運行 git merge <remote>/<branch> 將這些工作合併到當前所在的分支。
- 拉取
# 這個命令會自動將從遠程倉庫抓取的分支合併到當前所在的分支
$ git pull <remote> <branch>
如果想要在自己的 branch 分支上工作,可以將其建立在遠程跟蹤分支之上
$ git checkout -b <branch> <remote>/<branch>
# 這會給你一個用於工作的本地分支,並且起點位於遠程分支<remote>/<branch>
# 這會使創建的分支為跟蹤分支
# 跟蹤分支是與遠程分支有直接關係的本地分支。
# 如果在一個跟蹤分支上輸入 git pull,Git 能自動地識別去哪個服務器上抓取、合併到哪個分支。
# 跟蹤分支的一個重要特性是,它們會自動與遠程分支保持同步。
2.7.4 推送到遠程倉庫
$ git push <remote> <branch>
# 例如
$ git push origin master
# 推送所有分支
$ git push <remote> --all
# 推送一個分支到遠程倉庫,並重命名遠程分支為 <branch_new_name>
# 如果遠程倉庫不存在 <branch_new_name> 分支,會創建一個新分支;若已存在同名分支,則會用本地分支的提交更新遠程分支。
$ git push <remote> <branch>:<branch_new_name>
只有當你有所克隆服務器的寫入權限,並且之前沒有人推送過時,這條命令才能生效
2.7.5 遠程倉庫重命名與移除
# 重命名
$ git remote rename <old_name> <new_name>
# 移除別名
$ git remote remove <name>
或
$ git remote rm <name>
一旦你使用這種方式刪除了一個遠程倉庫,那麼所有和這個遠程倉庫相關的遠程跟蹤分支以及配置信息也會一起被刪除
2.8 打標籤
Git 可以給倉庫歷史中的某一個提交打上標籤,以示重要。
標籤在 Git 中是全局的,並不屬於特定的某個分支。
Git 支持兩種標籤:輕量標籤(lightweight)與 附註標籤(annotated)
輕量標籤很像一個不會改變的分支——它只是某個特定提交的引用。
附註標籤是存儲在 Git 數據庫中的一個完整對象, 它們是可以被校驗的,其中包含打標籤者的名字、電子郵件地址、日期時間, 此外還有一個標籤信息,並且可以使用 GNU Privacy Guard (GPG)簽名並驗證。
默認給當前 HEAD 所指向的提交打標籤,也就是最近的一次提交
2.8.1 創建標籤
- 附註標籤
$ git tag -a <tag-name> -m "標籤信息"
- 輕量標籤
創建輕量標籤,不需要使用 -a、-s 或 -m 選項,只需要提供標籤名字
$ git tag <tag-name>
2.8.2 列出標籤
$ git tag
# (可帶上可選的 -l 選項 --list)
如果你提供了一個匹配標籤名的通配模式,那麼 -l 或 --list 就是強制使用的
$ git tag -l "v1.8.5*"
# 列出所有以 v1.8.5 開頭的標籤
2.8.3 查看標籤信息
$ git show <tag-name>
2.8.4 後期打標籤
可以對過去的提交打標籤
# # <commit-id> 可以是提交的 SHA-1 校驗和的前幾位字符
# 打輕量標籤
$ git tag <tag-name> <commit-id>
# 打附註標籤
# 直接添加標籤信息
$ git tag -a <tag-name> -m "標籤信息" <commit-id>
# 在文本編輯器中編輯標籤信息
$ git tag -a <tag-name> <commit-id>
- 例如在 Vim 中
按
insert鍵進入插入模式,填寫標籤信息。完成後,按Esc鍵退出插入模式,然後輸入:wq並回車,這會保存修改並退出 Vim
2.8.5 共享標籤
默認情況下,git push 命令並不會傳送標籤到遠程倉庫服務器上。
創建完標籤後你必須顯式地推送標籤到共享服務器上。
$ git push <remote> <tag-name>
# 推送所有標籤到遠程倉庫
$ git push <remote> --tags
使用 git push
--tags 推送標籤並不會區分輕量標籤和附註標籤, 沒有簡單的選項能夠讓你只選擇推送一種標籤。
2.8.6 刪除標籤
- 刪除本地標籤
$ git tag -d <tag-name>
- 刪除遠程標籤
$ git push <remote> :refs/tags/<ta-name>
# 上面這種操作的含義是,將冒號前面的空值推送到遠程標籤名,從而高效地刪除它。
# 更直觀的刪除
$ git push <remote> --delete <tag-name>
2.8.7 檢出標籤
查看某個標籤所指向的文件版本
這會使你的倉庫處於分離頭指針 detached HEAD的狀態
這種狀態下,你對文件所做的修改和提交不會影響到任何分支,因為 HEAD 沒有與分支關聯。
$ git checkout <tag-name>
- 撤銷分離頭指針狀態
$ git switch -
- 創建新分支保留提交
如果你想基於當前處於 “detached HEAD” 狀態下的提交創建一個新分支來保留所做的更改
# -c 選項的作用是創建並切換到一個新分支
$ git switch -c <new-branch-name>
三. 分支
Git保存數據的方式
Git 保存的不是文件的變化或者差異,而是一系列不同時刻的快照。
- 提交對象
進行提交操作時,Git 會保存一個提交對象(commit object)。
提交對象包含了作者的姓名和郵箱、提交時輸入的信息以及指向它的父對象的指針和一個指向暫存內容快照的指針。
首次提交產生的提交對象沒有父對象,普通提交操作產生的提交對象有一個父對象, 而由多個分支合併產生的提交對象有多個父對象。
使用 git commit 進行提交操作時:
- Git 會先計算每一個子目錄的校驗和
- 然後將 Git 倉庫中這些校驗和保存為樹對象
- 隨後,Git 便會創建一個提交對象, 它除了包含上面提到的那些信息外,還包含指向這個樹對象的指針。
Git 倉庫中有五個對象:三個 blob 對象(保存着文件快照)、一個 樹 對象 (記錄着目錄結構和 blob 對象索引)以及一個 提交 對象(包含着指向前述樹對象的指針和所有提交信息)。
3.0 HEAD指針和^,~引用
分離頭指針
分離頭指針是一種特殊的狀態, 它表示當前 Git 倉庫處於一個沒有任何分支的狀態。
# 例如:
$ git checkout <commit-id>
# 這會使你的倉庫處於分離頭指針狀態。
# 此時,你對文件所做的修改和提交不會影響到任何分支,因為 HEAD 沒有與分支關聯。
$ git switch -
# 這會將 HEAD 指針切換回上一次所在的分支,撤銷進入 “分離頭指針” 狀態的操作,恢復到之前的工作狀態。
相對引用
單一父提交的引用為上一次的提交
多父提交的引用,第一個父提交是當前分支在合併前的狀態,第二個父提交是被合併分支的狀態 。
- ^引用
# 例如: 現在提交記錄為上圖
# 現在: HEAD指向master,master指向C3
$ git checkout master^
# 這會將 HEAD 指針切換到 master 分支的上一個提交,即 c1。
$ git merge main
# 這會將當前分支(master)與 main 分支合併。
# 合併完成後,HEAD 指針會指向最新的提交,即 c4。
# 如下圖所示:
$ git checkout master^
# 這會將 HEAD 指針切換到 master 分支合併前的狀態提交,即 c3。
# 如下圖所示:
$ git checkout master
# 這會將 HEAD 指針切換回 master 分支,恢復到之前的工作狀態。
$ git checkout master^2
# 這會將 HEAD 指針切換到被合併分支的狀態提交,即 c2。
# 也就是之前master分支合併的main分支指向的c2提交
# 如下圖所示:
- ~引用
相對引用的簡化形式,可以使用 ~ 符號來代替 ^ 符號
# 例如分支提交為上圖
# 現在: HEAD指向main,main指向C3
$ git checkout main~number
# number 為 2 時
$ git checkout main~2
# 這會將 HEAD 指針切換到 main 分支的上兩個提交,即 c1。
# number 為 3 時
$ git checkout main~3
# 這會將 HEAD 指針切換到 main 分支的上三個提交,即 c0。
3.1 分支簡介
- Git 的分支,其實本質上僅僅是指向提交對象的可變指針。
- Git 的默認分支名字是 master, 是因為 git init 命令默認創建它
3.2 分支操作
3.2.1 分支創建
- 只創建分支不切換到新分支
$ git branch <new-branch-name>
# 這會創建一個指向當前提交對象的指針
只有當你在該分支提交後,Git 才會把這個指針移動到新的提交對象上。
- 創建新分支並切換到新分支
$ git switch -c <new-branch-name>
------------------------------------
$ git checkout -b <new-branch-name>
# 上面的命令等價於
$ git branch <new-branch-name>
$ git checkout <new-branch-name>
3.2.2 分支切換
$ git checkout <branch-name>
# 這樣 HEAD 就指向了該分支
分支切換會改變你工作目錄中的文件
請牢記:當你切換分支的時候,Git 會重置你的工作目錄,使其看起來像回到了你在那個分支上最後一次提交的樣子。
- 強制分支指向指定提交
$ git branch -f <branch-name> <commit-id>
# 這會將分支 <branch-name> 強制指向 <commit-id> 所指向的提交對象。
3.2.3 列出分支
# 列出所有本地分支
$ git branch
# 查看每一個分支最後一次提交
$ git branch -v
# 列出所有遠程分支
$ git branch -r
# 列出所有遠程分支的最後一次提交
$ git branch -rv
# 列出所有本地分支和遠程分支
$ git branch -a
# 列出所有本地分支和遠程分支,以及它們的最後一次提交
$ git branch -av
# 列出哪些分支已經合併到當前分支
$ git branch --merged
# 列出哪些分支還沒有合併到當前分支
$ git branch --no-merged
# 還可以加附加一個參數<branch-name>,列出哪些分支還沒有合併到<branch-name>分支或者哪些分支已經合併到<branch-name>分支
$ git branch --merged <branch-name>
$ git branch --no-merged <branch-name>
3.2.4 分支合併
- 合併指定分支到當前分支
$ git merge <branch-name>
- 合併指定分支到指定分支
# 將 <source-branch> 分支合併到 <target-branch> 分支
$ git merge <source-branch> <target-branch>
若合併過程中沒有衝突,Git 會自動將分支指針向前移動, 並將其指向被合併分支所指向的提交對象。
若合併過程中發生了衝突,Git 會停止合併過程,並要求你解決衝突。
為了解決衝突,你必須選擇使用由 ======= 分割的兩部分中的一個,或者你也可以自行合併這些內容。
解決衝突後,你需要使用 git add 命令將衝突文件添加到暫存區, 然後使用 git commit 命令提交合並。
3.2.5 分支刪除
- 刪除本地分支
$ git branch -d <branch-name>
- 刪除遠程分支
$ git push origin --delete <branch-name>
# 或者
$ git push origin :<branch-name>
# 這種格式在早期的 Git 版本中較為常用
# 它的含義就是告訴 Git,要把一個空分支推送到遠程倉庫的指定分支位置
# 實際上就相當於刪除遠程分支。
# 或者
$ git push origin -d <branch-name>
# 此操作僅影響遠程倉庫,本地倉庫中對應的分支仍然存在(如果本地有該分支的話)。
3.3 遠程分支
遠程跟蹤分支是遠程分支狀態的引用, 它們以 <remote>/<branch> 的形式命名.
Git 的 clone 命令會為你自動將遠程倉庫命名為 origin,拉取它的所有數據, 創建一個指向它的 master 分支的指針,並且在本地將其命名為 origin/master。Git還會創建一個與遠程跟蹤分支指向同一個提交對象的本地master分支,這個本地master分支就是你所在的master分支。
“origin” 並無特殊含義
遠程倉庫名字 “origin” 與分支名字 “master” 一樣,在 Git 中並沒有任何特別的含義一樣。
同時 “master” 是當你運行 git init 時默認的起始分支名字,原因僅僅是它的廣泛使用, “origin” 是當你運行 git clone 時默認的遠程倉庫名字。
如果你運行 git clone -o booyah,那麼你默認的遠程分支名字將會是 booyah/master。
3.3.1 查看遠程引用
# 列出遠程倉庫的所有引用信息
# 不僅包括分支(refs/heads/ 下的內容),還涵蓋標籤(refs/tags/ 下的內容)以及其他可能的引用
$ git ls-remote <remote>
# 專門用於列出遠程倉庫中所有分支(包括本地跟蹤的遠程分支)的引用信息
$ git ls-remote --heads <remote>
# 獲得遠程分支的更多信息
$ git remote show <remote>
3.3.2 跟蹤分支
跟蹤分支是一個指向遠程分支的本地分支,它會自動更新以反映遠程分支的狀態。
在一個跟蹤分支上輸入 git pull,Git 能自動地識別去哪個服務器上抓取、合併到哪個分支。
3.3.2.1 創建跟蹤分支
# 創建一個本地分支,該分支會自動跟蹤遠程倉庫的指定分支
$ git checkout -b <branch> <remote>/<branch>
# 或者
# 這會創建一個本地分支,該分支會自動跟蹤遠程倉庫的指定分支
$ git checkout --track <remote>/<branch>
# 都會自動切換到新的分支
# 更加簡潔的方式
$ git checkout <branch>
# 1. Git 會先檢查本地是否存在名為 <branch> 的分支
# 2. 如果不存在,Git 接着會在所有遠程倉庫中查找是否有唯一與之匹配的遠程分支.
# 3. 一旦條件滿足,Git 會自動創建一個本地的 <branch> 分支,並將其設置為跟蹤遠程分支的分支,然後立即切換到這個新創建的本地分支
# 4. 如果遠程倉庫中也不存在名為 <branch> 的分支,Git 會報錯
# 這個快捷方式依賴於遠程分支名稱的唯一性
# 將本地已有分支與遠程分支建立跟蹤關係
# 在已有分支下執行
# -u 或 --set-upstream-to
$ git branch -u <remote>/<branch>
3.3.2.2 查看設置的所有跟蹤分支
$ git branch -vv
3.3.3 刪除遠程分支
$ git push <remote> --delete <branch>
# 基本上這個命令做的只是從服務器上移除這個指針。 Git 服務器通常會保留數據一段時間直到垃圾回收運行,所以如果不小心刪除掉了,通常是很容易恢復的。
3.4 分支改名
3.4.1 本地分支改名
$ git branch -m <old - branch - name> <new - branch - name>
3.4.2 遠程分支改名
# 先改本地分支名,再推送新名並刪除舊名
# 改本地分支名
$ git branch -m <old - branch - name> <new - branch - name>
# 推送新名分支
$ git push <remote> <new_branch-name>
# 刪除舊名分支
$ git push <remote> --delete <old_branch-name>
3.5 變基
變基操作的目的是將一個分支的提交歷史“重新應用”到另一個分支上。
無論是通過變基,還是通過三方合併,整合的最終結果所指向的快照始終是一樣的,只不過提交歷史不同罷了。
變基過程中,原分支的每個提交都會在基準分支的新上下文下重新創建,提交哈希因父節點變更而更新,故每個提交對應一個新對象。
3.5.1 變基的基本操作:
# 分支初始狀態如上圖
# 現在處於master分支
# 現要將master分支變基到main分支
$ git rebase main
# 1. 執行 git rebase main 時,Git 會把 master 分支基於 main 分支的共同祖先之後的修改提取出來
# 2.然後在 main 分支的最新提交之上重新應用這些修改,從而產生一系列新的提交(可看作產生了一個基於 main 分支最新狀態的新提交)
# 3. 並讓 master 分支指針指向這個新的提交
# 如下圖所示
# 檢出到main分支
$ git checkout main
# 進行快進合併master分支
$ git merge master
# 1. 因為 master 分支現在是 main 分支的直接上游(變基後的結果)
# 2. 所以 main 分支可以直接 “快進” 到 master 分支指針所指向的提交位置
# 3. 即將 main 分支指針移動到 master 分支最新提交處,完成合並
# 如下圖所示
3.5.2 截取主題分支上的另一個主題分支,然後變基到其他分支
# 現在有提交記錄如上圖
# 現在處於master分支
# 並且有一個基於c2提交的主題分支demo_1分支和一個基於c4提交的主題分支demo_2分支
# 現在要截取主題分支demo_1分支的另一個主題分支demo_2分支變基到master分支
$ git rebase master demo_1 demo_2
# 執行後HEAD指針指向產生的新提交c6`
# 效果如下圖所示
# 切回master分支,進行快速合併
$ git checkout master
$ git merge demo_2
# 效果如下圖所示
# 將demo_1分支變基到master
$ git rebase master demo_1
# 並切換到master,進行快速合併
$ git checkout master
$ git merge demo_1
# 變基過程中,原分支的每個提交都會在基準分支的新上下文下重新創建,提交哈希因父節點變更而更新,故每個提交對應一個新對象。
# 此處原分支有 3 個提交,因此生成 3 個新提交。
# 效果如下圖所示
3.5.3 變基的注意事項
- 變基操作會改變提交歷史,因此在變基之前,一定要確保你已經備份了所有重要的工作。
- 變基操作可能會導致提交歷史的混亂,因此在執行變基操作之前,一定要確保你已經備份了所有重要的工作。
變基也並非完美無缺,要用它得遵守一條準則:
如果提交存在於你的倉庫之外,而別人可能基於這些提交進行開發,那麼不要執行變基。
3.5.4 用變基解決變基
如果遇到有人推送了經過變基的提交,並丟棄了你的本地開發所基於的一些提交的這種情境
執行 git rebase <remote>/<branch> 命令
- 另一種簡單的方法
git pull --rebase命令
該命令會自動執行
git fetch命令來獲取遠程分支的最新提交,然後執行git rebase命令來將本地分支的提交歷史重新應用到遠程分支的最新提交之上。