Как заменить авторов всех коммитов, сохранив остальные данные
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Переписывание истории коммитов с заменой авторов
Замена авторов во всех коммитах — операция, требующая перезаписи истории Git. Это изменяет SHA-хеши коммитов, поэтому требует осторожного подхода, особенно в общих репозиториях.
Основной подход с git filter-branch
Наиболее мощный инструмент — git filter-branch с использованием переменных окружения GIT_AUTHOR_ и GIT_COMMITTER_**:
git filter-branch --env-filter '
OLD_EMAIL="старый@email.com"
CORRECT_NAME="Новое Имя"
CORRECT_EMAIL="новый@email.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --all
Ключевые параметры:
--env-filter— позволяет модифицировать переменные окружения для каждого коммита--tag-name-filter cat— сохраняет теги, переписывая их на новые коммиты-- --all— применяет операцию ко всем веткам
Современная альтернатива: git filter-repo
git filter-repo — более современный и производительный инструмент, рекомендованный вместо git filter-branch:
# Пример файла mailmap для git-filter-repo
git filter-repo --mailmap mailmap.txt
Содержимое mailmap.txt:
Новое Имя <новый@email.com> Старое Имя <старый@email.com>
Пакетная обработка нескольких авторов
Для замены нескольких авторов создайте скрипт:
#!/bin/bash
git filter-branch -f --env-filter '
case "$GIT_COMMITTER_EMAIL" in
"user1@old.com")
export GIT_COMMITTER_NAME="Имя1"
export GIT_COMMITTER_EMAIL="user1@new.com"
;;
"user2@old.com")
export GIT_COMMITTER_NAME="Имя2"
export GIT_COMMITTER_EMAIL="user2@new.com"
;;
esac
case "$GIT_AUTHOR_EMAIL" in
"user1@old.com")
export GIT_AUTHOR_NAME="Имя1"
export GIT_AUTHOR_EMAIL="user1@new.com"
;;
"user2@old.com")
export GIT_AUTHOR_NAME="Имя2"
export GIT_AUTHOR_EMAIL="user2@new.com"
;;
esac
' --tag-name-filter cat -- --all
Последовательность действий для безопасного выполнения
-
Создайте полную резервную копию:
git clone --mirror исходный-репозиторий backup-repo.git -
Выполните переписывание на локальной копии
-
Проверьте результат:
git log --pretty=format:"%h %an <%ae> %cn <%ce>" -
Принудительный push (если необходимо):
git push --force --tags origin 'refs/heads/*'
Важные предостережения
- Изменяются SHA-хеши — все коммиты получат новые идентификаторы
- Согласуйте с командой — переписывание истории нарушит работу коллег с репозиторием
- Обновите все клоны — после операции всем придется переклонировать репозиторий
- Проверьте CI/CD — убедитесь, что pipelines не полагаются на старые SHA
Альтернативный подход без переписывания истории
Если изменение авторов нужно только для будущих отображений, можно использовать .mailmap файл без переписывания истории:
Правильное Имя <правильный@email.com> Старое Имя <старый@email.com>
Команды git log и git shortlog будут учитывать эти соответствия, но фактические данные коммитов останутся неизменными.
Выбор подхода
- Для приватных репозиториев —
git filter-repoилиgit filter-branch - Для публичных репозиториев с историей —
.mailmapфайл - Для полной санации данных — переписывание истории с последующим принудительным push
Эта операция требует понимания последствий, но при правильном выполнении позволяет корректировать метаданные коммитов без потери содержимого изменений.