git config alias中的感叹号代表什么意思?

51

我只看到以下的git config命令:

git config --global alias.out \!"git fetch; git cherry origin/HEAD -v"

它是什么意思?它是否等同于这个:

git config --global alias.out '!git fetch; git cherry origin/HEAD -v',

我对感叹号感到困惑,希望能得到帮助。


5
我认为感叹号表示该别名是一个 shell 命令,而不是 Git 命令。虽然我记不清百分之百了。 - Chris Hayes
请注意,如果您像这样别名命令 lg1 = log --graph --format...,则无法将其别名为子命令(lg = lg1 不起作用),但您需要使用 !,如 lg = !"git lg1" - Nick T
3个回答

60
git-config手册中:

如果别名展开以一个感叹号为前缀,它将被视为一个 shell 命令。


4
请注意,Shell 命令将在存储库的顶层目录中执行,这可能不一定是当前目录。例如:git config --global alias.conf "!cat .git/config" 可以派上用场。 - Frank N

6

最受欢迎的答案仅表示!使git别名成为“shell命令”。那是什么意思?这只是引出了我紧接着要问的问题:

将git别名作为“shell命令”执行是什么意思,有什么作用?

@Frank Nocke在这里的评论中慷慨地回答了这个问题。他的评论实际上应该是另一个答案(这样我就可以点赞了),因此我尝试将其变成答案:

让我们再引用一下man git commit手册中的内容(我加粗了一些):

如果别名扩展的前缀是感叹号,它将被视为 shell 命令。例如,定义 alias.new = !gitk --all --not ORIG_HEAD,调用 git new 相当于运行 shell 命令 gitk --all --not ORIG_HEAD。请注意,shell 命令将从存储库的顶层目录执行,这可能不一定是当前目录。GIT_PREFIX 设置为通过在原始当前目录中运行 git rev-parse --show-prefix 返回的值。参见 git-rev-parse(1)。
另请参阅(感谢 Martin C. 指出):https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases,其中说道(重点添加):

As you can tell, Git simply replaces the new command with whatever you alias it for. However, maybe you want to run an external command, rather than a Git subcommand. In that case, you start the command with a ! character. This is useful if you write your own tools that work with a Git repository. We can demonstrate by aliasing git visual to run gitk:

$ git config --global alias.visual '!gitk'
因此,! 表示 git 别名正在访问常规 shell 命令而不是 git 子命令,并且它还使 git 在 git 仓库的根目录中执行此 shell 命令,而不是在当前目录中执行。(提示:该句含有英文单词和标点符号,请结合语境准确翻译)

因此,如果您运行此命令为您提供一个名为 git add-commit 的 git 别名,用于一次性执行 git addgit commit 操作 (source):

git config --global alias.add-commit '!git add -A && git commit'

如果这样做,您将在~/.gitconfig文件中看到以下内容:

[alias]
    add-commit = !git add -A && git commit

现在,您可以像这样使用该别名:
git add-commit -m 'My commit message'

这个别名被执行时,就像在git仓库的根目录下运行常规的shell命令一样,因此,这似乎有点像执行以下操作:

starting_dir="$PWD"
# see: https://dev59.com/cHNA5IYBdhLWcg3wcddk#957978
repo_root_dir="$(git rev-parse --show-toplevel)"
cd "$repo_root_dir"
git add -A && git commit -m 'My commit message'
cd "$starting_dir"

如果你不太喜欢使用Git别名,只想将其变为Bash函数,可以在~/.bashrc文件底部添加以下内容:

git-add-commit() {
    starting_dir="$PWD"
    # See: https://dev59.com/cHNA5IYBdhLWcg3wcddk#957978
    repo_root_dir="$(git rev-parse --show-toplevel)"
    cd "$repo_root_dir"
    git add -A
    git commit "$@"
    cd "starting_dir"
}

然后像这样运行它(注意git之后的额外破折号):

git-add-commit -m 'My commit message'

或者将其制作为一个独立的可执行的bash脚本,文件名为git-add-commit,存放在你的PATH文件夹中(例如在~/bin/git-add-commit),并在顶部添加#!/usr/bin/env bash的shebang行,然后你可以像使用git别名一样运行该命令,但是不需要在“git”后面加上连字符,就像这样:

git add-commit -m 'My commit message'

这是因为 git 可执行文件会扫描你的 PATH 变量中所有目录,查找名为 git-ANYTHING 的可执行文件,并将它们作为 git ANYTHING 运行。

另请参阅:

  1. 有没有一种方法可以在一个命令中获取 git 根目录?
  2. Git 添加和提交在一个命令中
  3. *****https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases

1
这是一篇关于 Git 的一个看似晦涩难懂的隐藏功能的精彩而详尽的回答,它提供了高层次的功能概述,并将其作为一个简单的 shell 脚本进行了解密。完美而全面,与主题相关。每个 Git 用户在使用一年后都应该阅读此文。 - adamency

5

来自https://git-scm.com/book/zh/v2/Git-基础-Git-别名

然而,有时您可能想运行外部命令,而不是 Git 子命令。在这种情况下,您需要以 ! 字符开头执行该命令。

因此,如果您只想使用 git子命令,则不需要在此处使用!。

但是,如果您想要使用git命令/外部命令,则需要使用!。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接