Как мне отредактировать неверное сообщение о коммите в git (которое я нажал)?

152

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

Как мне изменить сообщение коммита? Является ли это возможным?

Мехди Рааш
источник

Ответы:

125

Сообщение от Линуса Торвальдса может ответить на ваш вопрос:

Изменить / отредактировать старые сообщения коммита

Краткий ответ: нельзя (если нажал).


выдержка (Линус называет BitKeeper как BK):

Заметка, просто из исторического интереса: в БК можно.

И если вы привыкли к этому (как я), это было действительно довольно практично. Я бы применил патч-бомбу от Эндрю, заметил, что что-то не так, и просто отредактировал ее, прежде чем выдвинуть.

Я мог бы сделать то же самое с мерзавцем. Было бы достаточно легко сделать так, чтобы просто сообщение о фиксации не было частью имени, и при этом гарантировалось, что история осталась нетронутой, и позволяло «исправить комментарии позже».

Но я не сделал.

Частично это чисто «внутренняя согласованность». Git - просто более чистая система, поскольку все защищено SHA1, и все объекты обрабатываются одинаково, независимо от типа объекта. Да, есть четыре разных типа объектов, и все они действительно разные, и их нельзя использовать одинаково, но в то же время, даже если их кодировка на диске может быть разной, концептуально все они работают точно тот же самый.

Но внутренняя согласованность не является оправданием негибкости, и, очевидно, было бы очень гибко, если бы мы могли просто исправлять ошибки после их возникновения. Так что это не очень сильный аргумент.

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


Чтобы быть полным, вы можете переписать свою локальную историю коммитов, чтобы отразить то, что вы хотите, как предлагает sykora (с некоторой перебазировкой и сбросом --hard, gasp!)

Однако, как только вы опубликовать пересмотренную историю сноваgit push origin +master:master, то +знак заставляя толчок произойти, даже если это не приводит к «быстрому вперед» совершить) ... вы могли бы попасть в неприятность .

Выдержка из этого другого ТАК вопроса:

Я на самом деле однажды нажал --force на git.git репозиторий и получил от Линуса БОЛЬШОЕ ВРЕМЯ. Это создаст много проблем для других людей. Простой ответ «не делай этого».

VonC
источник
хороший ответ Знаете ли вы, что теперь вы можете изменять уже отправленные сообщения коммита в новых версиях git? Что-нибудь изменилось с тех пор, как это было опубликовано в '09?
Дэвид Вест
@DavidWest тот же принцип: вы можете переписать свою историю и сделать толчок.
VonC
2
Чтобы сделать вещи более конкретными, если вы измените / rebase коммиты, их идентификаторы коммитов (шестнадцатеричные хэши в git index) неизбежно изменятся; это означает, что отредактированные коммиты обрабатываются иначе, чем их старые коммиты в истории git VCS. Тем не менее, если члены вашей команды разработчиков, к сожалению, уже извлекли старые коммиты, они обязаны вытащить отредактированные новые коммиты и выполнить слияние старого и нового в своих локальных рабочих копиях.
Шигерелло
1
Для удобства ваших коллег лучше отредактировать отредактированные коммиты, тем самым удачно исключив необходимость объединения рабочих копий коллег.
Шигерелло
28

В настоящее время git replace может помочь.

Подробно: создайте временную рабочую ветку

git checkout -b temp

Сброс на коммит для замены

git reset --hard <sha1>

Исправьте коммит с правильным сообщением

git commit --amend -m "<right message>"

Заменить старый коммит новым

git replace <old commit sha1> <new commit sha1>

вернуться в филиал, где вы были

git checkout <branch>

удалить временную ветку

git branch -D temp

От себя

guess

сделано.

Johan
источник
11
@Jonah: я получаю сообщение «Все актуально», когда я пытаюсь перейти на удаленную ветку
Simon Kagwi
1
Как уже упоминалось в другом ответе: используйте rebase -i с reword. И это перепишет историю.
Сильвен
Спасибо за решение, которое я искал. Вы экономите мое время!
Томаш Кутер
1
@Jonah - у меня проблема ... ваше решение обновило мои логи коммитов локально, но не удаленно. Как их туда подтолкнуть?
Томаш Кутер
1
@ TomaszKuter, у меня была такая же проблема, как и у тебя. Мое сообщение коммита не было удалено обновлено. Я решил это с помощью следующей справки от GitHub: help.github.com/articles/changing-a-commit-message . Выполните следующие действия: внесение изменений в раздел старых или нескольких сообщений о коммитах. Это в основном ответ снизу, данный пользователем987419. Если вы уже изменили сообщение о коммите, вы можете выбрать и сохранить его, не меняя его снова.
evaldeslacasa
19

