Питання Як змінити ім'я автора, ім'я виконавця та електронну пошту кількох команд у Git?


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

Чи є спосіб змінити автора цих зобов'язань на моє ім'я?


2004
2018-04-15 03:09


походження


Питання: чи використовує гіт-фільтр-філія SHA1 для попередніх тегів, версій та об'єктів? Чи буде зміна назви автора змінити пов'язані SHA1 також? - AndyL
Хеш змінить так - Not Available
По суті, я створив невеликий скрипт, який, нарешті, виправив для мене основну причину. gist.github.com/tripleee/16767aa4137706fd896c - tripleee
@impinball Вік запитання навряд чи актуальний. Створення нового дубльованого питання не підходить. Я думаю, я міг би створити питання, яке благало цю конкретну відповідь, але я зовсім не переконаний, що це принесе все таку ж видимість. Це не схоже на дефіцит Git питань тут ... Рада я міг допомогти, у всякому разі. - tripleee
Для цього GitHub має спеціальний сценарій: help.github.com/articles/changing-author-info - Timur Bernikowich


Відповіді:


Зміна автора (чи комітера) вимагатиме переписування всієї історії. Якщо ви все в порядку з цим і думаєте, що варто це, то ви повинні перевірити гіт-фільтр-гілка. Сторінка "Людина" містить кілька прикладів для початку. Також зауважте, що ви можете використовувати змінні середовища, щоб змінити назву автора, комітера, дати тощо - див. Розділ "Змінні середовища" git man page.

Зокрема, ви можете виправити всі неправильні імена авторів та електронні листи для всіх галузей та тегів з цією командою (джерело: 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

801
2018-04-15 03:16



Для цього Github має публічний сценарій help.github.com/articles/changing-author-info і це чудово працює! - rodowi
Після виконання сценарію ви можете видалити запасне відділення, виконавши "git update-ref-d refs / original / refs / heads / master". - D.R.
@ Doodowi, він дублює всі мої зобов'язання. - Rafael Barros
@RafaelBarros інформація про автора (як і все інше в історії) є частиною ключа commit. Будь-яка зміна історії - це перезапис, що веде до створення нового ідентифікатора для всіх дій. Тому не перепишіть на загальну репо або переконайтеся, що всі користувачі знають про це ... - johannes
Вирішено використання git push --force --tags origin HEAD:master - Matteo Contrini


Використовуйте інтерактивну програму Rebase

Ви могли б зробити

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

Потім позначте всі ваші погані зобов'язання як "редагувати" у файлі rebase. Якщо ви також хочете змінити свій перший фікс, вам доведеться вручну додати його як перший рядок у файл rebase (слідувати формату інших рядків). Тоді, коли гіт просить вас внести зміни до кожного зобов'язання, робіть

 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

Однозначне виконання

Як зазначають деякі коментатори, якщо ви просто хочете змінити останню фіксацію, команду 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 тягнуть запити, то буде тонна злиття робить у вашій історії). Це дуже часто може призвести до зовсім іншої історії (оскільки повторювані зміни можуть бути "перебазовані"), і в гіршому випадку це може призвести до git rebase просять вас вирішувати складні конфлікти злиття (які, ймовірно, вже вирішені при об'єднанні). Рішенням є використання -p прапор до git rebase, що збереже структуру злиття вашої історії. Довідник для git rebase попереджає про використання -p і -i може призвести до проблем, але в BUGS У розділі сказано, що "Редагування зобов'язує і переформулювати свої повідомлення про коректність".

Я додав -p до вищевказаної команди. Для випадку, коли ви просто змінюєте останню процедуру, це не проблема.


1417
2017-08-24 03:08



Відмінно підходить для непарних зобов'язань, хоча - корисно, якщо ви спарюєтесь і забудете змінити автора - mloughran
+1 для згадки про usecase для типової помилки: git commit --amend --author = ім'я користувача - Nathan Kidd
Це ідеальне, найчастіше я вважаю, що я сідаю на інший комп'ютер і забув налаштувати автора, і, як правило, він <5 зобов'язується або так вирішити. - Zitrax
git commit --amend --reset-author також працює один раз user.name і user.email налаштовані правильно. - pts
Перепишіть інформацію про авторські права на всі зобов'язання після <commit> використовуючи user.name і user.email від ~/.gitconfig: біжи git rebase -i <commit> --exec 'git commit --amend --reset-author --no-edit', зберегти, кинути. Не треба редагувати! - ntc2


Ви також можете зробити:

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

566
2018-05-15 19:15



Чи не використовує ENV-фільтр простіше рішення? Не знаєте, чому це отримує більше голосів, потім. - stigkj
Потім посилання зламано. Як ми натискаємо ці зміни на інший сховище? - Russell
ENV-фільтр змінить всі зобов'язання. Це рішення дозволяє умовно. - user208769
"A previous backup already exists in refs/original/ Force overwriting the backup with -f" вибачте, але де -f -flag збирається виконувати цей сценарій два рази. Насправді, це відповідає Брайан, вибачте про порушення тільки після того, як фільтр-гілка - це рішення. - hhh
@ user208769 env-filter також дозволяє умовно; подивіться на мою відповідь :-) - stigkj


