Использование gitconfig для каждой ветки

Наша компания использует множество индивидуальных проектов с открытым исходным кодом. Всякий раз, когда я вношу вклад в восходящую ветвь, у меня есть возможность использовать мой личный адрес электронной почты/имя. Есть ли способ иметь gitconfig для каждой ветки?

Например, я хочу

[remote 'gerrit']
name = 'Personal Name'

[branch 'origin']
name = 'Name in company'

person XeIte    schedule 14.04.2018    source источник
comment
stackoverflow.com/q/4220416/1135424   -  person nbari    schedule 14.04.2018
comment
Вы хотите изменить настройку после оформления заказа или перед отправкой? После оформления заказа относительно просто использовать скрипт после оформления заказа. Перед отправкой будет немного сложнее, так как вам придется переписывать коммиты. Причина, по которой я спрашиваю, заключается в том, что пример немного сбивает с толку .. (обычно происхождение - это имя удаленного устройства)   -  person Moti Korets    schedule 14.04.2018
comment
@MotiKorets Я думаю, что оформления заказа достаточно, и я не заметил, что есть хук перед оформлением заказа. Сценарий, о котором вы говорите, это .git/hook, верно?   -  person XeIte    schedule 14.04.2018
comment
@nbari Я думаю, что ссылка не связана с моей проблемой. Я не хочу иметь несколько репозиториев.   -  person XeIte    schedule 14.04.2018
comment
@Xelte скрипт должен быть в .git/hooks/post-checkout см. мой ответ ниже   -  person Moti Korets    schedule 14.04.2018


Ответы (5)


Для этого можно использовать хук post-checkout. Бегать

$ touch .git/hooks/post-checkout 
$ chmod a+x .git/hooks/post-checkout 

Добавьте содержимое в скрипт post-checkout (при необходимости отредактируйте имена и ветки)

#!/bin/bash
# $3 "0" - checking out file. "1" - checking out branch.
[[ "$3" == "0" ]] && exit 0 
branch=$(git status --short -b | cut -d' ' -f2-)
case $branch in
  gerrit*)
    git config user.name "Personal Name"
    echo "changed user.name to Personal Name"
    ;;
  master*)
    git config user.name "Company Name"
    echo "changed user.name to Company Name"
    ;;
  *)
    echo "Some other branch, what should user.name be?"
    ;;
esac
person Moti Korets    schedule 14.04.2018
comment
Вам не нужно branch=$(git status…). Git отправляет в хук post-checkout 3 параметра — предыдущую ветку, текущую ветку и флаг переключения ветки. - person phd; 14.04.2018
comment
спасибо за ваш комментарий, переданные параметры имеют форму 45fb8d9.., и мы ищем имя ветки. последний параметр, вероятно, полезен, я отредактирую свой ответ, еще раз спасибо. - person Moti Korets; 14.04.2018

С Git 2.23 (3 квартал 2019 г.) нет необходимости в хуке после оформления заказа, и вы можете официально использовать git config условное включение без скрипта!
Механизм условного включения научился основывать выбор на ветке, на которой в данный момент находится HEAD.

См. commit 07b2c0e (05 июня 2019 г.) от Дентон Лю (Denton-L).
(объединено Хунио С. Хамано -- gitster -- в коммит 3707986, 09 июля 2019 г.)

config: узнайте условие onbranch: includeIf

В настоящее время, если пользователь хочет иметь индивидуальные настройки для каждой ветки, он должен вручную отслеживать настройки в своей голове и вручную устанавливать параметры в командной строке или изменять конфигурацию в каждой ветке.

Научите config условию onbranch: includeIf, чтобы оно могло условно включать файлы конфигурации, если ветвь, извлеченная в текущем рабочем дереве, соответствует заданному шаблону.

git config man-страница теперь содержит:

onbranch:

Данные, которые следуют за ключевым словом onbranch:, считаются шаблоном со стандартными подстановочными знаками и двумя дополнительными, **/ и /**, которые могут соответствовать нескольким компонентам пути.

Если мы находимся в рабочем дереве, где имя извлеченной в данный момент ветки соответствует шаблону, условие включения выполняется.

Если шаблон заканчивается на /, автоматически добавляется **.
Например, шаблон foo/ становится foo/**.

Другими словами, он соответствует всем ветвям, начинающимся с foo/. Это полезно, если ваши ветки организованы иерархически, и вы хотите применить конфигурацию ко всем ветвям в этой иерархии.

Итак, в вашем случае:

[includeIf "onbranch:gerrit"]
  path=gerrit

И в файле .git/gerrit:

[remote 'gerrit']
  name = 'Personal Name'

Пример:

vonc@vonvb:~/gits/src/git$ git version
git version 2.23.0.b4


vonc@vonvb:~/gits/src/git$ git config includeIf.onbranch:next.path user1
vonc@vonvb:~/gits/src/git$ git config includeIf.onbranch:pu.path user2
vonc@vonvb:~/gits/src/git$ git config --local -l
core.repositoryformatversion=0
core.filemode=true
core.bare=false
...
includeif.onbranch:next.path=user1
includeif.onbranch:pu.path=user2

Установите файлы конфигурации для каждой ветки:

vonc@vonvb:~/gits/src/git$ git config --file=.git/user1 user.name user1
vonc@vonvb:~/gits/src/git$ git config --file=.git/user1 user.email [email protected]

vonc@vonvb:~/gits/src/git$ more .git/user1
[user]
    name = user1
    email = [email protected]


vonc@vonvb:~/gits/src/git$ git config --file=.git/user2 user.name user2
vonc@vonvb:~/gits/src/git$ git config --file=.git/user2 user.email [email protected]

vonc@vonvb:~/gits/src/git$ more .git/user2
[user]
    name = user2
    email = [email protected]

Проверьте, работает ли он!

vonc@vonvb:~/gits/src/git$ git config user.name
VonC

vonc@vonvb:~/gits/src/git$ git checkout next
Branch 'next' set up to track remote branch 'next' from 'origin'.
Switched to a new branch 'next'
vonc@vonvb:~/gits/src/git$ git config user.name
user1

vonc@vonvb:~/gits/src/git$ git checkout pu
Branch 'pu' set up to track remote branch 'pu' from 'origin'.
Switched to a new branch 'pu'
vonc@vonvb:~/gits/src/git$ git config user.name
user2

vonc@vonvb:~/gits/src/git$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
vonc@vonvb:~/gits/src/git$ git config user.name
VonC

От master до next и до pu ответвлений: три разных user.name! Один на ветку.

Никаких крючков. Нет сценария.


Как показано на Git 2.30 (1 квартал 2021 г.), обязательно используйте Git 2.24+, иначе вы можете получить странные сообщения об ошибках:

См. commit f1beaae (19 ноября 2020 г.) от Йоханнес Шинделин (dscho).
(объединено Хунио С. Хамано -- gitster -- в коммит 1242501, 30 ноября 2020 г.)

t1309: используйте нейтральное имя ветки в onbranch тестовых примерах

Подписал: Йоханнес Шинделин

onbranch тестовых случаев, затронутых этим патчем, на самом деле не пытаются включать какую-либо другую конфигурацию. Их цель — избежать регрессии двух ошибок в коде include.onbranch:<name>.path, которые мы исправили в прошлом, ошибок, которые на самом деле не связаны с каким-либо конкретным именем ветки.

Первая ошибка была исправлена ​​в 85fe0e800ca (config: обход ошибки с includeif:onbranch и ранняя конфигурация, 31 июля 2019 г., Git v2.23.0-rc1 -- слияние ).
По сути, при чтении ранней конфигурации будет ловушка-22, пытающаяся получить доступ к ссылкам, и поэтому мы просто не можем оценить условие в этот момент. Тестовый пример гарантирует, что мы избежим появления этого фиктивного сообщения:

BUG: refs.c:1851: attempting to get main_ref_store outside of repository  

Второй тестовый пример относится к сценарию без Git, где у нас просто нет текущей ветки для начала (потому что у нас вообще нет репозитория), а тестовый пример был представлен в 22932d9169f (config: прекратите проверять, является ли the_repository NULL, 06.08.2019, Git v2.24.0-rc0 -- слияние, указанное в batch #2), чтобы гарантировать, что мы не вызовем ошибку сегментации, если код по-прежнему будет неправильно пытаться просмотреть любую ссылку.

Короче говоря, ни один из этих двух тестовых случаев никогда не будет смотреть на имя текущей ветки, даже в случае регрессии. Поэтому фактическое название ветки вообще не имеет значения. Поэтому мы можем легко избежать здесь названий веток с расовой подоплекой, и это то, что делает этот патч.

person VonC    schedule 14.07.2019

Я не знаю ни одного инструмента, который автоматически меняет имя пользователя и адрес электронной почты после смены ветки, но вы можете установить эту информацию непосредственно перед отправкой с помощью инструмента для перезаписи истории, такого как filter-branch (и дополнительно установить его как хук перед отправкой для автоматизации процесса). Вы можете установить изменение информации об авторе только для определенных веток.

Подробнее см. ссылку ниже: Изменение информации об авторе

person M. Twarog    schedule 14.04.2018

Конфигурация Git поддерживает условные включения, что было бы хорошим решением, но в настоящее время единственным поддерживаемым условием является путь к репозиторию. Филиалы или пульты не подходят для условий. Когда мы делаем коммит, локальный заголовок не должен указывать на ветку (отключенное состояние HEAD), а локальная ветка не должна иметь отслеживающую ветку. Кроме того, имя локальной ветки не обязательно должно совпадать с названием ее отслеживаемой ветки.

Первое возможное решение, о котором я думаю, это post-commit. После завершения фиксации в post-commit получите правильное имя и адрес электронной почты, а затем запустите git -c user.name foo -c user.email bar commit --amend --no-edit, чтобы переписать фиксацию с именем и адресом электронной почты. После нескольких попыток я узнаю, что получается инфинитивная петля. Коммит вызывает post-commit для запуска другого git commit.

Затем я пытаюсь экспортировать такие переменные, как GIT_AUTHOR_NAME, связанные с именем и адресом электронной почты автора и коммиттера в pre-commit. Это тоже не удается. Я думаю, что эти значения должны быть переданы в самом начале git commit и первый вызванный pre-commit уже слишком поздно, не говоря уже о prepare-commit-msg, commit-msg или post-commit, которые вызываются позже.

Третья попытка - это псевдоним, например git $(foo) commit, где foo возвращает правильное -c user.name=xx -c user.email=yy в соответствии с именем ветки и ее удаленным. Но git alias с использованием bash-скрипта — это грязная яма, и я просто сдаюсь.

Наконец я возвращаюсь к post-commit:

#!/bin/bash

head=`git rev-parse --abbrev-ref HEAD`
remote=`git config --get branch."${head}".remote`
if [ "$remote" = "origin" ];then
    git filter-branch -f --env-filter '
        export GIT_AUTHOR_NAME=xx \
        export [email protected] \
        export GIT_COMMITTER_NAME=xx \
        export [email protected]' \
        HEAD^..HEAD
elif [ "$remote" = "gerrit" ];then
    git filter-branch -f --env-filter '
        export GIT_AUTHOR_NAME=yy \
        export [email protected] \
        export GIT_COMMITTER_NAME=yy \
        export [email protected]' \
        HEAD^..HEAD
else
    echo no amend
fi

Это работает до некоторой степени. Но баги очевидны. Один из них заключается в том, что после git cherry-pick коммита, автором которого является кто-то другой, имя автора и адрес электронной почты станут вашими после git filter-branch выполнения. Кроме того, как упоминалось в первом абзаце, если вы хотите, чтобы ветки и удаленные устройства были такими же, как в этом хуке, вы должны следовать некоторым строгим потокам. Никакого отсоединенного HEAD, никакого отсутствия branch.<name>.remote в конфиге.

Я думаю, что идеальным решением может быть псевдоним или функция. Этот ответ также дает хороший совет. Чтобы сбалансировать уровень автоматизации и удобство и надежность, было бы лучше иметь два алиаса для двух случаев, например git -c user.name=foo user.email=foo@com commit. Вы сами решаете, какой псевдоним использовать в разных ветках.

person ElpieKay    schedule 14.04.2018

К вашему сведению: убедитесь, что git действительно имеет правильную версию. Вот мой вопрос в качестве справки: includeIf с ветками в git

Публикую это, потому что перформанс

person kornicameister    schedule 10.03.2020