前言
我们在前面的基础篇中学习了 Git 的基本内容,这些内容涵盖了工作内容的 90%,剩下的 10% 则是属于 Git 当中的进阶内容。
分支的合并方式
在大多数情况下,我们都会采用 merge 方式进行分支的合并,这符合绝大多数的项目,但是某些项目也会采用 rebase 方式进行分支的合并。
merge
merge 方式我们在前面提到过,您需要首先切换到上游的分支上,然后将做了修改的下游分支合并到当前活跃的上游分支上,比如 git switch master && git merge dev
,这会将 dev 下游分支合并到 master 上游分支上。
比如我在 main 分支的 C1 这个最新提交记录上新建分支 dev 并提交一次,这时 dev 的最新记录为 C2,接着切换回 main 分支并提交一次,这时的情况如下:
如果采用 merge 方式合并(合并时也会产生一次 commit 提交记录):
当分支很少的时候,我们项目的提交记录的线条是很好区分的,但是!如果有很多分支,我们是不能正确的区分这些提交记录,整个提交记录就好像麻花一样杂乱无序,于是我们可以采用另外一种合并方式 —— rebase。
rebase
所谓的 rebase,官方称为变基,这并不好理解,更加完整的说法是 —— 「重新设置合并后的基准线分支」。
merge 合并方式:需要首先切换到上游的分支上,然后将做了修改的下游分支合并到当前活跃的上游分支上,比如 git switch master && git merge dev
,这会将 dev 下游分支合并到 master 上游分支上。
rebase 合并方式:需要首先切换到做了修改的下游分支上,并在在该分支上指定设置基准线的上游分支。比如 git switch dev && git rebase main
,这会将 dev 合并到 main 并以 main 为基准线分支。采用 rebase 合并方式,我们分支的提交记录就是一条笔直的直线,干净整洁。
如下图的例子,在 main 分支的 C1 提交记录上新创建分支 dev 并且在该分支上提交一次(C2),接着切换到 main 分支并提交一次(C3),最后切换到 dev 分支且使用 git rebase main
:
在 dev 分支上使用 rebase 到 main 后,dev 分支的 C2 提交记录依然存在,C2′ 提交记录指的是 rebase 到 main 分支的 C2 副本
此时的问题是 main 分支并没有指向 C2′ 这个提交记录上,我们重新 rebase 一下就好了:
git switch main && git rebase dev
多分支有序 rebase
现在需要将所有的分支都 rebase 到 main 分支中,但是领导有一个要求,希望 rebase 到 main 之后得到有序的提交记录历史,即 C6′ 在 C7′ 前面,C5′ 在 C6′ 前面,以此类推,这应该怎么操作?
笨方法:
git switch bugFix
git rebase main
git switch side
git rebase bugFix
git switch another
git rebase side
git switch main
git rebase another
git rebase
的手册页中有这样的一种语法:
git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase> | --keep-base] [<upstream> [<branch>]]
我们可以指定 [<branch>]
而不必非要切换到相应的分支,换言之,上面的命令可以简化为:
# 将 bugFix 分支合并到 main 分支并以 main 为基准线分支
git rebase main bugFix
git rebase bugFix side
git rebase side another
git rebase another main
解决 rebase 的冲突问题
同 merge 合并方式一样,我们也要处理 rebase 合并方式的冲突问题,当出现这种冲突问题时,您可以有三种选择:
- 运行
git rebase --abort
来撤销变基,即恢复到git rebase
之前的分支状态 - 手动解决冲突问题
- 运行
git rebase --skip
来跳过引起冲突问题的 commit ,应谨慎使用这种解决冲突的方法。
我们可以在本地库中模拟 rebase 的冲突问题:
PS > cd E:\git-test\
PS > git branch -a
* master
PS > git log --oneline
9139f56 (HEAD -> master, tag: v-1.0.0-2025-03-16) 人为解决 error.log 的合并冲突
94f3acd 新文件 error.log
40ed5ac 新增三行内容到新文件 error.log
6f4b5d9 对文件control.txt的第三行进行追加
33fca75 新增文件control.txt
4be932e newb1分支中的第一个新文件
8a77771 修改后的lab-file文件
f20abbc lab-file初始内容
47d9368 tmp-file.txt --> Tmp-File.txt
ae6cc9d (tag: v-0.0.1-2025-03-16) First commit
9a70355 测试文件
# 在 9139f56 上新创建 module 分支
PS > git branch module
PS > git branch -a
* master
module
PS > git switch module
Switched to branch 'module'
# PowerShell 中换行为 `n
PS > echo "2025-03-20`nBUG`n2025-03-21" > system.log
PS > cat .\system.log
2025-03-20
BUG
2025-03-21
PS > git add ./
PS > git commit -m "新增system.log文件并写入3行内容"
# 切换到 master 分支,创建同名的文件,也写入三行内容但第二行内容不一样
PS > git switch master
PS > echo "2025-03-20`nSYSTEM`n2025-03-21" > system.log
PS > git add ./
PS > git commit -m "新增system.log文件"
# 切换到 module 分支,准备 rebase 到 master 分支
PS > git switch module
Switched to branch 'module'
## 报错如下
PS > git rebase master
Auto-merging system.log
CONFLICT (add/add): Merge conflict in system.log
error: could not apply 38bfc19... 新增system.log文件并写入3行内容
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Could not apply 38bfc19... 新增system.log文件并写入3行内容
# 查看引起冲突的文件内容
PS > cat cat .\system.log
2025-03-20
<<<<<<< HEAD
SYSTEM
=======
BUG
>>>>>>> 38bfc19 (新增system.log文件并写入3行内容)
2025-03-21
我们可以手动解决合并的冲突问题:
# 利用编辑器修改该冲突的文件内容
PS > cat system.log
2025-03-20
SYSTEM
2025-03-21
PS > git add ./
# 重新 rebase
PS > git rebase --continue
Successfully rebased and updated refs/heads/module.
