用途
git-rebase-sync 用于将当前功能分支通过 git rebase 同步到最新的 origin/{base_branch}(通常是 dev 或 main 等仓库默认分支)。它强调在冲突解决时不做猜测,遇到意图不明确的情况会提出明确的澄清问题。
主要能力
- 将当前分支变基到指定的基础分支。
- 有意识地解决冲突,避免臆测。
- 保留安全护栏:备份引用、在执行历史重写命令前确认、安全推送。
- 检测堆叠分支(stacked branches),并通过 --update-refs 让它们跟随重写,避免被孤立。
- 支持普通变基与保留合并提交(--rebase-merges)两种模式。
硬性规则
- 不创建或切换到其他功能分支,除非明确要求,否则在当前分支上操作。
- 在执行任何历史重写命令(git rebase ...、git push --force*)之前,打印将要运行的确切命令并等待确认。
- 在开始变基前创建本地备份引用(优先使用附注标签),除非明确要求,否则不推送备份引用。
- 优先使用 git push --force-with-lease,绝不使用普通的 --force。
- 如果正确的冲突解决方案不明确,停止并询问一个有针对性的问题,不编造产品行为。
使用方式(工作流)
- 识别基础分支与当前分支:使用 git branch --show-current 获取当前分支;若未提供基础分支,使用 gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' 获取 GitHub 默认分支;然后 git fetch origin。
- 预检安全检查:git status 确保工作区干净且没有进行中的操作。如果存在进行中的 merge/rebase/cherry-pick,停止并询问如何处理(中止还是继续)。
- 创建本地备份引用(不推送):git tag -a {branch_name}-rebase-backup-$(date +%Y%m%d-%H%M%S) -m "pre-rebase backup" HEAD,并记录标签名作为 {backup_ref} 用于恢复。
- 选择变基模式:通过 git rev-list --count --merges origin/{base_branch}..HEAD 检查分支是否包含合并提交。如果存在合并提交,询问是保留(--rebase-merges)还是展平(普通变基)。
- 检测堆叠分支:枚举指向被重写范围(origin/{base_branch}..HEAD)的其他本地分支,报告给用户。普通变基会将这些分支孤立在旧提交上,而 --update-refs 会将它们移动到重写后的提交上。在另一个工作区中检出的分支会被 --update-refs 跳过,需要标记以便手动验证。
- 运行变基(需要确认):默认使用 --update-refs,打印确切命令并等待确认。默认命令:git rebase --update-refs origin/{base_branch};保留合并时:git rebase --rebase-merges --update-refs origin/{base_branch}。可通过 git config --global rebase.updateRefs true 设为永久默认。
- 冲突处理循环:当冲突发生时,收集上下文(git status),识别冲突文件,打开文件理解周围代码与意图。优先采用最小化、机械化的解决方式:除非功能分支有意取代上游更改,否则保留上游更改;适当时重新运行生成器(锁文件、代码生成)而不是手动编辑。如果意图不明确,提出一个有针对性的问题,例如“我们应该保留新的上游行为 X,还是保留功能行为 Y?”或“这个文件是生成的吗,可以安全地重新生成,还是需要手动解决?”应用解决方案后,仅暂存已解决的文件(git add <file...>),然后 git rebase --continue。如果解决风险过高或不明确,停止并询问,可选建议中止变基。冲突期间有用的命令:git diff 查看当前冲突块,git show 查看正在重放的提交,git rebase --abort 安全退出(优先于破坏性重置)。
- 变基后验证:使用 git log --oneline --decorate origin/{base_branch}..HEAD 显示新的提交范围。确认第 5 步中的每个堆叠分支都移动到了重写后的范围。git rebase --update-refs 会打印“Updated the following refs with --update-refs”摘要,移动的分支引用也应作为装饰出现在日志中的新提交上。记录未移动的分支(例如在另一个工作区中检出的)以便手动处理。如果可用,运行适当的仓库检查(测试、类型检查、lint)。
- 推送更新后的分支(需要确认):如果分支已存在于 origin,变基会重写历史,因此推送需要 force-with-lease。--update-refs 只移动本地引用。普通的 git push 只更新当前分支——每个同样存在于 origin 的堆叠分支(来自第 5 步)必须单独强制推送。打印确切命令并等待确认。当前分支:git push --force-with-lease origin HEAD:{branch_name};每个已移动且存在于 origin 的堆叠分支(每个分支重复):git push --force-with-lease origin {stacked_branch}。因在另一个工作区中检出而被跳过的分支未被移动——推送前需验证。
恢复
如果出现问题,使用 {backup_ref} 恢复变基前的状态。除非在展示确切命令后明确确认,否则不要运行破坏性命令(例如 git reset --hard)。
适用场景
- 需要将功能分支同步到最新基础分支并保持历史整洁。
- 存在堆叠分支,希望它们跟随变基而不被孤立。
- 希望在冲突解决中保持谨慎,避免猜测产品行为。
限制
- 不创建或切换分支,仅在当前分支操作。
- 所有历史重写命令和推送都需要用户确认。
- 备份引用默认不推送。
- 在另一个工作区中检出的分支不会被 --update-refs 移动,需要手动处理。
- 冲突解决意图不明确时会停止并询问,不会自动决定。