Git配置目录范围,包含多个存储库 [英] Git config with directory scope, containing multiple repositories
问题描述
情况如下:
- 我有多个域,其中我编写代码,例如专业和空闲时间。
- 这些域中的每一个都包含多个Git存储库,位于其中一个域目录中的分层目录结构中。
- I have multiple domains in which I write code, e.g. professional and free time. Those are represented by different directories on my computer.
- Each of those domains contains multiple Git repositories, in a hierarchical directory structure inside one of the domain directories.
每个域名,我想使用不同的电子邮件地址作为作者/提交者信息的一部分。也就是说,我希望我的私人地址被列入我的空闲时间项目,我的公司地址在我的专业地址。
Per domain, I want to use a different email address as part of author/committer information. That is, I want my private address to be listed in my free-time projects and my company address in my professional ones.
git config
知道3个范围:存储库,全局和全系统。 我基本上需要的是存储库和全局之间的第四个范围,代表一组存储库(或只是文件系统中的目录)。
git config
knows 3 scopes: repository, global and system-wide. What I basically need is a 4th scope between repository and global, representing a group of repositories (or simply a directory in the file system).
看起来像 git config
不允许。当然,我可以为每个存储库设置电子邮件地址,但是我每次设置或克隆存储库时都希望避免此手动步骤。一个选项是编写一个包含 git init / clone
和 git config
的脚本,还有其他的想法? / p>
It seems like git config
doesn't allow that. Of course I could set the email address per repository, but I want to avoid this manual step every time I set up or clone a repository. One option would be to write a script that wraps git init/clone
and git config
, are there other ideas?
推荐答案
我想出的解决方案来自于。因为它不是直接适用于我的情况,我修改了钩子的bash脚本和改进了几个部分*。
The solution I came up with is inspired from Scott Weldon's answer. Since it was not directly applicable for my case, I adapted the hook's bash script and improved several parts*.
从主目录中假定以下目录结构:
Assume the following directory structure from the home directory:
~
.gitconfig // [init] templatedir
.git-template
hooks
post-checkout // our bash script
MyDomain
.gitconfig // [user] name, email
最初我让Git知道我的模板目录在哪里。在Windows上,您可能需要指定绝对路径( C:/Users/MyUser/.git-template
)。
Initially I let Git know where my template directory is. On Windows, you may need to specify the absolute path instead (C:/Users/MyUser/.git-template
).
git config --global init.templatedir '~/.git-template'
在〜/ MyDomain / .gitconfig
中,我存储该目录(域)的配置,应该应用对其内的所有存储库及其子目录。
In ~/MyDomain/.gitconfig
I store the configuration for that directory (domain), which should be applied to all repositories inside it and its subdirectories.
cd ~/MyDomain
git config --file .gitconfig user.name "My Name"
git config --file .gitconfig user.email "my@email.com"
有趣的部分是 post-checkout
bash脚本,它定义了后检查钩子。我使用一个自定义的 user.inferredConfig
标志只执行一次(在 git clone
),而不是重复(on git checkout
)。当然也可以创建一个单独的文件来表示该状态。
The interesting part is the post-checkout
bash script, which defines the post-checkout hook. I used a custom user.inferredConfig
flag to execute it only once (on git clone
), not repeatedly (on git checkout
). It would of course also be possible to create a separate file to represent that state.
#!/bin/bash
# Git post-checkout hook for automated use of directory-local git config
# https://stackoverflow.com/a/40450106
# Check for custom git-config flag, to execute hook only once on clone, not repeatedly on every checkout
if grep -q "inferredConfig" .git/config
then
exit
fi
# Automatically set Git config values from parent folders.
echo "Infer Git configuration from directory..."
# Go upwards in directory hierarchy, examine all .gitconfig files we find
# Allows to have multiple nested .gitconfig files with different scopes
dir=$(pwd)
configFiles=()
while [ "$dir" != "/" ]
do
# Skip first directory (the newly created Git repo)
dir=$(dirname "$dir")
if [ -f "$dir/.gitconfig" ]
then
configFiles+=("$dir/.gitconfig")
fi
done
# Iterate through configFiles array in reverse order, so that more local configurations override parent ones
for (( index=${#configFiles[@]}-1 ; index>=0 ; index-- )) ; do
gitconfig="${configFiles[index]}"
echo "* From $gitconfig:"
# Iterate over each line in found .gitconfig file
output=$(git config --file "$gitconfig" --list)
while IFS= read -r line
do
# Split line into two parts, separated by '='
IFS='=' read key localValue <<< "$line"
# For values that differ from the parent Git configuration, adjust the local one
parentValue=$(git config $key)
if [ "$parentValue" != "$localValue" ]
then
echo " * $key: $localValue"
git config "$key" "$localValue"
fi
done <<< "$output"
# Set custom flag that we have inferred the configuration, so that future checkouts don't need to do it
git config user.inferredConfig 1
done
*:原始代码的更改包括: / p>
*: The changes from the original code include:
- 适用于路径中的空格(在Windows上特别有用)
- 解析来自
.gitconfig
正确(不要读取for
,使用循环读取
而不是) - 检查
.gitconfig
从根目录到本地目录的文件,而不是副-versa - 仅在初始克隆时调用钩子,而不是在每次结帐时调用钩子
- 输出在
git上应用的配置设置克隆
- Works with spaces in paths (especially interesting on Windows)
- Parses key-value pairs from
.gitconfig
correctly (don't read lines withfor
, iterate withwhile read
instead) - Checks
.gitconfig
files from root to local directory, not vice-versa - Invokes hook only at initial clone, not at every checkout
- Output the config settings that are applied on
git clone
这篇关于Git配置目录范围,包含多个存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!