如何将 bash 脚本直接嵌入到 git 别名中

Posted

技术标签:

【中文标题】如何将 bash 脚本直接嵌入到 git 别名中【英文标题】:How to embed bash script directly inside a git alias 【发布时间】:2010-11-21 12:28:21 【问题描述】:

我可以嵌入以下 bash shell 代码吗:

for name in $(git diff --name-only $1); do git difftool $1 $name & done

直接进入创建一个git别名:

git config --global alias.diffall ***my-bash-code-here***

这从我在 SO 上的 previous question/answer 引出,我将代码放入 .sh 文件,然后为该文件添加别名:

git config --global alias.diffall '!sh diffall.sh'

但是在对简单性的永无止境的追求中,总有一种方法可以跳过文件并将代码直接插入别名中吗?我无法弄清楚格式...

【问题讨论】:

【参考方案1】:

将这两行添加到您的 .git/config 文件中应该可以解决问题。

[alias]
    diffall = '!for name in $(git diff --name-only $1); do git difftool $1 $name & done'

编辑:大概 git-config 版本也可以,但我喜欢将我的别名保留在配置文件中以便于管理。

git wiki 上有一个很好的页面,它非常清楚地解释了别名:http://git.or.cz/gitwiki/Aliases 特别是,请阅读“带参数的高级别名”

【讨论】:

git config --global 会将您的别名存储在 $HOME/.gitconfig 上,其中(IMO)它们更易于管理;几乎没有别名需要特定于存储库。 (回购具体进入 repo/.git/config) 谢谢大卫,但它对我不起作用 - 或者您包含的伟大链接中的任何变体。也许我应该提到我在 Windows 环境中运行?谢谢凯泽,同意,这对我来说是“全球性的”。 如今,git.wiki.kernel.org/index.php/Aliases#Advanced 是一个值得一看的好地方。 (git 或 cz 链接重定向到那里,但本节特别提到了使用参数运行复杂的东西)【参考方案2】:
git config --global alias.diffall '!sh diffall.sh'

这在某种程度上是多余的。如果你无论如何都要把 'diffall.sh' 添加到你的 $PATH 中,为什么不把它保存为 'git-diffall',这样你就不用声明别名了。是的,“git diffall”会运行它。

【讨论】:

那个。是很棒的。我最初担心我会不小心运行某些东西,因为我已经编写了一些 shell 脚本来做 git 的东西,并给它们加上前缀 'git-',但是我的 shell (zsh) 不会自动完成它们,所以我会必须明确键入它们。如果我想要自动完成行为,我可以为其自己的子命令声明一个 git 别名,这也是我明确从脚本到子命令的链接的要求。 是的,它是一个二进制文件,你只需要 bang:! binary 对我不起作用,在别名 !sh git checkout $(git log --branches -1 --pretty=format:'%D' | sed 's/.*, //g') 中使用会导致 /usr/lib/git-core/git: /usr/lib/git-core/git: cannot execute binary file。在开始时尝试使用和不使用sh【参考方案3】:

我在文档中找不到,但是如果您在路径中创建脚本“git-”,则可以在您的存储库中使用“git name”调用它。

见:

$ cd ~/bin
$ echo "echo I love this log:
>pwd
>git log --graph  --summary --decorate --all" > git-logg
$ chmod +x git-logg
$ cd /path/to/your/repo
$ git logg
I love this log:
/path/to/your/repo
* commit 3c94be44e4119228cc681fc7e11e553c4e77ad04 (whatever-branch)
| Author: myself <my@Laptop.(none)>
| Date:   Fri Apr 1 16:47:20 2011 +0200
| 
|     would have been better not to do it at all
| 
...
$

所以,你也可以用这种(相当晦涩的)方式编写任何你喜欢的别名。

您还可以为定义函数的新命令添加自动完成功能。信息here

$ _git_logg ()

  # you can return anything here for the autocompletion for example all the branches
  __gitcomp_nl "$(__git_refs)" 

【讨论】:

+1,以为它只能在 git libexec 文件夹中工作。感谢分享这个技巧【参考方案4】:

(来自 ProGit 文档:http://progit.org/book/ch7-3.html

您是否尝试在 .git/hooks 中添加脚本?

例如,如果你创建一个脚本 .git/hooks/post-checkout:

#!/bin/bash

echo "This is run after a 'git checkout'"

然后运行命令:

$ git checkout master
Switched to branch 'master'
This is run after a 'git checkout'

【讨论】:

钩子与配置、扩展和别名有什么关系?【参考方案5】:

要在 git 别名中运行命令,尤其是向这些命令传递参数,您可能必须创建一个临时函数,然后立即调用:

$ vim ~/.gitconfig
...
[alias]
    # compare:
    foo = "! echo begin arg=$1/$2/end"
    foo2 = "!f()  echo "begin arg=$1/$2/end"; ; f"

在这个例子中,这个函数可能是你所需要的(并且对于你可以在单个“语句”中做什么也更加灵活);您可能会说,对于这两个选项,git 命令的剩余参数只是作为参数传递给别名,无论它是“echo”还是“f”;调用该函数只会消耗 args,而忽略未明确使用的内容:

$ git foo a b c
begin arg=a/b/end a b c

$ git foo2 a b c
begin arg=a/b/end

另一个示例(根据匹配模式列出所有别名)(注意:您可以在整个 .gitconfig 中继续重复使用相同的函数名称“f()”):

[alias]
    alias = "!f()  git config --get-regexp "^alias.$1$" ; ; f"

第一个返回“foo$”的别名,第二个返回“foo.*”的别名:

$ git alias foo
alias.foo ! echo begin arg=$1/$2/end

$ git alias 'foo.*'
alias.foo ! echo begin arg=$1/$2/end
alias.foo2 !f()  echo begin arg=$1/$2/end; ; f

(注意:实际结果可能因 shell 而异;我在 Linux、Unix 和 Cygwin (Windows) 上将其与 bash 一起使用。)

【讨论】:

git.wiki.kernel.org/index.php/Aliases#What.27s_new.3F 隐式推荐使用sh -c,这样你就不用担心用户的登录shell是什么了。 我提供的函数语法有意可跨多个 shell (sh/ksh/bash/zsh) 移植,并且比启动子进程更快。我建议仍然使用函数语法,除非在特定平台上存在特定的可移植性问题。 你的评论让我回到了这个答案,我可能会用你的方式。它节省了一级报价,而这些级别已经足够疯狂了。 :-) 这篇文章看起来不错,描述了你在做什么:atlassian.com/blog/git/advanced-git-aliases 注意:我已在此处发布了关于此答案的后续问题:***.com/questions/52123145/…。 "如何用自定义别名替换内部 git 命令,例如git status"

以上是关于如何将 bash 脚本直接嵌入到 git 别名中的主要内容,如果未能解决你的问题,请参考以下文章

Git bash如何调用不同版本的python

git别名可以像bash别名一样扩展吗?

如何在 Windows 的 Git Bash 中设置别名?

bash 脚本从 bash 脚本添加 git 凭据

git-bash的alias别名设置

如何在 vscode 终端中使用 git bash 别名?