You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在裸仓库中编写钩子自动将main分支提交cherry-pick到其他工作树?

问题描述

我拥有main、macos、linux三个分支,希望在main分支完成提交后,自动将该提交cherry-pick到另外两个分支,且操作需在裸仓库中进行。

我已能通过手动执行以下命令完成该操作:

git --git-dir=<path-to-bare-repo>/worktrees/linux --work-tree=<path-to-bare-repo>/linux cherry-pick main
git --git-dir=<path-to-bare-repo>/worktrees/macos --work-tree=<path-to-bare-repo>/macos cherry-pick main

但编写post-commit钩子脚本后,执行时出现“本地更改将被覆盖”的错误,钩子未按预期工作。我的钩子脚本如下:

#!/bin/bash
current_branch=$(git symbolic-ref --short HEAD)

# Check if committing to the main branch
if [ "$current_branch" = "main" ]; then
    gitdir=$(dirname `pwd`)
    # Update the linux branch
    git --git-dir="$gitdir/worktrees/linux" --work-tree="$gitdir/linux" cherry-pick main

    # Update the macos branch
    git --git-dir="$gitdir/worktrees/macos" --work-tree="$gitdir/macos" cherry-pick main

fi

执行提交时的错误信息为:

git commit -m "Add README"
error: your local changes would be overwritten by cherry-pick.
hint: commit your changes or stash them to proceed.
fatal: cherry-pick failed
error: your local changes would be overwritten by cherry-pick.
hint: commit your changes or stash them to proceed.
fatal: cherry-pick failed
[main ed96ee9] Add README
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README

我也曾尝试使用cd ../linux; git cherry-pick main,但同样无法正常工作。请问如何修复该钩子脚本?

修复方案

出现“本地更改将被覆盖”错误的核心原因是linux、macos对应的worktree工作区存在未提交的本地修改,或者当前worktree的HEAD状态与分支最新提交不一致;另外钩子中通过dirname \pwd``获取git仓库路径的方式不可靠,因为post-commit钩子执行时的工作目录不一定是仓库根目录。

可以按以下思路修改钩子脚本:

  1. 用可靠方式获取仓库路径:通过git rev-parse --git-dir获取裸仓库的绝对路径,避免依赖当前工作目录。
  2. 确保worktree分支状态正确:cherry-pick前切换到目标分支,保证分支处于最新状态。
  3. 处理工作区未提交修改:提前检查工作区是否干净,若有未提交内容先暂存,避免覆盖。

修改后的钩子脚本如下:

#!/bin/bash
current_branch=$(git symbolic-ref --short HEAD)

# 仅在main分支提交后执行操作
if [ "$current_branch" = "main" ]; then
    # 获取裸仓库的绝对路径
    bare_repo=$(git rev-parse --git-dir)
    
    # 处理linux分支
    linux_git_dir="$bare_repo/worktrees/linux"
    linux_work_tree="$bare_repo/linux"
    
    # 切换到linux分支并拉取最新状态(无需同步远程可去掉pull)
    git --git-dir="$linux_git_dir" --work-tree="$linux_work_tree" checkout linux
    git --git-dir="$linux_git_dir" --work-tree="$linux_work_tree" pull origin linux
    
    # 检查工作区是否有未提交修改,有则暂存
    if ! git --git-dir="$linux_git_dir" --work-tree="$linux_work_tree" diff --quiet; then
        git --git-dir="$linux_git_dir" --work-tree="$linux_work_tree" stash push -m "Auto-stash before cherry-pick from main"
    fi
    
    # 执行cherry-pick
    git --git-dir="$linux_git_dir" --work-tree="$linux_work_tree" cherry-pick main
    
    # 可选:若需要恢复暂存的修改,取消下面注释(注意可能引发冲突)
    # git --git-dir="$linux_git_dir" --work-tree="$linux_work_tree" stash pop

    # 处理macos分支(逻辑同linux分支)
    macos_git_dir="$bare_repo/worktrees/macos"
    macos_work_tree="$bare_repo/macos"
    
    git --git-dir="$macos_git_dir" --work-tree="$macos_work_tree" checkout macos
    git --git-dir="$macos_git_dir" --work-tree="$macos_work_tree" pull origin macos
    
    if ! git --git-dir="$macos_git_dir" --work-tree="$macos_work_tree" diff --quiet; then
        git --git-dir="$macos_git_dir" --work-tree="$macos_work_tree" stash push -m "Auto-stash before cherry-pick from main"
    fi
    
    git --git-dir="$macos_git_dir" --work-tree="$macos_work_tree" cherry-pick main
    
    # git --git-dir="$macos_git_dir" --work-tree="$macos_work_tree" stash pop
fi

额外注意事项

  • 确保钩子脚本拥有可执行权限:在裸仓库中执行chmod +x hooks/post-commit。
  • 如果你的linux、macos分支不需要同步远程仓库,可以去掉git pull步骤。
  • 若自动恢复暂存的修改,需做好冲突处理的准备,建议在稳定的代码场景下使用。

内容的提问来源于stack exchange,提问作者sahinakkaya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:52:47