在.gitconfig中,是否可以针对通配符域名配置user.name和user.email?

55

我有一台工作电脑,全局配置了我的工作电子邮件和姓名以进行提交。这很好。然而,我想制定一些规则,比如说:“如果仓库源是github,则使用用户X和电子邮件Y”

我知道可以针对每个仓库创建一个配置项,但我希望它更加自动化:如果克隆是来自github,则应使用github用户详细信息。如果从工作处克隆,则应使用工作详细信息。

有没有办法基于远程域来全局配置这个?还是还有别的方法?

编辑/更新:

我已接受下面的答案,但稍微修改了一下脚本:

#!/usr/bin/env bash

# "Real" git is the second one returned by 'which'
REAL_GIT=$(which -a git | sed -n 2p)

# Does the remote "origin" point to GitHub?
if ("$REAL_GIT" remote -v 2>/dev/null | grep '^origin\b.*github.com.*(push)$' >/dev/null 2>&1); then

    # Yes.  Set username and email that you use on GitHub.
    export GIT_AUTHOR_NAME=$("$REAL_GIT" config --global user.ghname)
    export GIT_AUTHOR_EMAIL=$("$REAL_GIT" config --global user.ghemail)

fi

"$REAL_GIT" "$@"

主要的改动是需要两个git config值。

git config --global user.ghname "Your Name"
git config --global user.ghemail "you@yourmail.com"

这样可以避免在脚本中硬编码数值,使其更具可移植性。也许呢?


请考虑将接受的答案更改为boywhoroared。它是在Mike Morearty的答案被接受之后提交的,但我认为它是一个更好的答案。它更容易添加其他域,并且使用git的post-checkout钩子而不是完全替换可执行文件。 - charmoniumQ
相关链接:https://dev59.com/I2855IYBdhLWcg3wpmLw - djvg
6个回答

53

Git 2.13 增加了对条件配置包含的支持。如果你将你的检出组织成每个工作域的目录,那么你可以根据检出所在位置添加自定义设置。在您的全局 git 配置中:

[includeIf "gitdir:code/work/"]
    path = /Users/self/code/work/.gitconfig

然后在~/code/work/.gitconfig中:

[user]
    email = self@work.com

当然,您可以为任意数量的工作领域执行此操作。


