Как изменить автора, имя коммиттера и адрес электронной почты нескольких коммитов в Git?

Здесь есть отличный пост: Список онлайн-пользователей .

Вы можете создать прослушиватель, который прослушивает событие kernel.controller и обновляет поле пользователя lastActivity каждый раз, когда пользователь активен. Вы можете проверить lastActivity < now()- 2 minutes и обновить временную метку lastActivity.

Также: Реализация активности пользователя в symfony 2

Вот как это сделать

Примечание. Если вы не используете FOSUserBundle, см. раздел «Редактировать» ниже.

1 Добавьте это в свой пользовательский объект

/**
 * Date/Time of the last activity
 *
 * @var \Datetime
 * @ORM\Column(name="last_activity_at", type="datetime")
 */
protected $lastActivityAt;

/**
 * @param \Datetime $lastActivityAt
 */
public function setLastActivityAt($lastActivityAt)
{
    $this->lastActivityAt = $lastActivityAt;
}

/**
 * @return \Datetime
 */
public function getLastActivityAt()
{
    return $this->lastActivityAt;
}

/**
 * @return Bool Whether the user is active or not
 */
public function isActiveNow()
{
    // Delay during wich the user will be considered as still active
    $delay = new \DateTime('2 minutes ago');

    return ( $this->getLastActivityAt() > $delay );
}

2 Create Слушатель событий

securityContext = $securityContext;
        $this->userManager = $userManager;
    }

    /**
    * Update the user "lastActivity" on each request
    * @param FilterControllerEvent $event
    */
    public function onCoreController(FilterControllerEvent $event)
    {
        // Check that the current request is a "MASTER_REQUEST"
        // Ignore any sub-request
        if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) {
            return;
        }

        // Check token authentication availability
        if ($this->securityContext->getToken()) {
            $user = $this->securityContext->getToken()->getUser();

            if ( ($user instanceof UserInterface) && !($user->isActiveNow()) ) {
                $user->setLastActivityAt(new \DateTime());
                $this->userManager->updateUser($user);
            }
        }
    }
}

3 Объявить событие Слушатель как услуга

parameters:
    acme_user.activity_listener.class: Acme\UserBundle\EventListener\ActivityListener

services:
    acme_user.activity_listener:
        class: %acme_user.activity_listener.class%
        arguments: [@security.context, @fos_user.user_manager]
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onCoreController }

И вы готовы идти!

Изменить (без FOSUserBundle)

1 Добавьте это в свой пользовательский объект

Same as Step 1 Above

2 Создайте прослушиватель событий

securityContext = $securityContext;
        $this->entityManager = $entityManager;
    }

    /**
    * Update the user "lastActivity" on each request
    * @param FilterControllerEvent $event
    */
    public function onCoreController(FilterControllerEvent $event)
    {
        // Check that the current request is a "MASTER_REQUEST"
        // Ignore any sub-request
        if ($event->getRequestType() !== HttpKernel::MASTER_REQUEST) {
            return;
        }

        // Check token authentication availability
        if ($this->securityContext->getToken()) {
            $user = $this->securityContext->getToken()->getUser();

            if ( ($user instanceof User) && !($user->isActiveNow()) ) {
                $user->setLastActivityAt(new \DateTime());
                $this->entityManager->flush($user);
            }
        }
    }
}

3 Объявите событие Слушателем как услугой

parameters:
    acme_user.activity_listener.class: Acme\UserBundle\EventListener\ActivityListener

services:
    acme_user.activity_listener:
        class: %acme_user.activity_listener.class%
        arguments: [@security.context, @doctrine.orm.entity_manager]
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onCoreController }

И ты в порядке!

2229
задан Ciro Santilli 新疆改造中心996ICU六四事件 31 May 2018 в 14:08
поделиться

10 ответов

Смена автора (или коммиттера) потребовала бы переписывания всей истории. Если вы согласны с этим и считаете, что оно того стоит, вам следует проверить git filter-branch . Страница man содержит несколько примеров, с которых можно начать. Также обратите внимание, что вы можете использовать переменные окружения для изменения имени автора, коммиттера, дат и т. Д. - см. Раздел «Переменные среды» на справочной странице git .

В частности, вы можете С помощью этой команды исправьте все неправильные имена и адреса электронной почты для всех веток и тегов (источник: GitHub help ):

#!/bin/sh

git filter-branch --env-filter '
OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.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 -- --branches --tags
1095
ответ дан 22 November 2019 в 19:55
поделиться

