← Назад к вопросам

Как заменить авторов всех коммитов, сохранив остальные данные

1.8 Middle🔥 71 комментариев
#Git и системы контроля версий

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Переписывание истории коммитов с заменой авторов

Замена авторов во всех коммитах — операция, требующая перезаписи истории 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

Последовательность действий для безопасного выполнения

  1. Создайте полную резервную копию:

    git clone --mirror исходный-репозиторий backup-repo.git
    
  2. Выполните переписывание на локальной копии

  3. Проверьте результат:

    git log --pretty=format:"%h %an <%ae> %cn <%ce>"
    
  4. Принудительный 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

Эта операция требует понимания последствий, но при правильном выполнении позволяет корректировать метаданные коммитов без потери содержимого изменений.

Как заменить авторов всех коммитов, сохранив остальные данные | PrepBro