Как да смените името и имейла на автор и имейл на няколко комисии в Git?

Написах обикновен компютърен скрипт в училище и направих промени в Git (в репото, което беше в моя pendrive клониран от моя компютър у дома). След няколко ангажимента осъзнах, че правя неща като потребител на root.

Има ли начин да промените автора на тези ангажименти към моето име?

2100
15 апр. попита от Flávio Amieiro 15 април 2009-04-15 06:09 '09 в 6:09 2009-04-15 06:09
@ 32 отговора
  • 1
  • 2

Промяната на автора (или изпълнител) ще изисква презапис на цялата история. Ако сте добре с това и смятате, че си струва, трябва да проверите git filter-branch . Страницата с ръководството съдържа няколко примера за започване. Също така имайте предвид, че можете да използвате променливите на обкръжението, за да промените името на автора, изпълнителя, датите и т.н. - вижте секцията "Променливи на околната среда" на git man .

По-специално, можете да коригирате всички неправилни имена на автори и имейли за всички клонове и маркери, като използвате тази команда (източник: помощ за GitHub ):

887
15 апр. Отговор, даден от Пат Нот на 15 април 2009-04-15 06:16 '09 в 6:16 AM 2009-04-15 06:16

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

Можете да го направите

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

След това маркирайте всичките си грешки като "редактиране" в файла rebase. Ако искате да промените първия си ангажимент, трябва ръчно да го добавите към първия ред в файла rebase (следвайте формата на другите редове). След това, когато git ви моли да промените всяко поемане, направете

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

Единична фиксация

Както отбелязват някои коментатори, ако просто искате да промените последното фиксиране, командата rebase не е необходима. Просто направи

  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 <some HEAD before all your bad commits> , тогава git rebase ще ги изглади (и, между другото, ако използвате GitHub заявки в историята си). Това много често може да доведе до съвсем различна история (тъй като дублиращите се промени могат да бъдат "преинсталирани"), а в най-лошия случай това може да доведе до git rebase молба да разрешите сложни конфликти за сливане (които вероятно вече са били разрешени в сливането). ). Решението е да се използва флаг -p за git rebase , което ще запази сливащата се структура на вашата история. git rebase предупреждава, че използването на -p и -i може да доведе до проблеми, но в секцията BUGS казва: "Редактирането се извършва и пренаписването на съобщенията им за поемане трябва да работи добре."

Добавих -p към горната команда. За случая, когато просто променяте последното съобщение, това не е проблем.

1465
24 авг. отговор, даден asmeurer 24 aug. 2009-08-24 06:08 '09 в 6:08 am 2009-08-24 06:08

Можете също така да направите:

 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 
573
15 мая '09 в 22:15 2009-05-15 22:15 отговорът е даден от Rognon на 15 май 2009 г. в 22:15 ч. 2009-05-15 22:15

Едно вмъкване, но внимавайте, ако имате многопотребителско хранилище - това ще промени всички фиксации за присъствието на един и същ (нов) автор и изпълнител.

 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):

501
15 апр. Отговор, даден от Брайън Джанфоркаро на 15 април 2009-04-15 06:22 '09 в 6:22 am 2009-04-15 06:22

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

209
16 февр. отговорът е даден lrkwz 16 февруари. 2012-02-16 12:46 '12 в 12:46 2012-02-16 12:46

За едно поправяне:

181
27 апр. отговорът е даден blueyed 27 апр. 2010-04-27 01:50 '10 в 1:50 2010-04-27 01:50

В случай, че само най-малките постъпления имат лоши автори, можете да го направите във вътрешността на git rebase -i като използвате командата exec и фиксирането - --amend както следва:

 git rebase -i HEAD~6 # as required 

който ви предоставя списък с корекции, които могат да се редактират:

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

След това добавете exec ... --author="..." линии exec ... --author="..." след всички редове с лоши автори:

 pick abcd Someone else 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 за вдъхновение.

159
08 дек. отговорът е даден от Алекс Браун 08 декември. 2011-12-08 20:05 '11 в 20:05 2011-12-08 20:05

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

108
07 окт. Отговорът е даден от Оливие Вердиер 07 октомври 2010-10-07 12:54 '10 в 12:54 2010-10-07 12:54

Както беше споменато по-горе, пренаписването на историята е опасно и ще унищожи хранилищата на други хора.

