Git Merge 无头远程分支小技巧

Git Merge 无头远程分支小技巧
旧项目需要整体升级,因此从旧项目中切出了一个独立仓库。由于没有使用 Fork,现在需要把旧项目后续更新的功能合并到新项目中。
由于提交数量很多,一个个执行 cherry-pick 非常麻烦;直接使用
merge 或 rebase,又会从第一次提交开始产生冲突。
可以使用 grafts / replace 将旧提交映射到新的基准提交,从而解决这个问题。
简单来说,就是把旧项目中“切出新项目”的那个提交 SHA,设置为新项目某个提交的父提交。 在本文示例中,将指定的旧项目提交设置为新项目根提交的父提交,之后就可以直接 Merge 旧项目分支,从而合并指定提交节点到最新提交节点之间的所有变更。
相比逐个执行 cherry-pick,这种方式可以避免同一份文件经过多次修改时,
反复处理合并冲突。
同时,旧项目提交历史中已经完成的 Merge 冲突处理结果,也可以直接继承过来。
如果使用 cherry-pick,这些冲突往往需要重新解决一次,操作复杂且容易出错。
操作模板
git fetch upstream
TARGET=$(git rev-parse upstream/master)
# 假设 my-work 的根提交是 ROOT
ROOT=$(git rev-list --max-parents=0 HEAD)
# 创建 replace
# 推荐使用该方式,因为 grafts 已被废弃
git replace --graft $ROOT $TARGET
git log --oneline --graph --decorate
# 此时可以看到 my-work 的根提交下面出现了 upstream 的提交
持久化 Replace 对象
git replace 默认只保存在本地仓库的
.git/refs/replace/ 目录中。
如果希望其他人克隆仓库后仍然能够使用该 Replace 映射,可以尝试将 Replace 引用推送到远程仓库:
git push origin refs/replace/*
需要注意,远程 Git 服务器必须支持存储和获取
refs/replace/* 引用。
我的操作记录
- 在 IDEA 的 Git 提交记录中,找到旧项目的指定提交。
-
右键选择
Copy Revision Number,获取TARGET。 -
在新项目中找到 Root 提交,使用相同方式获取
ROOT。 -
执行
git replace --graft命令。
git replace --graft \
31e8b54b6498404e5383a91c86db233172ebcd37 \
019aece182cdffd15012263ea9671e13447eace6
执行完成后,就可以直接 Merge 旧项目分支。
相关延伸
1. 一个本地项目可以添加多个远程仓库
git remote add store1 http://xxx
2. 本地分支可以合并任意远程仓库的分支
首先获取远程仓库的最新分支信息:
git fetch store1
然后将对应远程分支合并到当前本地分支:
git merge store1/master