Один вкладиш, але будьте обережні, якщо у вас є багатокористувацький репозиторій - це зміниться все зобов'язується мати одного (нового) автора і комітера.

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

483
2018-04-15 03:22



Так, але не забувайте ім'я / адресу електронної пошти продавця. Що для мене було git filter-branch -f --env-filter "GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='newemail'; GIT_COMMITER_NAME='Newname'; GIT_COMMITTER_EMAIL='newemail';" HEAD В іншому випадку git буде стежити за старим ім'ям як комір! - Olivier Verdier
@ Олів'є У вас є помилка на GIT_COMMITER_NAME -> GIT_COMMITTER_NAME - Filipe Correia
Він працював для всіх завдань для мене, включаючи початковий. - Vincent
Чому це перезаписує всі зобов'язання, якщо ви вкажете HEAD в кінці команди? - Nick Volynkin
Це не працює для мого сховища bitbucket, будь-яка ідея? Я роблю git push --force --tags origin 'refs/heads/*' після порадженої команди - ujsgeyrr1f0d0d0r0h1h0j0j_juj


Це трапляється, коли у вас немає ініціалізованої версії $ 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


202
2018-02-16 09:46



Це дуже добре працює на останній фіксації. Приємно і просто. Ні мати бути глобальними змінами, використовуючи --local працює теж - Ben
git commit --amend --reset-author --no-edit - mafrosis


Для однієї фіксації:

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

(витягнуте з відповіді асмерзера)


180
2018-04-26 22:50



але це тільки якщо це останнє зобов'язання - Richard
Відповідно до git help commit, git commit --amend змінює фіксацію на "кінці поточної гілки" (тобто HEAD). Це, як правило, найновіша фіксація, але ви можете спочатку зробити це будь-яким спонуканням перевірити що здійснюють з git checkout <branch-name> або git checkout <commit-SHA>. - Rory O'Kane
Але якщо ви це зробите, усі ті зобов'язання, які вже мають цю компрометацію як батьків, будуть вказувати на неправильну фіксацію. Краще використовувати фільтр-гілку в той момент. - John Gietzen
@ JohnGietzen: Ви можете переробляти повернення на те, що було змінено, щоб виправити це. Однак якщо ви робите> 1 фіксацію, то, як вже згадувалося, фільтр-гілка, мабуть, буде набагато простіше. - Thanatos
Зверніть увагу, що це змінює тільки здійснити author а не committer - Nick Volynkin


У тому випадку, коли лише деякі найуспішніші особи мають погані автори, ви можете зробити все це всередині 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 за натхненням.


152
2017-12-08 17:05



Напевно, чудово. Чи можете ви скоротити його, встановивши user.name і user.email в локальній конфігурації repo, а потім кожен рядок буде тількиexec git commit --amend --reset-author -C HEAD ? - Andrew
@Andrew - reset-author працює просто чудово. - Boggin
Канонічна відповідь, щоб використовувати фільтр-гілку, просто вилучені refs / heads / master для мене. Тож +1 до керованого, редагованого рішення. Дякую! - jmtd
Чому ти починаєш з Someone else's commitзамість my bad commit 1? Я просто спробував HEAD^^ внести зміни до останніх двох команд, і це працювало чудово. - fredoverflow
Замість git rebase -i HEAD^^^^^^ Ви можете також писати git rebase -i HEAD~6 - Patrick Schlüter


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"
'

108
2017-10-07 09:54



Працював чудово. Просто довелося git reset --hard HEAD^ кілька разів на інших локальних сховищах, щоб отримати їх у більш ранній версії, git pull- оновлена ​​змінена версія, і тут я без рядків, що містять unknown <stupid-windows-user@.StupidWindowsDomain.local>(треба любити невідповідність git). - Alan Plum
Я не можу поштовх після цього. Чи повинен я використовувати "-f"? - fossilet
я зробив git push -f. Також після цього треба відремонтувати місцевих репо. - fossilet
Якщо вам потрібно запустити скрипт оболонки в певній гілці, ви можете змінити останній рядок на: "" майстер ... ваша назва гілки "(якщо ви розгадаєте майстра). - Robert Kajic
Натисніть на посилання <nice solution>, коли сценарій був оновлений - mdn


Як згадується docgnome, переписування історії є небезпечним і розбитиме інші сховища людей.

Але якщо ви дійсно хочете це зробити, і ви перебуваєте в середовищі bash (без проблем у Linux, у Windows ви можете використовувати git bash, що забезпечується встановленням 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

79
2017-08-04 00:52



Зверніть увагу, що це дозволить залишити будь-які теги, що вказують на старі зобов'язання. --tag-name-filter cat це варіант "зробити це роботою". - Roman Starkov
@romkyns будь-яка ідея про те, як змінити теги? - Nick Volynkin
@NickVolynkin Так, ви вкажете --tag-name-filter cat. Це дійсно повинно було бути поведінкою за умовчанням. - Roman Starkov