Один вкладыш, но будьте осторожны, если у вас есть многопользовательский репозиторий - это изменит все коммиты , чтобы иметь одинакового (нового) автора и коммиттера ,

git filter-branch -f --env-filter "GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='new@email'; GIT_COMMITTER_NAME='Newname'; GIT_COMMITTER_EMAIL='new@email';" HEAD

С разрывами строк в строке (что возможно в bash):

git filter-branch -f --env-filter "
    GIT_AUTHOR_NAME='Newname'
    GIT_AUTHOR_EMAIL='new@email'
    GIT_COMMITTER_NAME='Newname'
    GIT_COMMITTER_EMAIL='new@email'
  " HEAD
531
ответ дан 22 November 2019 в 19:55
поделиться

Вы также можете:

git filter-branch --commit-filter '
        if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
        then
                GIT_COMMITTER_NAME="<New Name>";
                GIT_AUTHOR_NAME="<New Name>";
                GIT_COMMITTER_EMAIL="<New Email>";
                GIT_AUTHOR_EMAIL="<New Email>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD

Обратите внимание: если вы используете эту команду в командной строке Windows, вам необходимо использовать " вместо ':

git filter-branch --commit-filter "
        if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
        then
                GIT_COMMITTER_NAME="<New Name>";
                GIT_AUTHOR_NAME="<New Name>";
                GIT_COMMITTER_EMAIL="<New Email>";
                GIT_AUTHOR_EMAIL="<New Email>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi" HEAD
585
ответ дан 22 November 2019 в 19:55
поделиться

Использование интерактивной перебазировки

Вы могли бы сделать

git rebase -i -p <some HEAD before all of your bad commits>

Затем пометить все свои плохие коммиты как «редактировать» в файле перебазирования. Если вы также хотите изменить свою первую фиксацию, вам нужно вручную добавить ее в качестве первой строки в файл перебазирования (следуйте формату других строк). Затем, когда git просит вас изменить каждую фиксацию, выполните

 git commit --amend --author "New Author Name <email@address.com>" 

отредактируйте или просто закройте открывшийся редактор, а затем выполните

git rebase --continue

, чтобы продолжить перебазирование.

Вы можете вообще не открывать редактор, добавив ] - без редактирования так что команда будет:

git commit --amend --author "New Author Name <email@address.com>" --no-edit && \
git rebase --continue

Single Commit

Как отметили некоторые из комментаторов, если вы просто хотите изменить самую последнюю фиксацию, команда rebase не нужна. Просто выполните

 git commit --amend --author "New Author Name <email@address.com>"

. Это изменит автора на указанное имя, но в качестве коммиттера будет указан ваш настроенный пользователь в git config user.name и git config user.email . Если вы хотите установить для коммиттера то, что вы укажете, это установит и автора, и коммиттера:

 git -c user.name="New Author Name" -c user.email=email@address.com commit --amend --reset-author

Примечание о коммитах слиянием

В моем исходном ответе был небольшой изъян. Если есть какие-либо коммиты слияния между текущим HEAD и вашим , то git rebase сгладит их (и Кстати, если вы используете запросы на вытягивание GitHub, в вашей истории будет масса коммитов слияния). Это очень часто может привести к очень разной истории (поскольку повторяющиеся изменения могут быть «перебазированы»), а в худшем случае это может привести к git rebase с просьбой разрешить сложные конфликты слияния (которые, вероятно, были уже разрешено в коммитах слияния). Решение состоит в том, чтобы использовать флаг -p для git rebase , который сохранит структуру слияния вашей истории. Страница руководства для git rebase предупреждает, что использование -p и -i может привести к проблемам, но в разделе ОШИБКИ говорится: « Редактирование коммитов и изменение их сообщений о коммитах должно работать нормально. "

Я добавил -p в приведенную выше команду. Для случая, когда вы

1537
ответ дан 22 November 2019 в 19:55
поделиться

Для одной фиксации:

git commit --amend --author="Author Name <email@address.com>"

(извлечено из ответа Асмерера)

183
ответ дан 22 November 2019 в 19:55
поделиться

Если вы единственный пользователь этого репозитория, вы можете перезаписать историю , используя либо git filter-branch (как svick написал ), или git fast-export / git fast-import плюс скрипт фильтра (как описано в статье, указанной в docgnome answer ), или интерактивном перебазировать . Но любой из них изменит ревизии, начиная с первого измененного коммита; это означает проблемы для любого, кто основывал свои изменения на предварительной перезаписи вашей ветки.

ВОССТАНОВЛЕНИЕ

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