Но ако наистина искате да направите това, а вие сте в bash среда (няма проблем в Linux, в Windows можете да използвате git bash, който идва с инсталацията git), използвайте git филтър клон :

 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
04 авг. отговорът е даден от svick 04 aug. 2010-08-04 03:52 '10 в 3:52 2010-08-04 03:52

При заснемане на неподготвен ангажимент от друг автор, има лесен начин да се справите с това.

git commit --amend --reset-author

46
24 марта '16 в 1:23 2016-03-24 01:23 отговорът е даден от Райънт на 24 март 2011 г. в 1:23 2016-03-24 01:23

Това е по-внимателна версия на версията на @Brian:

За да промените автора и изпълнителя, можете да направите това (като използвате редове в низ, който е възможен в bash):

 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 вместо това, което означава филтриране на всички ревизии само за текущия клон. И тогава в пренаписана нишка няма да има тагове (или други връзки).

38
09 дек. отговорът е даден стигк 09 декември. 2011-12-09 13:23 '11 в 13:23 2011-12-09 13:23

Можете да го използвате като псевдоним, така че можете да го направите:

 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 

Добавяне към ~ / .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

Надявам се, че това е полезно.

38
02 авг. отговорът е даден на brauliobo 02 aug. 2012-08-02 02:09 '12 в 2:09 2012-08-02 02:09
  • стартирайте git rebase -i <sha1 or ref of starting point>
  • маркирайте всички ангажименти, които искате да редактирате с edit (или e )
  • изпълни следните две команди, докато не се справиш с всички команди:

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

Това ще запази всички останали данни за фиксиране (включително датите). Опцията --reuse-message=HEAD забранява стартирането на редактора на съобщения.

23
04 окт. отговор е даден sporsh 04 oct. 2012-10-04 05:22 '12 в 5:22 am 2012-10-04 05:22

Използвам следното за пренаписване на автора за цялото хранилище, включително етикети и всички клонове:

MAN страницата на клона за филтриране , изтрийте всички оригинални рефери, направени под резервни копия на filter-branch (това е разрушително, първо резервно копие): 

21
16 февр. Отговорът е даден Ton van den Heuvel 16 Feb. 2011-02-16 18:27 '11 в 18:27 2011-02-16 18:27

Адаптирах това решение , което работи чрез поглъщане на прост 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> 

скрипт:

20
05 февр. отговор, даден от Leif Gruenwoldt 05 Feb. 2011-02-05 01:46 '11 в 1:46 2011-02-05 01:46

Намерих представените версии на пътя агресивни, особено ако правите корекции от други разработчици, това по същество краде техния код.

Следващата версия работи във всички клонове и променя поотделно автора и изпълнителя, за да предотврати това.

Претенции към leif81 за всички опции.

18
23 апр. отговор, даден drahnr 23 апр 2012-04-23 11:46 '12 в 11:46 2012-04-23 11:46
  • Променете author name email на author name email Amend към „ 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 
  • Друг начин за 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 
17
14 дек. Саджиб Хан отговори на 14 декември. 2016-12-14 18:01 '16 в 18:01 2016-12-14 18:01

Трябва да отбележа, че ако единственият проблем е, че авторът / електронната поща е различен от обичайния ви, това не е проблем. Правилната корекция е да се създаде файл с име .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 .

Това е предимството на всички други решения тук, че не е нужно да пренаписвате историята, което може да предизвика проблеми, ако имате нагоре, и винаги е добър начин да загубите данни случайно.

Разбира се, ако сте направили нещо подобно на себе си, и то наистина трябва да бъде някой друг, и нямате нищо против да пренапишете историята за момента, промяната на автора на корекцията вероятно е добра идея за целите на приписването (в този случай аз ви изпращам на другия ми отговор тук).

15
29 февр. отговорът е даден asmeurer на 29 февруари 2012-02-29 02:57 '12 в 2:57 2012-02-29 02:57

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

ВЪЗСТАНОВЯВАНЕ

Ако други разработчици не са базирали работата си върху предварителната версия, най-лесното решение е да се клонира отново (повторно клониране).

