Я писал простой скрипт на школьном компьютере и фиксировал изменения в Git (в репозитории, который находился на моем pendrive, клонированном с моего домашнего компьютера). После нескольких фиксаций я понял, что фиксирую изменения как пользователь root.
Есть ли способ изменить автора этих коммитов на мое имя?
Вы могли бы сделать
git rebase -i -p <some HEAD before all of your bad commits>
Затем Марк все свои плохие совершает как "редактировать" в перебазировать файл. Если вы также хотите изменить свой первый коммит, вы должны вручную добавить его в качестве первой линии в переместить файл (формат других линий). Потом, когда ГИТ просит вас внести изменения каждого коммита, сделать
git commit --amend --author "New Author Name <[email protected]>"
редактировать или просто закрыть редактор, который открывает, а потом делать
git rebase --continue
продолжить перебазироваться.
Вы могли бы пропускать отверстия здесь редакторе, добавляя - нет-редактирование
так что команда будет:
git commit --amend --author "New Author Name <[email protected]>" --no-edit && \
git rebase --continue
Как некоторые комментаторы уже отметили, если вы просто хотите изменить последней фиксации, команда перебазироваться не надо. Вобще
git commit --amend --author "New Author Name <[email protected]>"
Это позволит изменить автора на имя, указанное, но комиссия будет установлена на ваш настроенного пользователя в ГИТ конфигурации пользователя.имяи
Git для пользователей конфигурации.электронной почты`. Если вы хотите установить коммиттер на что-то указать, это позволит установить автора и исполнителя:
git -c user.name="New Author Name" -c [email protected] commit --amend --reset-author
Был небольшой изъян в мой оригинальный ответ. Если есть какие-то коммитов слияния между текущим голова
и свой <некоторые головы, прежде чем все ваши плохие совершает>
, затем Git для перебазирования
будет расплющить (и кстати, если вы используете GitHub запросы тянуть, там будет куча коммитов слияния в вашей истории). Это может очень часто привести к очень разную историю (как повторяющиеся изменения могут быть "перебазированы из"), и в худшем случае, это может привести к Git для перебазирования
прошу Вас разрешить сложные конфликты слияния (которые скорее всего уже решен в коммитов слияния). Решение: использовать флаг -п
в Git для перебазирования
, которая позволит сохранить структуру слияния вашей истории. На странице справочника Git для перебазирования
предупреждает, что, используя -P
и я
может привести к проблемам, но в разделе баги
он пишет "редактирования коммитов и переформулировать их сообщения должны нормально работать&.и"
Я'вэ добавил -п
В приведенной выше команде. Для случая, когда вы're просто изменение самой последней фиксации, это не проблема.
Изменение автора (или коммиттера) потребует переписывания всей истории. Если вы не против этого и считаете, что это того стоит, то вам стоит ознакомиться с git filter-branch. На странице man есть несколько примеров для начала работы. Также обратите внимание, что вы можете использовать переменные окружения для изменения имени автора, коммиттера, даты и т.д. -- см. раздел "Переменные окружения" на странице git man page.
В частности, вы можете исправить все неправильные имена авторов и электронные адреса для всех веток и тегов с помощью этой команды (источник: GitHub help):
#!/bin/sh
git filter-branch --env-filter '
OLD_EMAIL="[email protected]"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="[email protected]"
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
Вы также можете:
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
Один лайнер, но будьте осторожны, если у вас многопользовательский репозиторий - это изменит все коммиты, чтобы они имели одного и того же (нового) автора и коммиттера.
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
Это происходит, когда у вас нет $дома/.gitconfig хранит настройки инициализации. Вы можете исправить это:
git config --global user.name "you name"
git config --global user.email [email protected]
git commit --amend --reset-author
протестировано с версий Git 1.7.5.4
На один коммит:
git commit --amend --author="Author Name <[email protected]>"
(извлечено из asmeurer'ы ответ)
В том случае, когда только несколько топ совершает плохие авторы, Вы можете выполнить Git это все внутри перебазировать -я
с помощью команды метод Exec
и `--изменить-дерзайте, следующим образом:
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 ... --автор=" от..."
в строках после всех строк с плохой авторов:
pick abcd Someone else's commit
pick defg my bad commit 1
exec git commit --amend --author="New Author Name <[email protected]>" -C HEAD
pick 1234 my bad commit 2
exec git commit --amend --author="New Author Name <[email protected]>" -C HEAD
сохраните и выйдите из редактора (для запуска).
Такое решение может быть дольше, чем некоторые другие, но это'ы очень управляема - я точно знаю, что совершает его хиты.
Спасибо @asmeurer для вдохновения.
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" = "[email protected]" ]
then
cn="Your New Committer Name"
cm="Your New Committer Email"
fi
if [ "$GIT_AUTHOR_EMAIL" = "[email protected]" ]
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"
'
Как docgnome отметил, переписывание истории-это опасно и будут ломать других людей'с репозиториев.
Но если вы действительно хотите сделать это, и вы находитесь в bash среды (никаких проблем в Linux, в Windows, вы можете использовать git Баш, который предоставляется при установке ЖКТ), использовать в Git фильтр-ветвь:
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
Вы можете использовать это в качестве псевдоним так что вы можете сделать:
git change-commits GIT_AUTHOR_NAME "old name" "new name"
или за последние 10 коммитов:
git change-commits GIT_AUTHOR_EMAIL "[email protected]" "[email protected]" HEAD~10..HEAD
Добавить в ~/.gitconfig хранит настройки:
[alias]
change-commits = "!f() { VAR=$1; OLD=$2; NEW=$3; shift 3; git filter-branch --env-filter \"if [[ \\\"$`echo $VAR`\\\" = '$OLD' ]]; then export $VAR='$NEW'; fi\" $@; }; f "
Источник: https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig
Надеюсь, что это полезно.
Это более разработанная версия @Брайан's версии:
Чтобы изменить автором и коммитером, вы можете сделать это (с разрывом строк в строки, которые можно в bash):
git filter-branch --env-filter '
if [ "$GIT_COMMITTER_NAME" = "<Old name>" ];
then
GIT_COMMITTER_NAME="<New name>";
GIT_COMMITTER_EMAIL="<New email>";
GIT_AUTHOR_NAME="<New name>";
GIT_AUTHOR_EMAIL="<New email>";
fi' -- --all
Вы можете сделать одну из этих ошибок:
Если вы хотите заставить работать несмотря на эти ошибки, добавить - сила
флаг:
git filter-branch --force --env-filter '
if [ "$GIT_COMMITTER_NAME" = "<Old name>" ];
then
GIT_COMMITTER_NAME="<New name>";
GIT_COMMITTER_EMAIL="<New email>";
GIT_AUTHOR_NAME="<New name>";
GIT_AUTHOR_EMAIL="<New email>";
fi' -- --all
Небольшое пояснение `-- --все может быть нужно: это делает фильтр-филиала работать на всех редакций на все рефы (включая все филиалы). Это означает, например, что теги-это также переписан и видна на переписать филиалы.
В общем-то "ошибку" это использовать голова
, что означает фильтрацию всех редакций на просто ветки. И тогда никакие теги (или другие ссылки) будет существовать в измененном филиала.
git перебазирования -я <SHA1 или Реф отправная точка>
в Git коммит --изменения --повторное использование-сообщение=глава --автор="по-новому автор <[email protected]>"
в
;
`Git для перебазирования --продолжить
Это будет держать все другие фиксации информации (включая даты). В `--повторное использование-сообщения параметр=голова мешает редактора сообщений от запуска.
Я использую следующие действия, чтобы переписать автора для всего репозитория, включая теги и все филиалы:
git filter-branch --tag-name-filter cat --env-filter "
export GIT_AUTHOR_NAME='New name';
export GIT_AUTHOR_EMAIL='New email'
" -- --all
Затем, как описано в man-страницы фильтра-филиала, Все ссылки подкрепленные фильтр-филиал
(это губительный, сначала сделайте резервную копию):
git for-each-ref --format="%(refname)" refs/original/ | \
xargs -n 1 git update-ref -d
Я адаптировал это решение, которая работает путем проглатывания простой автор-сопу-файл (формат тот же, что и для с Git-cvsimport). Она работает путем изменения всех пользователей, как определено в `автор-сопу-файл по всем отраслям.
Мы использовали это в сочетании с cvs2git
чтобы перенести наш репозиторий с CVS на Git.
т. е. образец автор-сопу-файл
john=John Doe <[email protected]>
jill=Jill Doe <[email protected]>
Сценарий:
#!/bin/bash
export $authors_file=author-conv-file
git filter-branch -f --env-filter '
get_name () {
grep "^$1=" "$authors_file" |
sed "s/^.*=\(.*\) <.*>$/\1/"
}
get_email () {
grep "^$1=" "$authors_file" |
sed "s/^.*=.* <\(.*\)>$/\1/"
}
GIT_AUTHOR_NAME=$(get_name $GIT_COMMITTER_NAME) &&
GIT_AUTHOR_EMAIL=$(get_email $GIT_COMMITTER_NAME) &&
GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME &&
GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL &&
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
' -- --all
А одна команда изменить автора за последние N коммитов:
git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <[email protected]>' --no-edit"
Примечания
--no-изменить флаг
гарантирует в Git коммит --изменить
не'т задать дополнительные подтвержденияфайл редактирования будет выглядеть следующим образом:
pick 897fe9e simplify code a little
exec git commit --amend --author 'Author Name <[email protected]>' --no-edit
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <[email protected]>' --no-edit
pick dc18f70 bugfix
exec git commit --amend --author 'Author Name <[email protected]>' --no-edit
Тогда еще можно изменить несколько строк, чтобы увидеть, где вы хотите изменить автора. Это дает вам отличное компромиссное решение между автоматика и управление: вы видите действия, которые будут выполняться и после того, как вы сохраните все будут применены одновременно.
Я обнаружил, представлены версии как для агрессивной, особенно если вы совершаете патчи от других разработчиков, эта, по сути, украсть их код.
Ниже версия работает на все ветви и изменения, автор и comitter отдельно, чтобы предотвратить это.
Престижность leif81 для всех вариант.
#!/bin/bash
git filter-branch --env-filter '
if [ "$GIT_AUTHOR_NAME" = "<old author>" ];
then
GIT_AUTHOR_NAME="<new author>";
GIT_AUTHOR_EMAIL="<[email protected]>";
fi
if [ "$GIT_COMMITTER_NAME" = "<old committer>" ];
then
GIT_COMMITTER_NAME="<new commiter>";
GIT_COMMITTER_EMAIL="<[email protected]>";
fi
' -- --all
; по электронной почте
по изменить
, то замена старого фиксации с новыми-один`: ГИТ кассе $ <фиксации хэш - > # извлечение для фиксации нужно изменить $ коммитов --изменения --автор "имя [email protected]" и # изменить имя автора и адрес электронной почты
$ git будет заменить на <старая фиксации-хэш> <новое фиксации-хэш> # заменить старый коммит новый фильтр-филиала $ ЖКТ -- --все # переписать все фьючерсы совершает на основе замены
$ Git на замену -д <старая фиксации-хэш> # снимите замена для чистоты $ Git с пуш-Ф происхождения глава # толчок силы
перебазировка
:$ Git для перебазирования -я <хорошей фиксации-хэш> # вернуться к последней удачной фиксации
$ коммитов --изменить --автор="у автора имя [email protected]" и # изменить имя автора & электронная почта
$ Git для перебазирования --продолжение # закончить перебазироваться
Я должен отметить, что если проблема только в том, что автор/электронной почты отличается от обычного, это не проблема. Правильным решением является создание файл с названием `.mailmap на базе каталога с линиями как
Name you want <email you want> Name you don't want <email you don't want>
И с тех пор, команды, как в Git shortlog
будут считать, что эти два имени должны быть одинаковы (если вы конкретно скажите им, чтобы не). См http://schacon.github.com/git/git-shortlog.html для получения дополнительной информации.
Это имеет то преимущество, что все другие решения здесь в том, что вы Дон'т иметь, чтобы переписать историю, которая может вызвать проблемы, если у вас есть выше по течению, и это всегда хороший способ, чтобы случайно не потерять данные.
Конечно, если вы совершили что-то, как самого себя, и это должно быть что-то еще, и вы не'т ум переписывание истории в этой точке, изменяя совершить автор, наверное, хорошая идея для атрибуции целей (в этом случае я вам прям мой другой ответ здесь).
Если вы являетесь единственным пользователем этого репозитория, вы можете переписать историю используя [в Git фильтр-ветвь
][в Git фильтр-ветвь] (как svick писал), или ГИТ фаст-экспорт
/ГИТ фаст-импорт
плюс фильтр скрипт (как описано в статье, на которую ссылается в docgnome ответить), или интерактивные смещение. Но ни один из этих бы изменить ревизии из первых изменил совершить года; это означает, проблема для кого что на основе его/ее изменения на вашей ветке предварительно переписать.
Восстановление
Если другие разработчики не'т основывают свою работу на предварительно переписать версию, простейшим решением было бы заново-клон (опять же клон).
В качестве альтернативы они могут попробовать ГИТ тянуть --перебазировать, которые бы вперед, если бы'т-либо изменения в свой репозиторий, или перебазировать свои ветви поверх переписать совершает (мы хотим избежать слияния, так как он будет держать предварительно переписать comits навсегда). Все это при условии, что они не имеют не поручено работать; используйте заначка ГИТ
, чтобы спрятать изменения в противном случае.
Если другие разработчики используют функцию филиалы, и/или ГИТ тянуть --перебазировать
не'т работу, например, потому что против течения не установлено, что они [перебазировка][в git-rebase и] свою работу на пост-переписать совершает. Например, сразу после извлечения новых изменений (Git для выборки
), на мастер-ветке основе / раздвоенной от происхождения/мастер
, один должен работать
$ git rebase --onto origin/master origin/master@{1} master
Здесь происхождения/мастер@{1}
предварительно переписать государства (до выборки), см. gitrevisions.
Альтернативным решением могло бы быть использование рефов/заменить/ механизм доступен в Git начиная с версии 1.6.5. В этом решении вам выдадут дубликат для коммиты, которые имеют неправильный электронный адрес; затем, кто выбирает 'заменить' ссылки (что-то вроде выборка = +рефы/заменить/*:рефы/заменить/*
refspec в соответствующем месте в их .в git/config файл
) будет сделать замены прозрачно, и те, кто не извлечет эти рефов увидеть старых коммитов.
Процедура проходит примерно так:
$ ГИТ лог [email protected] -все
$ ЖКТ кота-файл -Р <идентификатор неверной фиксации> | СЭД -э 's/[email protected]/[email protected]/g' > tmp.txt $ Git с хэш-объект -Т совершить -з tmp.txt <код исправлены фиксации>
заменить на Git
команда:ЖКТ $ заменить на <идентификатор неверной фиксации> <идентификатор исправлены фиксации>
$ Git на замену -л
и проверить, если замены происходят
$ ГИТ лог [email protected] -все
Можно конечно автоматизировать эту процедуру... ну, все, кроме, используя ГИТ заменить
, который не'т иметь (еще) пакетном режиме, так что вам придется использовать Shell петля Для то или замены "под рукой".
НЕ ПРОВЕРЯЛ! YMMV.
<суп>обратите внимание, что вы можете столкнуться с некоторыми грубых углов при использовании ссылок/заменить механизм/`: он новый, и еще не очень хорошо проверены на</SUP-серфинг>.