当普通命令成功时,Git别名失败 [英] git alias fails when plain command succeeds

查看:0
本文介绍了当普通命令成功时,Git别名失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在~/.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))

运行得非常好。我做错了什么?

推荐答案

TL;DR

您需要使用Git别名的!形式:!git reset $(...),而不是较短的形式!reset $(...)

长音

要了解此问题,我们需要了解:

cmd1 $(cmd2 arg ...)

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

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

第一次运行seq -f f%g 1 3

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

外壳读取这些单词,将它们转换为三个参数传递给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首先查看的参数-它在试图理解该行的其余部分之前,先扫描所有参数以寻找选项-所以这就是它抱怨的那个参数。

但是,如果我们将整个字符串提供给外壳,我们会让外壳展开每个$(...)事件。第一个命令运行git rev-parse --abbrev-ref HEAD,它打印当前分支的名称(如果有,或者HEAD如果有分离的头部)。此输出被反馈到外部git merge-base命令中,以查找master和命名分支(或再一次为HEAD)之间的合并基本提交。如果幸运的话,git merge-base打印一个提交散列ID,外壳用它替换最后一个命令:

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,它将重新设置索引以匹配HEAD提交。如果有多个合并基础--这很少见,但也不是不可能--Git会随机挑选一个。最好编写一个外壳函数或外壳脚本,使用git merge-base --all来验证是否恰好存在一个合并基,但更简单的别名将适用于几乎所有实际情况。

这篇关于当普通命令成功时,Git别名失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