TIP在使用静态博客框架的时候,我们常会遇到这样的场景:需要维护一个公开仓库作为基础框架,同时保留一个私有仓库用于构建发布博客,且希望私有仓库能随时同步公开仓库的更新。这个需求看似简单,实际操作中却可能遇到各种 Git 冲突和分支问题。本文将结合我的实操经历,详细分享这一过程中的配置方法、遇到的问题及解决方案。
为什么需要这样做?
我需要维护两个仓库:
-
公开仓库(
Mizuki
):作为基础项目框架,包含通用功能和公共更新,以及个性化修改 -
私有仓库(
my-blog
):基于公开仓库的个人博客,包含私有内容和网站配置
核心需求是:私有仓库能选择性同步公开仓库的更新,既保留网站配置,又能及时获取基础框架的 bug 修复和功能升级。这种模式的优势在于:
-
公开仓库专注通用功能开发及个性化需求和公共更新
-
保护私有仓库里的网站配置及文章不被公开
操作步骤与遇到的问题及解决方案
一、仓库初始化与关联配置
1. 关联两个仓库
首先需要将私有仓库与公开仓库关联,通过添加远程源(upstream
通常用于表示上游仓库)实现:
\# 克隆私有仓库到本地
git clone https://github.com/CuteLeaf/my-blog.git
cd my-blog
\# 添加公开仓库作为上游源
git remote add upstream https://github.com/CuteLeaf/Mizuki.git
\# 验证关联结果
git remote -v
此时会显示两个远程源:origin
(私有仓库)和 upstream
(公开仓库)。
二、首次同步公开仓库更新
1. 拉取公开仓库分支
git fetch upstream
该命令会拉取公开仓库的所有分支信息(如 upstream/master
)。
2. 合并公开仓库分支(首次合并的问题)
执行合并命令时,遇到第一个问题:
git merge upstream/master
\# 报错:fatal: refusing to merge unrelated histories
原因:两个仓库初始提交历史不同,Git 认为它们是完全独立的项目,拒绝合并。
解决方案:使用 --allow-unrelated-histories
参数强制首次合并:
git merge upstream/master --allow-unrelated-histories
三、合并冲突的处理
强制合并后,出现大量文件冲突(add/add
类型):
Auto-merging .gitignore
CONFLICT (add/add): Merge conflict in .gitignore
...(多个文件冲突)
原因:两个仓库存在同名文件但内容不同(如配置文件、示例文章)。
解决方案:手动解决冲突:
- 打开冲突文件,寻找冲突标记:
<<<<<<< HEAD # 私有仓库内容
...
\======= # 分隔线
... # 公开仓库内容
\>>>>>>> upstream/master
-
根据需求编辑:保留私有内容、保留公开内容或合并两者
-
标记为已解决并提交:
git add .
git commit -m "解决首次合并冲突,整合公开仓库更新"
四、选择性同步特定更新
当不需要合并整个分支,只想同步公开仓库的某个提交时,使用 cherry-pick
命令:
1. 查看公开仓库提交历史
git log upstream/master --oneline
\# 输出示例:
\# d381c56 bug:修复了RSS会泄露加密文章的重大问题
\# b1fc2c2 update:更新预设数据
\# ...
2. 应用单个提交(遇到的问题)
git cherry-pick d381c56
\# 提示:The previous cherry-pick is now empty...
原因:该提交的修改在私有仓库中已存在,或冲突解决后无实际变更。
解决方案:
-
若需保留空提交:
git commit --allow-empty
-
若需跳过:
git cherry-pick --skip
3. 应用多个提交
git cherry-pick af8436f c5e47ec e297dd2 ...
问题:中间某个提交出现冲突,导致操作中断。
解决方案:
-
解决冲突后继续:
git add . && git cherry-pick --continue
-
跳过当前提交:
git cherry-pick --skip
-
放弃所有操作:
git cherry-pick --abort
五、分支分歧与推送失败
当本地与远程私有仓库提交历史不一致时,推送会失败:
git push
\# 报错:! \[rejected] master -> master (non-fast-forward)
原因:本地分支与远程分支有不同的提交(本地 22 个,远程 12 个),Git 禁止覆盖远程历史。
解决方案:
- 优先方案:拉取远程更新并合并
git pull origin master # 拉取并合并远程更新
\# 若有冲突,解决后提交
git push origin master # 再次推送
- 谨慎方案:强制推送(仅个人仓库且确认无需保留远程额外提交时使用)
git push origin master --force
总结:最佳实践流程
- 日常同步公开仓库更新:
git fetch upstream # 拉取公开仓库最新信息
git merge upstream/master # 合并到本地私有分支(无需首次的强制参数)
- 选择性同步特定提交:
git log upstream/master --oneline # 查看目标提交
git cherry-pick <提交哈希> # 应用单个提交
git cherry-pick <哈希1> <哈希2> ... # 应用多个提交
- 解决冲突原则:
-
配置文件:合并双方必要配置
-
私有内容(如个人文章):保留本地版本
-
公共功能(如 bug 修复):优先保留公开仓库版本
- 推送前检查:
git pull origin master # 确保与远程私有仓库同步
git push origin master # 推送本地修改
通过这种方式,既能高效维护公开仓库与私有仓库的同步,又能灵活控制更新范围。
部分信息可能已经过时