Как изменить электронную почту автора во время коммита с помощью хуков - PullRequest
4 голосов
/ 16 февраля 2011

Вопрос говорит сам за себя.

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

Ответы [ 3 ]

8 голосов
/ 16 февраля 2011

Вы можете просто заставить их изменить свойство user.email в их локальном репозитории.

git config user.email email@server.com
3 голосов
/ 23 марта 2012

Независимо от того, что еще произойдет, если вы что-то измените - даже один символ в имени пользователя и / или электронной почте - в каком-то коммите, вы получите новый, другой коммит. (Это потому, что идентификатор фиксации состоит из крипографической контрольной суммы содержимого фиксации. Итак, если вы можете сломать криптографию, вы можете создать две разные фиксации, которые будут иметь один и тот же идентификатор. Но тогда вы полностью разбитый мерзавец, и, вероятно, также выиграл премию Тьюринга или Нобелевскую премию. :-))

Лучше всего подойдет "рабочая ловушка", с которой вы связались в комментариях к другому ответу. Эта проблема сводится к одному: вы не можете вносить какие-либо изменения в опубликованный коммит (не вызывая проблем для пользователей этой публикации), но вы можете внести любые изменения в приват совершайте, пока вы «знаете, что делаете». Использование git commit --amend --author "$user <$email>" -C HEAD для каждого отдельного коммита, поскольку они входят в вашу копию репо, гарантирует, что вы замените неопубликованный коммит новым, немного другим неопубликованным коммитом. (Я предполагаю, что вы поместили это в хук после фиксации.)

Я не уверен, какой частью вы недовольны, может быть, [ -n "$richo_git_rewrite" ] && exit 0? Это достаточно умный метод обнаружения рекурсии. Альтернатива - пропустить обнаружение рекурсии и вместо этого сравнить существующего пользователя и адрес электронной почты в коммите с желаемыми.

Вот скрипт, который делает это (за исключением того, что я использовал переменную env SWITCHY = true для моего тестирования):

#! /bin/sh
# first, pick which git config variables to get
if ${SWITCHY-false}; then
    config=user.work
else
    config=user
fi
# next, find out if they're set
can_rewrite=false
target_author=$(git config --get $config.name) &&
    target_email=$(git config --get $config.email) &&
    can_rewrite=true
# If they ARE set, we can "rewrite" (replace) the commit;
# if not, we can't.  Just because we can, though, does not
# mean we should.  Find out if the current author and email
# differ from the desired ones.
if $can_rewrite; then
    current_author=$(git log --pretty=format:%an HEAD -n 1)
    current_email=$(git log --pretty=format:%ae HEAD -n 1)
    if [ "$current_author" != "$target_author" -o \
          "$current_email" != "$target_email" ]; then
        # may want --allow-empty here, if you're allowing empty commits
        # at all, otherwise empty ones don't get the rewrite done
        git commit --amend --author "$target_author <$target_email>" -C HEAD
    fi
fi

Примечание: вам нужно установить этот же хук в hooks/post-merge, чтобы получить исправленные слияния с обновленным именем и адресом электронной почты. И, конечно, вы можете немного упростить ловушку (вам не нужна фактическая переменная can_rewrite, просто выполните две операции git config с && s и продолжайте работу с другой &&). Также имеет смысл иметь больше, чем просто пользователь против пользователя. Работа, может быть, пользователь против пользователя. Режим А против пользователя. Режим Б и т. Д., И вы можете прогнать его из любых тестов, которые вам нравятся (переменные env, наличие или отсутствие команд, и т. д.).


ОК, согласно комментариям, есть хук перед фиксацией. К сожалению, он не работает с git merge (ловушка предварительной фиксации запускается и выдает сообщение, а затем включается фиксация слияния).
#! /bin/sh
fatal()
{
    echo "$@" 1>&2
    exit 1
}
# pick which git config variables to get
if ${SWITCHY-false}; then
    config=user.work
else
    config=user
fi
# tn, te = target author name/email
# an, ae = what git will use for author name/email
tn=$(git config --get $config.name) || exit 0
te=$(git config --get $config.email) || exit 0

an=${GIT_AUTHOR_NAME-$(git config --get user.name)} ||
    fatal "no author name set"
ae=${GIT_AUTHOR_EMAIL-$(git config --get user.email)} ||
    fatal "no author email set"
[ "$an" = "$tn" -a "$ae" = "$te" ] ||
    fatal "git will use author $an <$ae>
but you want them as $tn <$te>
fix your environment variables and try again"

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

(Стоит также отметить, что этот хук перед фиксацией не смотрит на рабочее дерево или индекс, поэтому у него нет обычной ошибки "проверка рабочего дерева, но фиксация индекса".)

1 голос
/ 20 марта 2012

http://progit.org/book/ch6-4.html объясняет, как переписать историю.Внизу находится команда

git filter-branch --commit-filter '
    if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
    then
            GIT_AUTHOR_NAME="Scott Chacon";
            GIT_AUTHOR_EMAIL="schacon@example.com";
            git commit-tree "$@";
    else
            git commit-tree "$@";
    fi' HEAD

, которая изменяет все коммиты с schacon@localhost на schacon@example.com.

Предупреждение: это меняет ВСЕ коммиты с самого раннего письма-изменяем вперед.

...