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

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

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

41 ответ

Решение

Смена автора (или коммиттера) потребует переписывания всей истории. Если вы согласны с этим и считаете, что оно того стоит, вам следует проверить 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

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

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

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, который сохранит структуру слияния вашей истории. Manpage для git rebase предупреждает, что с помощью -p а также -i может привести к проблемам, но в BUGS в разделе написано "Редактирование коммитов и переписывание их коммитов должны работать нормально".

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

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

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

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

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

Это происходит, когда у вас нет инициализированного $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

В случае, если только у немногих лучших коммитов есть плохие авторы, вы можете сделать все это внутри 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 за вдохновение.

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

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

(извлечено из ответа 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" = "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"
'

Предположим, вы хотите сменить автора за последние N коммитов:

git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit"

ЗАМЕТКИ

  • --no-edit флаг удостоверяется git commit --amend не требует дополнительного подтверждения
  • когда вы используете git rebase -i, вы можете вручную выбрать коммиты, где сменить автора,

файл, который вы редактируете, будет выглядеть так:

pick 897fe9e simplify code a little
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick dc18f70 bugfix
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit

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

Как уже упоминалось в 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

Я должен отметить, что если единственная проблема заключается в том, что автор / электронная почта отличается от вашего обычного, это не проблема. Правильным решением является создание файла с именем .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 change-commits GIT_AUTHOR_NAME "old name" "new name"

или за последние 10 коммитов:

git change-commits GIT_AUTHOR_EMAIL "old@email.com" "new@email.com" HEAD~10..HEAD

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

Надеюсь, это полезно.

Это более сложная версия версии @Brian:

Чтобы изменить автора и коммиттера, вы можете сделать это (с переносом строки в строке, что возможно в 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

Вы можете получить одну из этих ошибок:

  1. Временный каталог уже существует
  2. Ссылки, начинающиеся с ссылок / оригинал уже существует
    (это означает, что другая ветвь фильтра была ранее запущена в хранилище, и тогда исходная ссылка на ветку резервируется в refs / original)

Если вы хотите форсировать запуск, несмотря на эти ошибки, добавьте --force флаг:

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

Небольшое объяснение -- --all может потребоваться опция: она заставляет ветку фильтра работать на всех ревизиях на всех ссылках (включая все ветки). Это означает, например, что теги также переписаны и видны в переписанных ветвях.

Распространенной "ошибкой" является использование HEAD вместо этого это означает фильтрацию всех ревизий только на текущей ветви. И тогда в переписанной ветке не будет никаких тегов (или других ссылок).

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

git commit --amend --reset-author

Более безопасная альтернатива git's filter-branch является filter-repoинструмент, предложенный здесь git docs.

git filter-repo --commit-callback '

  old_email = b"your-old-email@example.com"
  correct_name = b"Your Correct Name"
  correct_email = b"your-correct-email@example.com"

  if commit.committer_email == old_email :
    commit.committer_name = correct_name
    commit.committer_email = correct_email

  if commit.author_email == old_email : 
    commit.author_name = correct_name
    commit.author_email = correct_email
  '

Приведенная выше команда отражает логику, используемую в этом скрипте, но используетfilter-repo вместо того filter-branch.

Тело кода после commit-callbackoption - это в основном код Python, используемый для обработки коммитов. Здесь вы можете написать свою собственную логику на Python. Узнать больше оcommitобъект и его атрибуты здесь.

поскольку filter-repo инструмент не входит в комплект с git, вам нужно установить его отдельно.

См. Предварительные требования и руководство по установке.

Если у вас есть python env >= 3.5, вы можете использовать pip установить его.

pip3 install git-filter-repo

Примечание. Настоятельно рекомендуется попробоватьfilter-repoинструмент на свежем клоне. Также пульты удаляются после завершения операции. Подробнее о том, почему удаляют пульты, читайте здесь. Также ознакомьтесь с ограничениями этого инструмента в разделе ВНУТРЕННЯЯ ИНФОРМАЦИЯ.

  1. бежать git rebase -i <sha1 or ref of starting point>
  2. отметить все коммиты, которые вы хотите изменить edit (или же e)
  3. Зациклите следующие две команды, пока не обработаете все коммиты:

    git commit --amend --reuse-message=HEAD --author="New Author <new@author.email>";git rebase --continue

Это сохранит всю остальную информацию о коммите (включая даты). --reuse-message=HEAD опция запрещает запуск редактора сообщений.

Я использую следующее, чтобы переписать автора для всего хранилища, включая теги и все ветви:

git filter-branch --tag-name-filter cat --env-filter "
  export GIT_AUTHOR_NAME='New name';
  export GIT_AUTHOR_EMAIL='New email'
" -- --all

Затем, как описано на странице MAN в filter-branch, удалите все оригинальные ссылки, сохраненные filter-branch (это разрушительно, сначала сделайте резервную копию):

git for-each-ref --format="%(refname)" refs/original/ | \
xargs -n 1 git update-ref -d

Я адаптировал это решение, которое работает, принимая простые author-conv-file (формат такой же, как и для git-cvsimport). Он работает путем изменения всех пользователей, как определено в author-conv-file по всем веткам.

Мы использовали это в сочетании с cvs2git перенести наш репозиторий из cvs в git.

т.е. образец author-conv-file

john=John Doe <john.doe@hotmail.com>
jill=Jill Doe <jill.doe@hotmail.com>

Сценарий:

 #!/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

Я нахожу представленные версии агрессивными, особенно если вы делаете патчи от других разработчиков, это по существу украдет их код.

Версия ниже работает на всех ветках и изменяет автора и комитера отдельно, чтобы предотвратить это.

Престижность к leif81 для всего варианта.

#!/bin/bash

git filter-branch --env-filter '
if [ "$GIT_AUTHOR_NAME" = "<old author>" ];
then
    GIT_AUTHOR_NAME="<new author>";
    GIT_AUTHOR_EMAIL="<youmail@somehost.ext>";
fi
if [ "$GIT_COMMITTER_NAME" = "<old committer>" ];
then
    GIT_COMMITTER_NAME="<new commiter>";
    GIT_COMMITTER_EMAIL="<youmail@somehost.ext>";
fi
' -- --all

Самый быстрый и простой способ сделать это - использовать аргумент --exec команды git rebase:

git rebase -i -p --exec 'git commit --amend --reset-author --no-edit'

Это создаст список задач, который выглядит следующим образом:

pick ef11092 Blah blah blah
exec git commit --amend --reset-author --no-edit
pick 52d6391 Blah bloh bloo
exec git commit --amend --reset-author --no-edit
pick 30ebbfe Blah bluh bleh
exec git commit --amend --reset-author --no-edit
...

и это будет работать все автоматически, что работает, когда у вас есть сотни коммитов.

  1. Изменить коммит author name & email от Amendзатем замена old-commit with new-one:

    $ git checkout <commit-hash>                            # checkout to the commit need to modify  
    $ git commit --amend --author "name <author@email.com>" # change the author name and email
    
    $ git replace <old-commit-hash> <new-commit-hash>      # replace the old commit by new one
    $ git filter-branch -- --all                           # rewrite all futures commits based on the replacement                   
    
    $ git replace -d <old-commit-hash>     # remove the replacement for cleanliness 
    $ git push -f origin HEAD              # force push 
    
  2. По-другому Rebasing:

    $ git rebase -i <good-commit-hash>      # back to last good commit
    
    # Editor would open, replace 'pick' with 'edit' before the commit want to change author
    
    $ git commit --amend --author="author name <author@email.com>"  # change the author name & email
    
    # Save changes and exit the editor
    
    $ git rebase --continue                # finish the rebase
    

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

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

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

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

Если другие разработчики используют функциональные ветви и / или git pull --rebase не работает, например, потому что upstream не настроен, они должны перебазировать свою работу поверх коммитов после перезаписи. Например, сразу после получения новых изменений (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 --author=user@wrong.email --all
    
  2. Для каждого неправильного коммита создайте коммит замены и добавьте его в базу данных объекта.

    $ git cat-file -p <ID of wrong commit> | 
      sed -e 's/user@wrong\.email/user@example.com/g' > tmp.txt
    $ git hash-object -t commit -w tmp.txt
    <ID of corrected commit>
    
  3. Теперь, когда вы исправили коммит в объектной базе данных, вы должны указать git автоматически и прозрачно заменить неправильный коммит на исправленный, используя git replace команда:

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

    $ git replace -l
    

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

    $ git log --author=user@wrong.email --all
    

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

НЕ ИСПЫТАНО! YMMV.

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

Обратите внимание, что git хранит два разных адреса электронной почты: один для коммиттера (человека, который внес изменение), а другой для автора (человека, который написал изменение).

Информация о коммитере не отображается в большинстве мест, но вы можете увидеть ее с помощью git log -1 --format=%cn,%ce (или использовать show вместо log указать конкретный коммит).

Менять автора вашего последнего коммита так же просто, как git commit --amend --author "Author Name <email@example.com>", нет единой строки или аргумента, чтобы сделать то же самое с информацией о коммитере.

Решение состоит в том, чтобы (временно или нет) изменить вашу пользовательскую информацию, а затем изменить коммит, который обновит коммиттера до вашей текущей информации:

git config user.email my_other_email@example.com 
git commit --amend

Для сброса ВСЕХ коммитов (включая первый коммит) для текущего пользователя и текущей метки времени:

      git rebase --root --exec "git commit --amend --no-edit --date 'now' --reset-author"

Если коммиты, которые вы хотите исправить, являются самыми последними, и только пара из них, вы можете использовать комбинацию git reset а также git stash чтобы вернуть их снова после настройки правильного имени и адреса электронной почты.

Последовательность будет выглядеть примерно так (для 2-х неправильных коммитов нет ожидающих изменений):

git config user.name <good name>
git config user.email <good email>
git reset HEAD^
git stash
git reset HEAD^
git commit -a
git stash pop
git commit -a

Однострочный сfilter-repo:

Вы можете использовать функцию обратного вызоваgit-filter-repo(рекомендуемая замена для ), чтобы изменить имя и адрес электронной почты, связанные со всеми коммитами:

      git filter-repo --name-callback 'return b"New Name"' --email-callback 'return b"newemail@gmail.com"'

Это более производительно и потенциально более надежно, чем решения, использующиеfilter-branch.

Обратите внимание, что приведенная выше команда изменяет авторов (и коммиттеров) всех коммитов, если вы хотите эффективно «редактировать» определенного автора и изменять коммиты только этого конкретного автора, используйте команду--commit-callbackтакой вариант:

      git filter-repo --commit-callback '
old_email = b"oldemail@gmail.com"
new_email = b"newemail@gmail.com"
new_name = b"New Author"

if commit.author_email == old_email:
    commit.author_email = new_email
    commit.author_name = new_name

if commit.committer_email == old_email:
    commit.committer_email = new_email
    commit.committer_name = new_name
'

(Просто изменитеold_email,new_email, иnew_nameпеременные в приведенной выше команде к правильным значениям.)

Используя интерактивную перебазировку, вы можете поместить команду исправления после каждого коммита, который вы хотите изменить. Например:

pick a07cb86 Project tile template with full details and styling
x git commit --amend --reset-author -Chead

Ваша проблема действительно распространена. Смотрите " Использование Mailmap для исправления списка авторов в Git"

Для простоты я создал скрипт для облегчения процесса: git-changemail

Поместив этот скрипт в свой путь, вы можете выполнить такие команды, как:

  • Изменить совпадения авторов в текущей ветке

    $ git changemail -a old@email.com -n newname -m new@email.com
    
  • Измените совпадения авторов и коммиттеров для и . Проходить -f в фильтр-ветку, чтобы разрешить перезапись резервных копий

    $ git changemail -b old@email.com -n newname -m new@email.com -- -f &lt;branch> &lt;branch2>
    
  • Показать существующих пользователей в репо

    $ git changemail --show-both
    

Кстати, после внесения изменений очистите резервную копию из ветви фильтра с помощью: git-backup-clean

Сегодня мы столкнулись с проблемой, когда символ UTF8 в имени автора вызывал проблемы на сервере сборки, поэтому нам пришлось переписать историю, чтобы исправить это. Предпринятые шаги:

Шаг 1: Измените свое имя пользователя в git для всех будущих коммитов, следуя инструкциям здесь: https://help.github.com/articles/setting-your-username-in-git/

Шаг 2: Запустите следующий скрипт bash:

#!/bin/sh

REPO_URL=ssh://path/to/your.git
REPO_DIR=rewrite.tmp

# Clone the repository
git clone ${REPO_URL} ${REPO_DIR}

# Change to the cloned repository
cd ${REPO_DIR}

# Checkout all the remote branches as local tracking branches
git branch --list -r origin/* | cut -c10- | xargs -n1 git checkout

# Rewrite the history, use a system that will preseve the eol (or lack of in commit messages) - preferably Linux not OSX
git filter-branch --env-filter '
OLD_EMAIL="me@something.com"
CORRECT_NAME="New Me"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
fi
' --tag-name-filter cat -- --branches --tags

# Force push the rewritten branches + tags to the remote
git push -f

# Remove all knowledge that we did something
rm -rf ${REPO_DIR}

# Tell your colleagues to `git pull --rebase` on all their local remote tracking branches

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

У нас были проблемы с запуском этого на OS X, потому что он как-то испортил окончания строк в сообщениях коммитов, поэтому нам пришлось потом перезапускать его на машине Linux.

Если вы используете Eclipse с EGit, то есть довольно простое решение.
Предположение: у вас есть коммиты в локальной ветке 'local_master_user_x', которую нельзя отправить в удаленную ветку 'master' из-за недопустимого пользователя.

  1. Оформить заказ на удаленную ветку "Мастер"
  2. Выберите проекты / папки / файлы, для которых "local_master_user_x" содержит изменения
  3. Щелкните правой кнопкой мыши - Замените на - Ветвь - 'local_master_user_x'
  4. Передайте эти изменения снова, на этот раз как правильный пользователь и в локальную ветку 'master'
  5. Нажмите на удаленный "мастер"
Другие вопросы по тегам