2>/dev/null 部分

2>/dev/null 部分

我刚刚编写了以下脚本:将我当前的分支推送到其远程对应部分。

#!/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从现在开始使用。


这个故事的寓意是我写作剧本的两条基本规则之一:

在发明新轮子之前,请务必检查文档。 通常(对于广泛使用的工具),已经有一个选项可以完全满足您的需要,而无需编写自己的“垫片”脚本。

(违反此规则的情况很常见,即为某个工具编写了一个长而复杂的“包装器”脚本,而忽略了执行相同操作的特定命令行标志,这种情况非常常见,而且看起来非常痛苦。)

相关内容