在Git预推钩内更改目标远程分支名称

时间:2015-05-29 21:31:18

标签: git

我一直在尝试制作一个预推钩,它将从STDIN中读取远程引用,修改它,并让Git接受被推送的修订集,并使用修改后的名称创建远程引用。例如,我想要做的是,

  1. 假设客户端执行git push origin foo
  2. 预推钩会拦截它并将refspec从foo更改为refs/heads/foo:refs/heads/foobar
  3. 接受推送中包含的修订,
  4. Git会在远程仓库上创建一个名为foobar的分支(而不是foo)。
  5. 这种方法可行吗?如果是这样,我如何在钩子中修改客户端的分支参数并将其重定向到不同的分支名称?如果我可以添加任何信息,请告诉我。感谢。

1 个答案:

答案 0 :(得分:1)

你不能在pre-push hook中做到这一点,这已经太晚了:此时git已经连接到遥控器,并为它提供了它(你的git)打算给它的引用名称(远程git)更新,并将这些名称转换为SHA-1(远程git执行此转换,您的本地git只保存结果,然后将它们传递给您的钩子)。如果你允许的话,你当地的git会继续前进,并带有这些名字。

你可以做什么,虽然我会建议反对,因为它过于复杂,因此可能会破坏,是你的预推钩拒绝特别推动,但(首先)运行自己的< em> new git push带有一些其他名称,如果需要的话,会导致你的预推钩不能再做所有这些。

例如,考虑以下伪代码(Python和shell任意混合):

if ${PUSH_HOOK_RUNNING:-false}; then exit 0; fi # don't recurse

accepted=[]
replaced=[]
while read line; do
    lref, lsha1, rref, rsha1 = line.split()
    if lref == "refs/heads/foo" && rref == "refs/heads/foo"; then
        replaced.append("refs/heads/foo:refs/heads/foobar")
    else
        accepted.append("$lref:$rref")
    fi
done
if empty(replaced); then
    exit 0 # let this git push run
else
    # run a substitute git push as part of the hook
    PUSH_HOOK_RUNNING=true git push $accepted $replaced
    exit 1 # prevent this git push entirely
fi

以上内容存在许多缺陷,并且可以通过检查本地和远程引用名称以及SHA-1来解决一系列可以修复的问题。 (特别是,考虑如果本地名称xyz最初引用提交df08eb357dd7f432c3dcbe0ef4b3212a38b4aeff会发生什么,但是当调用“内部”git push时,它会引用其他一些SHA-1完全是由于执行git update-refgit branch -m或其他任何事情的单独流程。)

所有这一切,更简单的方法是使用而不是 git push拥有自己的前端命令喜欢发生,然后为你运行git push