2
这对我来说是一个很好的解决方案。对于Windows,[includeIf "gitdir:D:/repositories/"]将匹配D:\repositories\\中的所有存储库。最后的\显然是必需的。 - ceztko
2
如果您想将其应用于工作区文件夹内的多个文件夹,例如:[includeIf "gitdir:code/work/**"],则必须包括/** glob。 - tiagolisalves
@tiagolisalves - 这不是我的经验。我使用的配置几乎与我上面描述的完全相同,code/work/* 中的每个存储库都会得到 code/work/.gitconfig 的处理,甚至像 code/work/foo/bar 这样的嵌套存储库也是如此。也许您可以提供一个 gist 来演示您所描述的情况? - Jason R. Coombs
我在Ubuntu中使用像**这样的通配符。也许这与不同的实现有关。 - tiagolisalves
1
我正在使用MacOS Big Sur,对于多个文件夹,glob函数工作正常...全局的.gitconfig文件包含[includeIf "gitdir:code/work/**"] \n \t path = /Users/self/code/work/.gitconfig, 另一个位于 /Users/self/code/work/ 路径下的.gitconfig文件包含我的用户名和电子邮件地址。 - ManiVI

21

据我所知,Git中没有内置做这件事情的功能,但下面的Shell脚本似乎相当可靠。修改它以使用你在提交到GitHub时想要的用户名和电子邮件地址,并将其保存为可执行文件并命名为“git”,放在真正的Git之前的路径中。

#!/usr/bin/env bash

# "Real" git is the second one returned by 'which'
REAL_GIT=$(which -a git | sed -n 2p)

# Does the remote "origin" point to GitHub?
if ("$REAL_GIT" remote -v 2>/dev/null |
    grep '^origin\b.*github.com.*(push)$' >/dev/null 2>&1); then

    # Yes.  Set username and email that you use on GitHub.
    export GIT_AUTHOR_NAME='*** put your name here ***'
    export GIT_AUTHOR_EMAIL='*** put your email address here ***'

fi

"$REAL_GIT" "$@"

我在我的电脑上使用类似的技巧与ssh一起使用 - 我想要在运行时更改窗口背景颜色,然后在退出时将其改回 - 对我来说这一直很可靠。

还要注意,这是硬编码为只查看名为origin的远程。


1
GIT_AUTHOR_* 变量只在脚本和 Git 本身的生命周期内被导出,还是相对于终端会话而言是全局的?我不想在接触单个 GitHub 存储库后为非 GitHub 存储库覆盖这些值。 - Andrew
1
它们仅在脚本长度加上正确的 git 导出期间被导出。 - Mike Morearty
1
今天我正在测试/bin中的一个shim,并运行了“export PATH=/bin:$PATH”。后来我切换到另一个项目,运行git status,结果是…fork炸弹!我的错误,但是从现在开始,我将硬编码$REAL_GIT :-) - choover
他们只在脚本长度+git适当时被导出。猜测一下,但我认为这是真的原因是因为脚本的第一行:它在自己的/usr/bin/env bash中执行,而不是/usr/bin/bash。很棒的技巧。四面八方都是+1。 - eduncan911
1
@eduncan911 谢谢,但实际上那不准确。在所有类Unix操作系统中,shell脚本从不将其环境变量导出到父shell。(Windows则不同。) - Mike Morearty
每天学习一点点。 :) - eduncan911

7

5

~/.gitconfig

[user]
    name = John Doe
    email = jdoe@private.com

[includeIf "hasconfig:remote.*.url:https://git.work.com/**"]
    path = .gitconfig.work

~/.gitconfig.work

[user]
    name = John Doe
    email = jdoe@work.com

这样,如果仓库包含任何与https://git.work.com/**匹配的远程内容,用户详细信息将被包括并覆盖~/.gitconfig中的设置。


2
Mike的答案类似,但由于第四行中使用了uniq命令,即使你在shell内启动一个shell,也不会导致fork bomb。
#!/usr/bin/env bash

# "Real" git is the second one returned by 'which'
REAL_GIT=$(which -a git | uniq | sed -n 2p)

# Does the remote "origin" point to GitHub?
if ("$REAL_GIT" remote -v 2>/dev/null |
    grep '^origin\b.*github.com.*(push)$' >/dev/null 2>&1); then

    # Yes.  Set username and email that you use on GitHub.
    export GIT_AUTHOR_NAME='*** put your name here ***'
    export GIT_AUTHOR_EMAIL='*** put your email address here ***'

fi

"$REAL_GIT" "$@"

2
user.nameuser.email用于“签署”您的提交。由于提交是与存储库无关的(比如,当您推送它们时,同一提交将在许多不同的存储库中),因此这些属性不受远程相关性的影响。
您可以在通过https连接到不同远程时设置不同的日志记录。只需在url中放入用户名,格式为https://username@host/path/to/repo.git即可完成。
但是提交者的身份将是相同的user.name,因为提交是在本地进行的,然后只是与其他人共享。
由于提交者的身份是提交的一部分,如果您进行了两次提交,除提交者的名称和电子邮件外完全相同,则这些提交将具有不同的哈希值,因此它们将成为git中的两个不同提交。那会很混乱 :)
如果您真的想这样做,也许您可以使用挂钩(hooks)制作一个东西,将您的提交推送到计算机上的另一个存储库,而该存储库(再次通过挂钩)将重写提交,更改作者并推送到其他远程存储库。
但这太恶心了,我会否认告诉你这件事 ;)

是的,那很糟糕。但我不确定那是否必要... 我并不是想要以两个不同的身份提交到同一个代码库,而是不同的代码库。我也不打算重写已有的提交记录。 - Andrew

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