Вы можете использовать git rebase -i(против ответвления, от которого вы разветвились) «i» для интерактива.

Замените pickследующий за комментарием фиксации, который вы хотите изменить, r(или reword), сохраните и выйдите, и после этого вы сможете выполнить редактирование.

git push еще раз и все готово!

Маркус
источник
1
Это не позволяет редактировать сообщения при слиянии. Это возможно с некоторым вариантом этой команды?
Андрей Мао
1
Попробуйте -pаргумент о том, rebaseкакие pрезервы сливаются.
Кактус
3
Мне нравится эта процедура, но сначала я не совсем понял ответ. В случае, если кому-то нужна помощь в этом, на странице справки Githulb есть хорошая информация об этом: help.github.com/articles/changing-a-commit-message
evaldeslacasa
15

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

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]

Во-первых, checkoutвременная ветка:

git checkout -b temp

В tempветке, reset --hardдля коммита, который вы хотите изменить в своем сообщении (например, этот коммит 946992):

git reset --hard 946992

Используйте amendдля изменения сообщения:

git commit --amend -m "<new_message>"

После этого дерево будет выглядеть так:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
           \
            b886a0 [temp]

Затем, cherry-pickвсе коммиты, которые находятся впереди, 946992от и masterдо tempкоммитов, используйте, amendесли вы также хотите изменить их сообщения:

git cherry-pick 9143a9
git commit --amend -m "<new_message>
...
git cherry-pick 5a6057
git commit --amend -m "<new_message>

Дерево теперь выглядит так:

dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
               \
                b886a0 - 41ab2c - 6c2a3s - 7c88c9 [temp]

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

git push --force origin temp:master

Последний шаг, удалить ветку masterна локальном, git fetch originчтобы вытянуть ветку masterс сервера, затем переключиться на ветку masterи удалить ветку temp.

Теперь и ваши локальные и удаленные будут обновлять все сообщения.

Хуй во
источник
5

В нашем магазине я ввел соглашение о добавлении узнаваемых именованных тегов к коммитам с некорректными сообщениями и использовании аннотации в качестве замены.

Несмотря на то, что это не помогает людям, которые запускают случайные команды «git log», оно дает нам возможность исправить неправильные ссылки на средства отслеживания ошибок в комментариях, и все мои инструменты сборки и выпуска понимают соглашение.

Это, очевидно, не общий ответ, но это может быть что-то, что люди могут принять в конкретных сообществах. Я уверен, что если это будет использоваться в более широком масштабе, то какая-то фарфоровая подставка для него может в конечном итоге возникнуть ...

Кристиан Гетце
источник
3
«git notes» могут служить аналогичной цели
Кристиан Гетце
2

(Из http://git.or.cz/gitwiki/GitTips#head-9f87cd21bcdf081a61c29985604ff4be35a5e6c0 )

Как изменить коммиты глубже в истории

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

Для этого вы можете использовать StGIT, при необходимости инициализировать ветвь, отменить передачу до коммита, который вы хотите изменить, всплыть на него, если необходимо, внести изменения, затем обновить патч (с опцией -e, если вы хотите исправить сообщение коммита), затем нажать все и stg совершают.

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

Или вы можете использовать git rebase --interactive, который допускает различные модификации, такие как переупорядочение патчей, свертывание, ...

Я думаю, что должен ответить на ваш вопрос. Однако обратите внимание, что если вы отправили код в удаленный репозиторий, а люди извлекли его из него, то это испортит их историю кода, а также работу, которую они проделали. Так что делай это осторожно.

Сикора
источник
Хороший ответ в теории, очень опасный на практике: см. Stackoverflow.com/questions/253055#432518
VonC
0

Если вы используете Git Extensions: перейдите на экран Commit, там должен быть флажок с надписью «Amend Commit» внизу, как показано ниже:

введите описание изображения здесь

Батшева
источник
@KrunalPandya да, или просто нажмите «совершить и нажать»
batsheva