普通命令成功后,git别名失败

时间:2018-08-16 22:33:38

标签: git version-control alias

我在〜/ .gitconfig文件中存储了以下别名

reset-master = reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))

但是当我运行git reset-master时,它会失败并

$ git reset-master
error: unknown option `abbrev-ref'
usage: git reset [--mixed | --soft | --hard | --merge | --keep] [-q] 
[<commit>]
   or: git reset [-q] [<tree-ish>] [--] <paths>...
   or: git reset --patch [<tree-ish>] [--] [<paths>...]

    -q, --quiet           be quiet, only report errors
    --mixed               reset HEAD and index
    --soft                reset only HEAD
    --hard                reset HEAD, index and working tree
    --merge               reset HEAD, index and working tree
    --keep                reset HEAD but keep local changes
    --recurse-submodules[=<reset>]
                          control recursive updating of submodules
    -p, --patch           select hunks interactively
    -N, --intent-to-add   record only the fact that removed paths will be added later

正在运行

git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))

完全正常。我在做什么错了?

1 个答案:

答案 0 :(得分:2)

要将PetSerAl's comment(正确)扩展为答案,我们需要知道:

cmd1 $(cmd2 arg ...)

实际上是由 shell 处理的,方法是运行cmd2及其参数 first cmd2的输出(更准确地说是标准输出流)返回到外壳程序,该外壳程序将其读取并将其分解为单词,然后将这些单词传递给cmd1 。因此:

wc $(seq -f f%g 1 3)

首先运行seq -f f%g 1 3

$ seq -f f%g 1 3
f1
f2
f3

shell读取这些单词,将它们变成三个参数传递给wc

wc f1 f2 f3

(此示例有点愚蠢,因为我们知道seq -f f%g 1 3总是会打印这三个名称,因此我们可以只用这三个名称运行wc,但可以用于说明。)

默认情况下,

Git的别名不是 通过外壳运行:

reset-master = reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))

表示Git尝试将文字字符串$(git传递为git reset的第一个参数。第二个参数是merge-base,依此类推。其中一个参数是--abbrev-ref,首先是git reset所使用的参数-在试图弄清该行的其余部分之前,它会扫描所有参数中的选项,因此它抱怨。

但是,如果我们将整个字符串输入到 shell ,我们将获得shell来扩展每个$(...)事件。第一个运行git rev-parse --abbrev-ref HEAD,它打印当前分支的名称(如果有的话,或者如果我们有分离的HEAD,则打印HEAD)。此输出将反馈到外部git merge-base命令中,以找到master与命名分支(或再次为HEAD)之间的合并基础提交。运气好的话,git merge-base会打印一个提交哈希ID,shell会用它代替最终命令:

git reset <hash-id>

我们可以通过编写Git来做到这一点:

reset-master = !git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))

作为以!开头的Git别名表示通过外壳运行其余文本

请注意,如果没有 个合并基础提交,它将运行git reset,它等效于git reset --mixed HEAD,它将重新设置索引以匹配{ {1}}提交。如果存在多个合并基础(这是罕见的但并非不可能),Git会选择随机的基础。编写一个使用HEAD来验证是否存在一个合并基础的shell函数或shell脚本可能会很好,但是更简单的别名将适用于几乎所有实际情况