我刚刚编写了以下脚本:将我当前的分支推送到其远程对应部分。
#!/usr/bin/env bash
# Usage: pushes current checkout branch to its remote counterpart.
current_branch=$(git symbolic-ref HEAD 2>/dev/null) ||
current_branch="(unnamed branch)"
git push origin ${current_branch}
git symbolic-ref ...
在谷歌搜索如何完成我想做的事情后,我得到了这个东西。它似乎做了我想做的事情,但是还有其他方法可以实现这一点吗?
我也不明白这部分的含义/作用2>/dev/null
编辑:读了一点之后bash文档我猜这是重定向之王?
答案1
好的,代码审查开始了。
# Usage: pushes current checkout branch to its remote counterpart.
跳过第一个词。这是描述脚本功能的注释,而不是描述如何使用它。
current_branch=$(git symbolic-ref HEAD 2>/dev/null) ||
current_branch="(unnamed branch)"
您正在运行git symbolic-ref HEAD
,丢弃它stderr
并将 分配stdout
给一个变量。如果失败,您可以使用分支名称(unnamed branch)
。
git push origin ${current_branch}
最后,您将本地分支推送到原点。
这里有一些解释:
2>/dev/null 部分
在 Linux/Unix 终端上运行的每个程序都有一个称为的输入通道,stdin
它通常收集来自键盘的输入。它还具有两个输出通道,称为stdout
(用于打印正常操作信息的标准输出)和stderr
(用于打印警告和运行时错误的标准错误)。这些通道起源于硬件,但现在是每个终端和每个 Shell 都支持的纯软件标准。 Bash 处理 stdout 和 stderr 通道的方式是通过由数字1
和表示的指针2
。该2>
部分所做的就是告诉程序将其 stderr 重定向到不同的目标。/dev/null
是一个基本上充当黑洞的虚拟设备。发送到那里的任何东西都会丢失。因此,其2>/dev/null
字面意思是“不打印任何非标准输出”。
||部分
bash 中的双管道意味着:如果左侧的程序失败,即返回的退出代码不是0
,则运行双管道的右侧。您的“右侧”继续到下一行,您可以在其中为同一变量分配一个后备值。
现在回到评论。
您想要将新创建的分支推送到原点的远程分支,并且希望它与本地分支具有相同的名称。
你的代码没有这样做。嗯,不可靠。
HEAD
在 git 中是一个特殊的引用,它指向当前签出的分支中的最新提交(如果有)。最后一部分是您的代码存在危险的地方。HEAD
不一定总是指向一个分支。它也可以处于所谓的分离 HEAD 状态。在这种情况下,您的命令将失败并出现错误fatal: ref HEAD is not a symbolic ref
。此错误将被您的脚本丢弃,并会继续使用分支名称(unnamed branch)
。最后一行将尝试推送(unnamed branch)
您可能不想要的本地分支。
即使命令成功,您也会得到类似的输出refs/heads/yourbranchname
。您可以使用该选项--short
仅获取最后一部分:
git symbolic-ref --short HEAD
结果将是:
yourbranchname
如果我们没有分行怎么办?简单的。你不想推动任何东西!如果无法确定分支名称,您应该退出脚本。您可以通过以下方式进行操作。添加显式exit $errorcode
或使用 bash 的set -e
标志:
current_branch=$(git symbolic-ref HEAD) || exit $?
这里$?
包含最后一个命令的退出代码,因此git
调用失败。您不需要隐藏stderr
.这有助于确定出了什么问题。
或者:
set -e
current_branch=$(git symbolic-ref HEAD)
它set -e
启用了一种特殊的 bash 模式,在每次出现错误时都会退出脚本。我强烈鼓励您在每个脚本中使用它。
下一部分:
git push origin ${current_branch}
这个命令没有任何问题,但我认为你让自己的生活变得有点太艰难了。此详细命令仅需要一次即可在本地分支和远程分支之间创建链接。您可以使用-u
如下选项保存该链接:
git push -u origin ${current_branch}
运行此命令一次后,您只需键入即可git push
,它会自动推送到正确的远程分支。请记住,当您签出或克隆远程分支时,会自动建立此链接。仅本地创建的分支才需要此操作。
我们来总结一下
您可能想像这样重写脚本:
#!/usr/bin/env bash
# Pushes current checkout branch to its remote counterpart.
set -e
current_branch=$(git symbolic-ref --short HEAD)
git push -u origin "${current_branch}"
在为新分支运行一次后,只需使用:
git push
答案2
看看push.default
里面的设置git help config
。
我引用其中的一部分:
push.default Defines the action git push should take if no refspec is explicitly given. Different values are well-suited for specific workflows; for instance, in a purely central workflow (i.e. the fetch source is equal to the push destination), upstream is probably what you want. Possible values are: ... o current - push the current branch to update a branch with the same name on the receiving end. Works in both central and non-central workflows.
简而言之,运行git config --global push.default current
一次在您的机器上,然后git push
从现在开始使用。
这个故事的寓意是我写作剧本的两条基本规则之一:
在发明新轮子之前,请务必检查文档。 通常(对于广泛使用的工具),已经有一个选项可以完全满足您的需要,而无需编写自己的“垫片”脚本。
(违反此规则的情况很常见,即为某个工具编写了一个长而复杂的“包装器”脚本,而忽略了执行相同操作的特定命令行标志,这种情况非常常见,而且看起来非常痛苦。)