Как изменить автора, имя коммиттера и адрес электронной почты нескольких коммитов в Git? - PullRequest
2179 голосов
/ 15 апреля 2009

Я писал простой сценарий на школьном компьютере и вносил изменения в Git (в репозитории, который был в моем pendrive, клонирован с моего компьютера дома). После нескольких коммитов я понял, что коммитирую, как пользователь root.

Есть ли способ изменить автора этих коммитов на мое имя?

Ответы [ 32 ]

1495 голосов
/ 24 августа 2009

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

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

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

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

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

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

git rebase --continue

для продолжения перебазирования.

Вы можете вообще пропустить открытие редактора, добавив --no-edit так что команда будет:

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 и вашим <some HEAD before all your bad commits>, то git rebase сгладит их (и, между прочим, если вы используете GitHub pull-запросы, в вашем комитете слияния будет тонна коммитов история). Это может очень часто приводить к очень разной истории (поскольку повторяющиеся изменения могут быть «перебазированы»), и в худшем случае это может привести к git rebase, требующему разрешения сложных конфликтов слияния (которые, вероятно, уже были разрешены при слиянии совершает). Решение заключается в использовании флага -p для git rebase, который сохранит структуру слияния вашей истории. Страница man для git rebase предупреждает, что использование -p и -i может привести к проблемам, но в разделе BUGS написано "Редактирование коммитов и переписывание их сообщений коммитов должно работать нормально."

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

991 голосов
/ 15 апреля 2009

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

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

#!/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
578 голосов
/ 15 мая 2009

Вы также можете сделать:

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
514 голосов
/ 15 апреля 2009

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

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
212 голосов
/ 16 февраля 2012

Это происходит, когда у вас нет инициализированного $ HOME / .gitconfig. Вы можете исправить это как:

git config --global user.name "you name"
git config --global user.email you@domain.com
git commit --amend --reset-author

протестировано с git версии 1.7.5.4

181 голосов
/ 27 апреля 2010

Для одного коммита:

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

(извлечено из ответа asmeurer)

167 голосов
/ 08 декабря 2011

В случае, если только у нескольких верхних коммитов есть плохие авторы, вы можете сделать все это внутри git rebase -i, используя команду exec и --amend, как указано ниже:

git rebase -i HEAD~6 # as required

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

pick abcd Someone else's commit
pick defg my bad commit 1
pick 1234 my bad commit 2

Затем добавьте exec ... --author="..." строк после всех строк с плохими авторами:

pick abcd Someone else's commit
pick defg my bad commit 1
exec git commit --amend --author="New Author Name <email@address.com>" -C HEAD
pick 1234 my bad commit 2
exec git commit --amend --author="New Author Name <email@address.com>" -C HEAD

сохранить и выйти из редактора (для запуска).

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

Спасибо @asmeurer за вдохновение.

108 голосов
/ 07 октября 2010

Github имеет хорошее решение , которое представляет собой следующий сценарий оболочки:

#!/bin/sh

git filter-branch --env-filter '

an="$GIT_AUTHOR_NAME"
am="$GIT_AUTHOR_EMAIL"
cn="$GIT_COMMITTER_NAME"
cm="$GIT_COMMITTER_EMAIL"

if [ "$GIT_COMMITTER_EMAIL" = "your@email.to.match" ]
then
    cn="Your New Committer Name"
    cm="Your New Committer Email"
fi
if [ "$GIT_AUTHOR_EMAIL" = "your@email.to.match" ]
then
    an="Your New Author Name"
    am="Your New Author Email"
fi

export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'
80 голосов
/ 04 августа 2010

Как уже упоминалось в docgnome, переписывание истории опасно и нарушит работу репозиториев других людей.

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

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
47 голосов
/ 24 марта 2016

Принимая непогруженный коммит от другого автора, есть простой способ справиться с этим.

git commit --amend --reset-author

...