Като алтернатива, те могат да опитат 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 / mechanism, наличен в Git от версия 1.6.5. В това решение предоставяте замествания за коммити с грешен имейл адрес; тогава някой, който вземе "ref" (нещо като fetch = +refs/replace/*:refs/replace/* refspec на подходящото място в техния .git/config ) ще получи замените прозрачно и тези, които не извлича тези връзки ще видите стари ангажименти.

Процедурата изглежда така:

  • Намиране на всички се извършва с грешен имейл адрес, например чрез използване

     $ git log --author=user@wrong.email --all 
  • За всяко погрешно коммитиране създайте заместващ финал и го добавете към базата данни на обектите.

     $ 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> 
  • Сега, след като сте коригирали ангажимента в базата данни на обектите, трябва да укажете Git автоматично и прозрачно да замени грешното въвеждане, коригирано с git replace :

     $ git replace <ID of wrong commit> <ID of corrected commit> 
  • Накрая избройте цялата подмяна, за да проверите дали тази процедура е изпълнена.

     $ git replace -l 

    и проверете дали има замяна

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

Можете, разбира се, да автоматизирате тази процедура ... е, всичко, с изключение на използването на git replace , която няма (досега) пакетния режим, така че трябва да използвате обвивка на обвивката или да я замените ръчно.

НЕ ФИКСИРАН! YMMV.

Имайте предвид, че при използване на refs/replace/ mechanism може да срещнете някои груби ъгли: тя е нова и все още не е добре тествана .

9
04 авг. отговор, даден от Jakub Narębski 04 авг. 2010-08-04 12:41 '10 в 12:41 2010-08-04 12:41

Ако фиксирането, което искате да поправите, е последно и само няколко от тях, можете да използвате 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 
6
30 сент. Отговор, даден от djromero Sep 30 2011-09-30 21:04 '11 в 21:04 2011-09-30 21:04

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

 pick a07cb86 Project tile template with full details and styling x git commit --amend --reset-author -Chead 
5
26 февр. отговорът е даден на 26 февруари. 2013-02-26 16:19 '13 в 16:19 2013-02-26 16:19

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

Информацията за git log -1 --format=%cn,%ce не се показва на повечето места, но можете да я видите с git log -1 --format=%cn,%ce (или използвайте show вместо log да посочите конкретен ангажимент).

Промяната на автора на последния ви git commit --amend --author "Author Name <email@example.com>" е толкова лесна, колкото и git commit --amend --author "Author Name <email@example.com>" , няма един ред или аргумент, които да направят същото с информацията за членовете.

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

 git config user.email my_other_email@example.com git commit --amend 
5
06 дек. Отговор, даден от сър Атон 06 декември 2013-12-06 00:21 '13 в 0:21 2013-12-06 00:21

Ако използвате Eclipse с EGit, тогава има доста просто решение.
Предполагам: направихте грешка в локалния клон local_master_user_x, който не може да бъде прехвърлен на "master" на отдалечения клон поради невалиден потребител.

  • Разгледайте отдалечения клон "master"
  • Изберете проекти / папки / файлове, за които local_master_user_x съдържа промени.
  • Кликнете с десния бутон - Замяна с - Клон - 'local_master_user_x'
  • Завършете тези промени отново, този път като правилния потребител и в местния клон "master"
  • Натиснете за отдалечено „master“
5
24 авг. отговорът се дава от paphko 24 aug. 2011-08-24 20:54 '11 в 20:54 2011-08-24 20:54

Днес се сблъскахме с проблем, когато символът 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 машината.

5
22 окт. Отговор, даден от Милош Ранджелович 22 октомври. 2014-10-22 06:32 '14 в 6:32 2014-10-22 06:32

Вашият проблем е много често срещан. Вижте „ Използване на Mailmap за определяне на списъка с автори в Git

За простота създадох скрипт, за да улесня процеса: git-changemail

След като поставите този скрипт на пътя си, можете да издавате команди като:

  • Смяна на автори в текущия клон

     $ git changemail -a old@email.com -n newname -m new@email.com 
  • Променете преобразуването на автора и изпълнителя на <branch> и <branch2>. Pass -f към клона на филтъра, за да се даде възможност за презапис на резервни копия

     $ git changemail -b old@email.com -n newname -m new@email.com -- -f  > 
  • Показване на съществуващите потребители в режим на репо

     $ git changemail --show-both 

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

5
ответ дан albfan 03 янв. '15 в 15:19 2015-01-03 15:19