用沙哑的钩子用力推到另一根远端树枝上

  • 本文关键字:一根 git shell
  • 更新时间 :
  • 英文 :


我想运行

git push origin --force CURRENT_BRANCH_NAME:sandbox

在预推挂钩中。

如何获得

CURRENT_BRANCH_NAME 

作为上述命令的一部分?

我知道我可以使用git branch --show-current来返回当前分支名称。只是不知道如何将其输出与上述git命令一起使用。

首先,我将回答您实际提出的问题:

  • 若要获取当前分支名称,请使用git branch --show-currentgit symbolic-ref --short HEADgit rev-parse --abbrev-ref HEAD请注意,这三个命令的作用略有不同请参阅下面的详细信息。

  • 在POSIX兼容的shell中,要将另一个命令中某个命令的输出替换为参数,请使用后引号或$()。我更喜欢$(...)序列,因为它嵌套得很好:也就是说,你可以在$(...)中放入另一个$(...),因为括号嵌套,所以它就可以工作了。反引号并非如此(它们可以起作用,但更为棘手)。

接下来,我会注意到您不应该麻烦做这件事。原因很简单:你必须从以上三项中选择一项,其中两项可能是错误的,这都是不必要的。简单使用:

git push --force origin HEAD:sandbox

或者,在其中两项可能错误的情况下,为了严格正确:

git push --force origin HEAD:refs/heads/sandbox

该变体使用完全限定的引用refs/heads/sandbox来引用远程Git中的分支名称sandbox,而不管尝试将HEAD转换为Git提交哈希ID的结果如何。

为什么这样做

git push命令将提交(不是文件,不是分支,只是提交和其他支持Git的对象)推送到其他Git。一旦提交(和/或其他支持Git对象)已经其他Git并准备在那里使用,git push通过请求(非强制推送)或命令(强制推送(forced push))其他Git在存储库中创建、删除或更新某些名称来结束

为了实现这一事件序列,git push需要:

  • 如果需要,它应该发送一些提交和/或其他支持Git对象的原始哈希ID
  • 名称它应该请求/命令其他Git设置或删除,以及要做的操作(设置与删除);以及
  • 强制标志(可以是简单的关闭/打开,也可以是更复杂的"租赁"风格选项之一)

你的Git——你的软件,从你的存储库发送到另一个Git,该Git是接收到目标存储库的软件——从获得以下三项

  • 标志,如+HEAD:refs/heads/sandbox中的--force+git push --delete中的--delete,它们位于明显的位置
  • 对于应当发送的原始散列ID,从src:dst对的左侧
  • 对于要更新的名称,从同一对的右侧

Git调用该对本身,无论是否带有可选的+强制标志,一个refspec。所以feature:sandbox是refspec,HEAD:sandbox也是refspec。事实上,即使是简并形式:

git push origin main

例如,使用refspec:它只是一个缺少冒号的部分,因此您只提供src部分。这是部分refspec,在这种情况下,Git对目标使用与您为源提供的相同的名称(对于git push,即git fetch也与refspec一起使用,但它对部分refspec的处理方式不同)。

由于您已经计划使用带有冒号的完整参考规范,因此左侧的项不需要是名称。您的Git将发送到另一个Git的名称来自refspec的右侧。

现在,这里有一个小问题:如果你给你的Git一个不合格的名称,比如moo,那么发送Git(即你的)如何知道是要求接收Git设置分支名称(refs/heads/moo),还是标记名称(refs/tags/moo),或者其他类型的名称(例如,Gerrit的refs/for/moo)?答案是,你的Git和/或他们的Git会尽最大努力猜测你指的是哪种名称,但通常情况下,当你这样做时——提供完整的参考规范,也就是说——明智的做法是在右边提供完整的参考,这样你就可以确定你想让其他Git设置(或删除)什么。脚本尤其如此,它可能在没有人工监督者的情况下运行。

因此这里有一个一般规则

当你作为一个人在跑步时:

git push origin feature3 v1.2

您知道feature3是您自己的本地分支名称,v1.2是您自己本地标记名称,所以您知道这实际上是refs/heads/feature3:refs/heads/feature3refs/tags/v1.2:refs/tags/v1.2。但在脚本中,通常是一次写入多次运行,更明智的做法是显式。

Coda:三个不同的命令

Git有两个";模式";对于HEAD:附加分离。(注意:Git调用后一个分离的HEAD模式;我将附加的HEAD模型作为明显的对应名称,但它不是正式的Git名称。)在附加的HEA德模式中,名称HEAD分支名称的符号引用1然而,在分离模式中,HEAD保存原始提交哈希ID。

当您处于附加HEAD模式时,命令git branch --show-current将显示HEAD所附加的名称,但当您处于分离HEAD模式下时,命令将无提示打印任何内容并以成功状态退出

命令git symbolic-ref HEAD在附加HEAD模式下打印HEAD所附加的分支的全名,并在分离HEAD模式时产生错误消息、无标准输出和非零退出代码。它使用--short打印分支名称的短版本,但在分离时仍然产生相同的无输出但错误。

命令git rev-parse --abbrev-ref HEAD在附加HEAD模式下打印当前分支的缩写名称,在分离HEAD模式中打印单词HEAD

这里还有一种模式值得一提,尽管它非常罕见:当你在";孤儿;或";未出生的";分支(Git使用这两个术语来指代这种状态),名称HEAD是对不存在的分支名称的符号引用。在状态下,git branch --show-currentgit symbolic-ref HEAD都成功(并打印不存在的分支名称),但git rev-parse --abbrev-rev HEAD失败。

要测试您所处的模式并获得提交哈希ID:

detached=false unborn=false
branch=$(git symbolic-ref --short HEAD 2>/dev/null) || detached=true
if ! $detached; then
git rev-parse -q --verify HEAD >/dev/null || unborn=true
fi

在执行这五行之后,$detached保存HEAD是否分离(作为一个简单的布尔结果),$branch保存HEAD未分离时的分支名称,$unborn包含测试当前是否有提交的结果,或者进行新的提交将创建当前分支。(很少需要$unborn。)


1在古老的原始Git中,这是用符号链接实现的:例如ln -s refs/heads/master HEAD。Git在移植到Windows时不得不放弃这个特定的快捷方式,因为Windows缺乏符号链接。

相关内容

  • 没有找到相关文章

最新更新