【git】通过 rebase 合并分支
【git】通过 rebase 合并分支
- 概述
- 例子
- 准备合并的分支
- 开始合并分支
- dev 分支后续处理
- 比对分支
概述
在 git 版本管理中,我们有两种合并分支的主要方式,他们是 rebase 和 merge 。 相比 merge , rebase 的优势在于它可以让提交历史保持线性,令到历史更加清晰。同时,如果合并过程中存在冲突, rebase 的线性历史也可以更方便观察冲突解决的过程。
例子
准备合并的分支
(1) 从 release 上切出 dev 分支
A---B <--- origin/release, origin/dev
(2) 在 dev 上开发新功能,在 release 上修复线上紧急 bug
A---B---C---D <--- origin/release
\
dev1 <--- origin/dev
(3) 在 release 上的 commit-C 非常关键,所以 cherry-pick 到 dev 上
$ git checkout dev
$ git cherry-pick -x C
A---B---C---D <--- origin/release
\
dev1---C' <--- origin/dev
(4) 在 dev 上继续开发新功能
A---B---C---D <--- origin/release
\
dev1---C'---dev2 <--- origin/dev
开始合并分支
这里我们先创建一个 tmp 分支用于 rebase ,完成使命后会将其删去。步骤 5-5 进行了一次空提交,目的是给分支合并留下记录,方便以后查阅历史。
(5) 合并分支时,新建一个分支 tmp rebase 到 release 上
[1] 在 dev 分支上新建一个 tmp 分支
$ git checkout -b tmp origin/dev
A---B---C---D <--- origin/release
\
dev1---C'---dev2 <--- origin/dev, tmp
[2] 将 tmp rebase 到 release 上
$ git rebase origin/release tmp
dev1'---dev2' <--- tmp
/
A---B---C---D <--- origin/release
\
dev1---C'---dev2 <--- origin/dev
[3] 将 release merge 到 tmp 上
$ git checkout release
$ git merge --ff-only tmp release
dev1'---dev2' <--- origin/release, tmp
/
A---B---C---D
\
dev1---C'---dev2 <--- origin/dev
[4] 删去 tmp 分支
$ git branch -d --force tmp
A---B---C---D---dev1'---dev2' <--- origin/release
\
dev1---C'---dev2 <--- origin/dev
[5*] 在 release 上进行一次空提交
$ git commit --allow-empty -m "merge message"
A---B---C---D---dev1'---dev2'---M <--- origin/release
\
dev1---C'---dev2 <--- origin/dev
dev 分支后续处理
(6) dev 完成使命后,可以删除
$ git push origin --delete dev
$ git branch -D dev
A---B---C---D---dev1'---dev2'---M <--- origin/release
(6') dev 完成使命后,可以 rebase 到 release 上
$ git checkout dev
$ git rebase remotes/origin/release dev
$ git push --force origin dev
A---B---C---D---dev1'---dev2' <--- origin/dev
\
M <--- origin/release
比对分支
#!/bin/bash
develop=dev
release=release_online
# 拉取最新
git fetch origin >& /dev/null
if [ $? -ne 0 ]; then
echo "Error: git fetch error" >& 2
exit 1
fi
# 检查分支是否存在
git branch -r | grep "origin/${develop}" >& /dev/null
if [ $? -ne 0 ]; then
echo "Error: branch not found" >& 2
exit 1
fi
git branch -r | grep "origin/${release}" >& /dev/null
if [ $? -ne 0 ]; then
echo "Error: branch not found" >& 2
exit 1
fi
# 打印 develop
echo "${develop}"
echo "commit,author,date,message,patch id"
content=$(git log origin/${release}..origin/${develop} --pretty=format:"%H %an" | cat)
echo "${content}" | while read commit author_name; do
if [ -n "${commit}" ]; then
patch_id=$(git show $commit | git patch-id | cut -d' ' -f1)
message=$(git log $commit -n 1 --pretty=format:"%s")
author_date=$(git log $commit -n 1 --pretty=format:"%ad" --date=iso | cut -d' ' -f1)
author_time=$(git log $commit -n 1 --pretty=format:"%ad" --date=iso | cut -d' ' -f2)
echo "\"${commit:0:8}\",\"${author_name}\",\"${author_date} ${author_time}\",\"${message}\",\"${patch_id}\""
fi
done
# 打印 release
echo "${release}"
echo "commit,author,date,message,patch id"
content=$(git log origin/${develop}..origin/${release} --pretty=format:"%H %an" | cat)
echo "${content}" | while read commit author_name; do
if [ -n "${commit}" ]; then
patch_id=$(git show $commit | git patch-id | cut -d' ' -f1)
message=$(git log $commit -n 1 --pretty=format:"%s")
author_date=$(git log $commit -n 1 --pretty=format:"%ad" --date=iso | cut -d' ' -f1)
author_time=$(git log $commit -n 1 --pretty=format:"%ad" --date=iso | cut -d' ' -f2)
echo "\"${commit:0:8}\",\"${author_name}\",\"${author_date} ${author_time}\",\"${message}\",\"${patch_id}\""
fi
done