Есть несколько способов, которые могут произойти.Прежде чем мы доберемся до них всех, нам нужно будет предоставить соответствующую справочную информациюТакже стоит подчеркнуть ключевой элемент: Никакие данные в любом существующем коммите не могут быть изменены, даже один бит. Пока коммит 39c31f5aebe43cdddbe00432207e4bb2cc6a777e
существует в вашем репозитории, он будет по-прежнему иметь ту же информацию,(Обратите внимание, что это родительский коммита, который вы показали. Вы не показали фактический хэш-идентификатор самого коммита, поэтому я не смог использовать его.)
Вочень специфический случай Git-GUI (git-gui.sh
, который я никогда не использую), он выглядит из source , как будто есть особенность, где использование «исправить» читает HEAD
фиксирует информацию об авторе и копирует ее.Обычно должен делать это, когда вы выбираете «внесение поправок» (что, как отмечено выше и ниже, является ложью белого), а не должно делать это, когда не вносятся поправки.В отличие от командной строки git commit
, похоже, нет ручки Git-GUI, чтобы внести изменения, не сохраняя автора.Если он случайно применяет автора, сохраняющего все новые коммиты, это просто ошибка.
Подробнее читайте дальше.
Фон
Каждый коммитимеет некоторые метаданные , связанные с ним.В необработанном объекте фиксации есть две соответствующие строки метаданных, которые называются author и committer .Эти два, как правило, но не обязательно, одинаковы, как можно видеть из различных коммитов в Git-репозитории для самого Git.Например:
$ git cat-file -p 5d826e972970a784bd7a7bdf587512510097b8c7
tree c790c47fe551d5ed812cfefdac243eb972c1fde3
parent b5796d9a3263b26a8ef32eeca76b3c1d62fcedc5
author Junio C Hamano <gitster pobox.com> 1544328981 +0900
committer Junio C Hamano <gitster pobox.com> 1544328981 +0900
Git 2.20
Signed-off-by: Junio C Hamano <gitster pobox.com>
(я заменил @
на
, чтобы, возможно, сократить сбор спама).Но:
$ git cat-file -p 6fcbad87d476d7281832af843dd448c94673fbfc
tree aa05bc7af6e92f3db5d5d738adf0d0b1b3dd23b6
parent b00bf1c9a8dd5009d5102aef7af9e2b886b1e5ad
author Johannes Sixt <j6t kdbg.org> 1543858489 +0100
committer Junio C Hamano <gitster pobox.com> 1543891852 +0900
rebase docs: fix incorrect format of [... snip]
Обратите внимание, что на самом деле в каждом из двух полей есть три части: полное имя, адрес электронной почты ви timestamp-with-zone-offset.
Когда вы делаете новый коммит, используя git commit
, Git обычно устанавливает и автора, и коммиттера в те же три строки .Но многие команды Git копируют некоторые существующие коммиты в новую улучшенную замену.Новый коммит, по определению, имеет новый и другой хэш-идентификатор, но предназначен для использования вместо старого.В этих случаях Git обычно сохраняет исходную информацию author и устанавливает вас (и сейчас) как committer .
Для справки: автор-сохраняющее коммит-копированиекоманды git commit
с опциями --amend
или -c
/ -C
;git cherry-pick
;и git rebase
.Команда git am
предназначена для превращения отправленных по электронной почте исправлений в коммиты: она принимает в качестве входных данных что-то отличное от commit , поэтому мы можем сказать, что это сохраняет автора, но затем мы должны определить, что мы подразумеваем автор .В этом случае git am
угадывает информацию об авторстве, анализируя сообщение в формате почтового ящика.
Механизмы для каждого поля
Существует одна базовая команда Git, git commit-tree
, другаяКоманды либо используют, либо встроены в них.Это фактически создает объект фиксации, который содержит вышеуказанные метаданные.Могут потребоваться различные директивы для индивидуальной настройки каждого поля.Если для какого-либо поля установлено , а не , git commit-tree
может принимать откуда-то значение по умолчанию.
Поскольку для каждого из авторов есть шесть частей - имя, адрес электронной почты и отметка времении коммиттер - есть шесть мест, чтобы получить конкретные директивы, и много мест - не шесть в этот раз! - чтобы получить значения по умолчанию.Однако сначала давайте перечислим первичные шесть.
Вместо того, чтобы принимать параметры командной строки, git commit-tree
берет эти шесть элементов из переменных среды , как описано в документации :
GIT_AUTHOR_NAME
GIT_AUTHOR_EMAIL
GIT_AUTHOR_DATE
GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL
GIT_COMMITTER_DATE
Если вы установите любую или все этих переменных, то будет установлено значение, которое войдет в все последующие новые коммиты (до тех пор, пока вы не сбросите переменные или ваш сеанс с этой средой не истечет, сбросив переменные).
Если нет, то в документации сказано:
В случае, если (некоторые из) эти переменные среды не установлены, информация берется из элементов конфигурации user.name и user.email или, если не присутствует, переменной среды EMAIL, или, если она не установлена, системного пользователяимя и имя хоста, используемые для исходящей почты (взяты из /etc/mailname
и возвращаются к полному имени хоста, когда этот файл не существует).
Это немного лживая ложь, так какфактический путь к коду зависит от параметров времени компиляции, поэтому разные установки Git могут иметь разные индивидуальные настройки по умолчанию.Но общая общая идея верна: Git сначала будет использовать ваши настройки user.name
и user.email
как для автора, так и для коммиттера, если вы не переопределили одно или оба с различными переменными окружения.
По умолчаниювременная метка, конечно, просто представление вашего компьютера о текущем времени.Относительно новый параметр user.useConfigOnly
говорит современному Git не догадываться при user.name
и / или user.email
.В более старых версиях Git Git не угадывал: если бы они не были установлены, git commit-tree
и git commit
просто потерпели бы ошибку с сообщением об ошибке, сообщая, что он не знал, кто вы.
The git commit
команда переднего конца также принимает --author
и --date
в качестве аргументов.Эти аргументы могут указывать имя пользователя, адрес электронной почты и / или метку времени для использования в новом коммите;git commit
эффективно реализует их, устанавливая на время операции фиксации переменные GIT_AUTHOR_*
.
При использовании внешнего интерфейса git commit
с флагом --amend
, который, несмотря на его имя,на самом деле не изменяет коммит;он просто создает новый, чтобы использовать вместо текущего, со всеми вытекающими отсюда последствиями - флаг --reset-author
указывает внешнему интерфейсу не сохранять информацию об авторе исходного коммита.
Заключение
Если новые коммиты получают неверного автора, а правильный коммиттер должен иметь место:
Если у вас есть какой-либо существующий коммит, и вы пытаетесь заменить его новым и улучшенным коммитом через git commit --amend
, но он сохраняет настройки автора, простодобавить --reset-author
.Конечно, это работает только из командной строки.Если вы используете что-то еще, выясните, есть ли у него аналогичная опция.
Если какой-то существующий коммит имеет неверного автора, вы застряли с этим.Вы можете скопировать существующий, не очень хороший, фиксацию в новый и улучшенный коммит и попытаться убедить всех остальных, у кого есть копия этого же хранилища - клон, - взять и использовать новый и улучшенный коммитвместо старого.То, насколько трудно , что будет очевидно, зависит от того, насколько упрямы другие пользователи, а также от того, где зафиксирован коммит.
Коммиты, которые находятся на верхушке их ветви, а не на каких-либо другихветку, довольно легко поменять, используя git commit --amend
.Дальнейшие коммиты в истории более трудны: вы можете использовать интерактивную перебазировку, или git replace
, или, в особо уродливых случаях, git filter-branch
, чтобы поменять их местами (иногда комбинируя эти приемы).Любое «изменение» на более старый коммит обязательно распространяется по всем его потомкам по дизайну, 1 , так что такого рода изменения могут быть весьма разрушительными.Однако, если она «меняется» - заменяет, действительно, историю, которую никто еще не видел, она достаточно безопасна.
1 Непосредственные потомки «плохого» коммитасодержит идентификатор родительского хэша плохого коммита.Следовательно, чтобы дети могли ссылаться на замену, мы должны заменить детей тоже .Это означает, что мы должны затем заменить их потомков и т. Д. По линии, вплоть до кончиков коммитов каждой затронутой ветви.