[英]force push to another remote branch using husky hook
I would like to run我想跑
git push origin --force CURRENT_BRANCH_NAME:sandbox
in a pre-push hook.在预推钩中。
How do I get如何得到
CURRENT_BRANCH_NAME
as part of the above command?作为上述命令的一部分?
I understand I can have git branch --show-current
to return the current branch name.我知道我可以让git branch --show-current
返回当前分支名称。 Just not sure how to use its output with the above-mentioned git command.只是不确定如何将其输出与上述 git 命令一起使用。
First, I'll answer the question you actually asked:首先,我将回答您实际提出的问题:
To get the current branch name, use git branch --show-current
or git symbolic-ref --short HEAD
or git rev-parse --abbrev-ref HEAD
.要获取当前分支名称,请使用git branch --show-current
或git symbolic-ref --short HEAD
git rev-parse --abbrev-ref HEAD
git symbolic-ref --short HEAD
或git rev-parse --abbrev-ref HEAD
。 Note that these three commands do slightly different things!请注意,这三个命令的作用略有不同! See details below.请参阅下面的详细信息。
In POSIX-compatible shells, to substitute the output of a command in place inside another command as an argument, use either backquotes or $(
and )
.在 POSIX 兼容的 shell 中,要将一个命令的输出替换为另一个命令内部的适当位置作为参数,请使用反引号或$(
和)
。 I prefer the $(...)
sequence as it nests properly: that is, you can put another $(...)
inside the $(...)
and it Just Works since parentheses nest.我更喜欢$(...)
序列,因为它可以正确嵌套:也就是说,您可以在$(...)
放置另一个$(...)
并且它可以正常工作,因为括号嵌套。 This is not true of backquotes (they can be made to work but it is trickier).反引号并非如此(它们可以起作用,但更棘手)。
Next, I'll note that you should not bother to do this.接下来,我会注意到你不应该费心这样做。 The reason is simple: you have to pick one of the above three items and two of them are probably wrong, and this is all unnecessary.原因很简单:你必须选择的一个以上的三个项目,其中两个都可能是错误的,这是所有不必要的。 Simply use:只需使用:
git push --force origin HEAD:sandbox
or, for strict correctness in the case where two of the items are probably wrong:或者,在其中两项可能错误的情况下,为了严格正确:
git push --force origin HEAD:refs/heads/sandbox
This variant uses a fully qualified reference, refs/heads/sandbox
, to refer to the branch name sandbox
in the remote Git, regardless of the result of an attempt to turn HEAD
into a Git commit hash ID.此变体使用完全限定的引用refs/heads/sandbox
来引用远程 Git 中的分支名称sandbox
,无论尝试将HEAD
转换为 Git 提交哈希 ID 的结果如何。
The git push
command pushes commits (not files, not branches, just commits and other supporting Git objects) to the other Git. git push
命令将提交(不是文件,不是分支,只是提交和其他支持 Git 对象)推送到另一个 Git。 Once the commits (and/or other supporting Git objects) have made it to that other Git and are ready to be used there, then git push
ends by asking (non-forced push) or commanding (forced push) the other Git to create, delete, or update some name(s) in their repository.一旦提交(和/或其它支撑GIT中的对象)都做了它对其它GIT中并准备在那里被使用,那么git push
通过询问(非强制推入)或命令(强制推)的其他GIT中创建端、删除或更新其存储库中的某些名称。
To achieve this sequence of events, git push
needs:为了实现这一系列事件, git push
需要:
Your Git—your software, sending from your repository, to the other Git that's software receiving into a target repository—gets these three items from:你的 Git——你的软件,从你的存储库发送到另一个 Git,它的软件接收到目标存储库——从以下位置获取这三个项目:
--force
or the +
in +HEAD:refs/heads/sandbox
or the --delete
in git push --delete
, which go in the obvious positions;标志像--force
或+
在+HEAD:refs/heads/sandbox
或--delete
在git push --delete
,其走在明显的位置;src : dst
pair;对于应该发送的原始哈希 ID,从src : dst
的左侧src : dst
对; Git calls the pair itself, with or without the optional +
force flag, a refspec . Git 调用对本身,有或没有可选的+
force 标志,一个refspec 。 So feature:sandbox
is a refspec, and HEAD:sandbox
is also a refspec.所以feature:sandbox
是一个 refspec, HEAD:sandbox
也是一个 refspec。 In fact, even the degenerate form:事实上,即使是退化形式:
git push origin main
for instance, uses a refspec: it's just one in which the colon is missing, so that you provide only a src
part.例如,使用 refspec:它只是缺少冒号的一个,因此您只提供一个src
部分。 This is a partial refspec and in this case, Git uses the same name for the target as you supplied for the source (for git push
that is—while git fetch
also works with refspecs, its treatment of partial refspecs is different).这是一个部分refspec,在这种情况下,Git 为目标使用与您为源提供的名称相同的名称(对于git push
即——虽然git fetch
也适用于 refspec,但它对部分 refspec 的处理是不同的)。
Since you already plan to use a full refspec, with the colon in it, the item on the left is not required to be a name .由于您已经计划使用包含冒号的完整refspec,因此左侧的项目不需要是name 。 The name that your Git will send to the other Git comes from the right hand side of the refspec.你的Git会发送到其他的Git的名字来自的Refspec的右手边。
Now, there's a small hitch here: how does the sending Git (ie, yours) know whether to ask the receiving Git to set a branch name ( refs/heads/moo
), or a tag name ( refs/tags/moo
), or perhaps some other kind of name ( refs/for/moo
for Gerrit for instance) if you give your Git an unqualified name like moo
?现在,这里有一个小问题:发送 Git(即你的)如何知道是否要求接收 Git 设置分支名称( refs/heads/moo
)或标签名称( refs/tags/moo
),如果你给你的 Git 一个像moo
这样的不合格名称,或者也许是其他类型的名称(例如refs/for/moo
代表 Gerrit )? The answer is that your Git and/or their Git will do their best to guess which kind of name you mean, but in general, when you are doing this—providing a full refspec , that is—it's wise to provide a full ref on the right, so that you know for sure what you intend to ask the other Git to set (or delete).答案是你的 Git 和/或他们的 Git 会尽力猜测你的意思,但一般来说,当你这样做时——提供完整的refspec ,也就是说——提供完整的参考是明智的正确的,以便您确定您打算要求其他 Git 设置(或删除)什么。 This is especially true from scripts, which may operate without a human overseer.脚本尤其如此,脚本可能在没有人工监督的情况下运行。
When you, as a human, are running:当你作为一个人跑步时:
git push origin feature3 v1.2
you know that feature3
is your own local branch name, and v1.2
is your own local tag name, so you know that this is really refs/heads/feature3:refs/heads/feature3
and refs/tags/v1.2:refs/tags/v1.2
.您知道feature3
是您自己的本地分支名称,而v1.2
是您自己的本地标签名称,所以您知道这实际上是refs/heads/feature3:refs/heads/feature3
和refs/tags/v1.2:refs/tags/v1.2
。 But in scripts , which are generally write-once run-many-times, it's wiser to be explicit.但在脚本中,通常一次编写多次运行,明确表示更明智。
Git has two "modes" for HEAD: attached and detached . Git 有两种 HEAD 的“模式”: attached和detached 。 (Note: Git calls the latter detached HEAD mode; I made up the name attached HEAD mode as the obvious counterpart, but it's not officially a Git name.) In the attached-HEAD mode, the name HEAD
is a symbolic reference to a branch name . (注意:Git 称后者为分离的 HEAD 模式;我将名称附加的 HEAD 模式作为明显的对应物,但它不是正式的 Git 名称。)在附加的 HEAD 模式中,名称HEAD
是对分支的符号引用名字。 1 In the detached mode, however, HEAD
holds a raw commit hash ID. 1然而,在分离模式下, HEAD
持有原始提交哈希 ID。
The command git branch --show-current
will show the name to which HEAD
is attached when you are in attached-HEAD mode, but will silently print nothing and exit with a successful status when you are in detached-HEAD mode.命令git branch --show-current
将在您处于附加 HEAD 模式时显示HEAD
附加到的名称,但在您处于分离 HEAD 模式时将静默打印任何内容并以成功状态退出。
The command git symbolic-ref HEAD
prints the full name of the branch to which HEAD
is attached when in attached-HEAD mode, and produces an error message, no standard output, and a nonzero exit code when in detached-HEAD mode.命令git symbolic-ref HEAD
在附加 HEAD 模式下打印HEAD
附加到的分支的全名,并在分离 HEAD 模式下生成错误消息、无标准输出和非零退出代码。 It prints the short version of the branch name with --short
but still produces the same no-output-but-error-instead when detached.它使用--short
打印分支名称的简短版本,但在分离时仍会产生相同的 no-output-but-error- 。
The command git rev-parse --abbrev-ref HEAD
prints the shortened name of the current branch when in attached-HEAD mode, and prints the word HEAD
when in detached-HEAD mode.命令git rev-parse --abbrev-ref HEAD
在 attach-HEAD 模式下打印当前分支的缩写名称,并在 detached-HEAD 模式下打印单词HEAD
。
There's one more mode worthy of mention here, although it's quite rare: when you are on an "orphan" or "unborn" branch (Git uses both terms to refer to this state), the name HEAD
is a symbolic ref to a branch name that does not exist.这里还有一种模式值得一提,尽管它非常罕见:当您处于“孤儿”或“未出生”分支时(Git 使用这两个术语来指代这种状态),名称HEAD
是对分支名称的符号引用那不存在。 In this state, git branch --show-current
and git symbolic-ref HEAD
both succeed (and print the nonexistent branch name), but git rev-parse --abbrev-rev HEAD
fails.在这种状态下, git branch --show-current
和git symbolic-ref HEAD
git branch --show-current
git symbolic-ref HEAD
都成功(并打印不存在的分支名称),但git rev-parse --abbrev-rev HEAD
失败。
To test which mode you're in and get the commit hash ID:要测试您处于哪种模式并获取提交哈希 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
After executing these five lines, $detached
holds whether HEAD
is detached (as a simple boolean result), $branch
holds the branch name if HEAD
is not detached, and $unborn
contains the result of testing whether there is currently a commit, or making a new commit will create the current branch.执行完这五行后, $detached
保存HEAD
是否被分离(作为一个简单的布尔结果),如果HEAD
没有分离, $branch
保存分支名称, $unborn
包含测试当前是否有提交,或者使新提交将创建当前分支。 (The need for $unborn
is rare.) (对$unborn
的需求很少见。)
1 In ancient, primeval Git, this was implemented with symlinks: ln -s refs/heads/master HEAD
for instance. 1在古老的原始 Git 中,这是通过符号链接实现的:例如ln -s refs/heads/master HEAD
。 Git had to drop this particular shortcut when it was ported to Windows, which lacked symlinks.当它被移植到缺少符号链接的 Windows 时,Git 不得不放弃这个特殊的快捷方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.