В качестве альтернативы они могут попробовать git rebase --pull , который будет перематывать вперед, если в их репозитории не было никаких изменений, или перенастроить свою ветку поверх перезаписанных коммитов (мы хотим, чтобы избегайте слияния, так как это навсегда сохранит коммиты до перезаписи). Все это при условии, что они не завершили работу; в противном случае используйте git stash , чтобы спрятать изменения.

Если другие разработчики используют ветки функций и / или git pull --rebase не работает, напримерпоскольку восходящий поток не настроен, они должны перебазировать свою работу поверх коммитов после перезаписи. Например, сразу после получения новых изменений ( git fetch ) для ветки master , основанной на / разветвленной от origin / master , необходимо запустить

$ git rebase --onto origin/master origin/master@{1} master

Здесь origin / master @ {1} - состояние предварительной перезаписи (до выборки), см. gitrevisions .


Альтернативным решением было бы использование механизма refs / replace / , доступного в Git начиная с версии 1.6.5. В этом решении вы предоставляете замену коммитам с неправильным адресом электронной почты; затем любой, кто получает «заменить» ссылки (что-то вроде fetch = + refs / replace / *: refs / replace / * refspec в соответствующем месте в их .git / config ) будут заменены прозрачно, и те, кто не получит эти ссылки, увидят старые коммиты.

Процедура выглядит примерно так:

  1. Найти все коммиты с неправильным адресом электронной почты, например, с помощью

     $ git log (скрыто) --all
    
  2. Для каждой неправильной фиксации создайте заменяющую фиксацию и добавьте ее в базу данных объектов

     $ git cat-file -p  |
    sed -e (скрытый)> tmp.txt
    $ git hash-object -t commit -w tmp.текст
    
    
  3. Теперь, когда вы исправили фиксацию в базе данных объектов, вы должны указать git автоматически и прозрачно заменить неправильную фиксацию исправленной с помощью команды git replace :

     $ git replace  
    
  4. Наконец, перечислите все замены, чтобы проверить, завершилась ли эта процедура

     $ git replace -l
    

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

     $ git log (скрыто) --all
    

Вы, конечно, можете автоматизировать эту процедуру ... ну, все, кроме использования git replace , в котором (пока) нет пакетного режима, поэтому вам придется использовать для этого цикл оболочки или заменить "рукой".

НЕ ПРОВЕРЯЛСЯ! YMMV.

Обратите внимание, что вы можете столкнуться с трудностями при использовании механизма refs / replace / : он новый и еще не очень хорошо протестирован .

9
ответ дан 22 November 2019 в 19:55
поделиться

Как упоминал docgnome, переписывать историю опасно и может сломать чужие репозитории.

Но если вы действительно хотите это сделать и находитесь в среде bash (в Linux это не проблема, в Windows вы можете использовать git bash, который поставляется с установкой git), используйте git filter-branch:

git filter-branch --env-filter '
  if [ $GIT_AUTHOR_EMAIL = bad@email ];
    then GIT_AUTHOR_EMAIL=correct@email;
  fi;
export GIT_AUTHOR_EMAIL'

Чтобы ускорить процесс, вы можете указать диапазон ревизий, которые вы хотите переписать:

git filter-branch --env-filter '
  if [ $GIT_AUTHOR_EMAIL = bad@email ];
    then GIT_AUTHOR_EMAIL=correct@email;
  fi;
export GIT_AUTHOR_EMAIL' HEAD~20..HEAD
80
ответ дан 22 November 2019 в 19:55
поделиться

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

На этой странице http://inputvalidation.blogspot.com/2008/08/how-to-change-git-commit-author.html описано, как это сделать. (Я не пробовал, так что YMMV)

2
ответ дан 22 November 2019 в 19:55
поделиться

Все ответы выше переписывают историю репозитория. Пока имя к изменению не использовалось несколькими авторами и особенно если бы репозиторий был совместно использован, и фиксация стара, я предпочел бы использовать .mailmap, зарегистрированный в https://git-scm.com/docs/git-shortlog. Это позволяет отображать неправильные имена/электронные письма к корректному, не изменяя repo историю. Можно использовать строки как:

Proper Name <proper@email.xx> <root@localhost>
1
ответ дан 22 November 2019 в 19:55
поделиться

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

От документация :

имя автора фиксации Изменения и электронная почта:

git-rocket-filter --branch TestBranch --commit-filter '
    if (commit.AuthorName.Contains("Jim")) {   
        commit.AuthorName = "Paul"; 
        commit.AuthorEmail = "paul@company.com"; 
    }
0
ответ дан 22 November 2019 в 19:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: