Как изменить существующие сообщения без фиксации?

7664

Я написал неправильную вещь в сообщении фиксации.

Как я могу изменить сообщение? Коммит еще не был передан.

Лори Янг
источник
868
Для тех, кто немного новичок в гите: точка зрения Лори о том, что она еще не подтолкнула, важна. Как и перебазирование, это меняет историю. Если кто-то клонировал / вытащил из вашего репо между оригинальной и переписанной историей, он не сможет вытащить после переписывания (для этой ветви).
Пэт Нотц

Ответы:

16133

Изменение самого последнего сообщения о коммите

git commit --amend

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

git commit --amend -m "New commit message"

… Однако, это может сделать сообщения о многострочной фиксации или небольшие исправления более трудоемкими для ввода.

Убедитесь , что у вас нет каких - либо изменений в оборотном копии поставил перед этим или они получат совершенные тоже. ( Не внесенные изменения не будут зафиксированы.)

Изменение сообщения коммита, который вы уже отправили в удаленную ветку

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

git push <remote> <branch> --force
# Or
git push <remote> <branch> -f

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

Предупреждение: будьте осторожны при внесении изменений в коммиты, которыми вы уже поделились с другими людьми. Внесение изменений в коммиты по существу переписывает их с разными идентификаторами SHA , что создает проблему, если у других людей есть копии старого коммита, который вы переписали. Любой, у кого есть копия старого коммита, должен будет синхронизировать свою работу с вновь перезаписанным коммитом, что иногда может быть затруднено, поэтому убедитесь, что вы координируете действия с другими при попытке переписать историю общего коммита, или просто избегайте перезаписи общих коммитов в целом.


Выполнить интерактивную перебазировку

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

Чтобы сделать сквош Git, выполните следующие действия:

// n is the number of commits up to the last commit you want to be able to edit
git rebase -i HEAD~n

Как только вы раздавите свои коммиты - выберите e/rдля редактирования сообщения:

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

Важное замечание об интерактивной перебазировке

При использовании git rebase -i HEAD~nможет быть больше n коммитов. Git "соберет" все коммиты за последние n коммитов, и если где-то между этими диапазонами произошло слияние, вы также увидите все коммиты, поэтому результат будет n +.

Хороший совет:

Если вам нужно сделать это для нескольких веток, и вы можете столкнуться с конфликтами при внесении изменений в контент, настройте git rerereи позвольте Git автоматически разрешать эти конфликты за вас.


Документация

user456814
источник
257
Однако git commit --amendне так мощно, как git rebase -i.
Джеффри Хосе
76
@jeffjose, это определенно не должно быть. Также git commit --amendможно исправить (a?) Мастер-коммит.
Страгер
116
Если вы уже нажали, просто нажмите толчок снова:git push -f origin branchname
hughes
177
@ Hughes не git push -fнемного опасно, если другие люди используют тот же репозиторий?
Арманд
91
Если вы не хотите переписывать все сообщение о коммите, перейдите к git commit --amend -c HEAD. Откроется редактор, предварительно заполненный вашим старым сообщением о коммите, и вы сможете его изменить.
Сэм
2506
git commit --amend -m "your new message"
lfx_cool
источник
7
Я сделал git commit --amend -m "Новое сообщение", но нажатие на Github сгенерировало "Объединить удаленные изменения перед повторной отправкой". После pull, commit --amend и push снова, новое сообщение не появляется. Вместо этого у меня есть «ветвь слияния« master »из github.com:[myrepo]»
Дейв Эверитт,
8
@DaveEveritt вы, скорее всего, передали свой коммит вверх по течению, прежде чем пытаться это исправить.
Турбьёрн Равн Андерсен
12
@ Kyralessa не правда. В bash вы можете легко составлять сообщения многострочной фиксации, просто не закрывая кавычку до тех пор, пока не закончите (нажимая клавишу возврата в конце каждой строки в кавычках).
варенье
32
Я не понимаю, как ответ, который очень похож на основную идею ответа, который был написан два года назад, а также принятый ответ получает так много голосов. Странный. (с ответом все в порядке)
счастливый кодер
7
@AmalMurali, хорошо. Мое мнение было не столько о популярности вопроса, ни о полезности ответа. Но этот конкретный ответ не является самым старым ответом, и при этом он не предлагает дальнейшего понимания принятого ответа. Похоже, это копия раздела принятого ответа. Это была моя точка зрения. CHEERS!
счастливый кодер
2376

Если фиксация, которую вы хотите исправить, не самая последняя:

  1. git rebase --interactive $parent_of_flawed_commit

    Если вы хотите исправить несколько некорректных коммитов, передайте родителю самого старого из них.

  2. Появится редактор со списком всех коммитов, начиная с того, который вы дали.

    1. Измените pickна reword(или на старых версиях Git, на edit) перед любыми коммитами, которые вы хотите исправить.
    2. После сохранения Git воспроизведет перечисленные коммиты.

  3. Для каждого коммита, который вы хотите перефразировать , Git вернет вас обратно в ваш редактор. Для каждого коммита, который вы хотите редактировать , Git помещает вас в оболочку. Если вы в оболочке:

    1. Измените коммит любым удобным вам способом.
    2. git commit --amend
    3. git rebase --continue

Большая часть этой последовательности будет объяснена вам при выводе различных команд. Это очень просто; Вам не нужно запоминать это - просто помните, что это git rebase --interactiveпозволяет вам исправлять коммиты, независимо от того, как давно они были.


Обратите внимание, что вы не захотите изменять коммиты, которые вы уже выдвинули. Или, может быть, так и есть, но в этом случае вам придется позаботиться о том, чтобы общаться со всеми, кто мог выполнить ваши коммиты и поработать над ними. Как я могу восстановить / повторно синхронизировать после того, как кто-то отправит ребаз или сброс в опубликованную ветку?

Аристотель Пагальцис
источник
39
Можно ли изменить сообщение первого коммита (у которого нет родителя)?
13рен
27
Это упомянуто в одном из других ответов, но я помещу примечание здесь. Начиная с git 1.6.6 вы можете использовать rewordвместо этого pickдля редактирования сообщения журнала.
MitMaro
89
Кстати, $parent_of_flawed_commitэто эквивалентно $flawed_commit^.
Peeja
67
Никогда НИКОГДА не делайте этого (или перебазируйте вообще), если вы уже продвинулись вверх по течению!
Даниэль Ринзер
20
Используйте -p( --preserve-merges), если после некорректного коммита произошло слияние.
Ахвен
778

Чтобы изменить предыдущий коммит, внесите необходимые изменения и выполните эти изменения, а затем выполните команду

git commit --amend

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

Чтобы изменить предыдущую фиксацию и сохранить то же сообщение журнала, запустите

git commit --amend -C HEAD

Чтобы исправить предыдущий коммит, удалив его полностью, запустите

git reset --hard HEAD^

Если вы хотите отредактировать более одного сообщения о коммите, запустите

git rebase -i HEAD~commit_count

(Замените commit_count на количество коммитов, которые вы хотите редактировать.) Эта команда запускает ваш редактор. Пометьте первый коммит (тот, который вы хотите изменить) как «edit» вместо «pick», затем сохраните и выйдите из вашего редактора. Сделайте изменения, которые вы хотите зафиксировать, а затем выполните

git commit --amend
git rebase --continue

Примечание. Вы также можете «внести необходимые изменения» в редакторе, открытом git commit --amend

Фатих Ацет
источник
18
git rebase -i HEAD~commit_countтакже позволит вам изменить сообщения о коммите любого количества коммитов по вашему выбору. Просто пометьте выбранные коммиты как «reword» вместо «pick».
Джо
2
Что делать, если вы не хотите перебазировать? Вы просто хотите изменить старое сообщение?
SuperUberDuper
3
git reset --hardуничтожает незафиксированные изменения. Пожалуйста, замените --hardна --soft.
угорь ghEEz
1
Согласен, git reset --hardэто совершенно законная команда, но она вводит в заблуждение, учитывая вопрос. Вы используете, --hardесли вы зафиксировали изменения, которые хотите отбросить, а не если вы сделали опечатку в сообщении коммита!
Сорен Бьорнстад
398

Как уже упоминалось, git commit --amendэто способ перезаписать последний коммит. Одно замечание: если вы хотите перезаписать файлы , команда

git commit -a --amend -m "My new commit message"
Джон
источник
4
И если вы не хотите добавлять все, вы можете сначала сделать, а git add file.extзатем простоgit commit --amend
MalcolmOcean
358

Вы также можете использовать git filter-branchдля этого.

git filter-branch -f --msg-filter "sed 's/errror/error/'" $flawed_commit..HEAD

Это не так просто, как тривиально git commit --amend, но особенно полезно, если у вас уже есть некоторые слияния после сообщения об ошибке.

Обратите внимание, что это попытается переписать каждый коммит между HEADошибочным коммитом, поэтому вы должны выбирать свою msg-filterкоманду очень мудро ;-)

отметка
источник
4
Есть ли версия этого, которая не изменяет коммит, если регулярное выражение ничего не находит?
sjakubowski
3
AFAIK filter-branch --msg-filter будет генерировать новые коммиты в любом случае. Тем не менее, вы можете проверить в msg-фильтре, успешен ли sed, и использовать эту информацию после завершения операции ответвления фильтра, чтобы сбросить ваше дерево до refs / original.
Марка
4
@DavidHogue Это верно только при использовании метода filter-branch. Идентификаторы фиксации после измененной фиксации не изменяются, если вы используете интерактивную перебазировку.
Марк
6
@ Марк Да, они делают, они обязаны. Идентификаторы коммитов зависят от предыдущих коммитов. Если бы они не изменились, мерзавец был бы бесполезен.
Майлз Рут
2
Тебе нужно $flawed_commit^..HEAD, а не $flawed_commit..HEAD. как указано на странице руководства: « Команда будет перезаписывать только те положительные ссылки, которые указаны в командной строке (например, если вы передадите a..b, только b будет перезаписано). »
Анхель
319

Я предпочитаю этот способ:

git commit --amend -c <commit ID>

В противном случае будет новый коммит с новым идентификатором коммита.

Krevedko
источник
7
Для меня, использование вашей команды выше фактически создает новый коммит с новым идентификатором фиксации плюс дополнительный коммит, говорящий «ветвь слияния» в качестве сообщения фиксации по умолчанию.
января
46
Изменение всегда создает новый коммит с новым идентификатором коммита. Идентификатор фиксации - это SHA-хэш содержимого фиксации, включая сообщение фиксации и созданные / зафиксированные временные метки. Это особенность Git, которая, за исключением коллизий хешей, гарантирует, что два коммита с одним и тем же идентификатором будут в точности одинаковыми, с абсолютно одинаковым содержимым, историей и т. Д.
Эмиль Лундберг
7
Согласитесь с Эмилем. Кроме того, при чтении документов - кажется, что все, что делает "-c", это говорит git, какое сообщение коммита использовать в качестве шаблона по умолчанию / для вашего нового коммита. Действительно, он уже собирается делать "-c <идентификатор ID>" по умолчанию. , так что нет необходимости указывать это.
Гал
2
Это -cделает несколько вещей. По умолчанию используется старое сообщение, но также копируется информация об авторстве (человек и время). -Cделает то же самое, за исключением того, что он не просит вас отредактировать сообщение.
Джозеф К. Штраус
1
Как @SantanuDey, это не сработало для меня. Я получилfatal: Option -m cannot be combined with -c/-C/-F/--fixup.
Эндрю Гримм
312

Если вы используете инструмент Git GUI, есть кнопка Amend last commit . Нажмите на эту кнопку, и тогда она покажет ваши последние файлы коммита и сообщение. Просто отредактируйте это сообщение, и вы можете зафиксировать его с новым сообщением фиксации.

Или используйте эту команду из консоли / терминала:

git commit -a --amend -m "My new commit message"
Ахилрай Н.С.
источник
4
Этот ответ буквально идентичен этому старшему . Вы проверили существующие ответы, прежде чем предоставить другой?
Дан Даскалеску
284

Вы можете использовать Git ReBasing . Например, если вы хотите изменить обратно, чтобы зафиксировать bbc643cd, запустите

$ git rebase bbc643cd^ --interactive

В редакторе по умолчанию измените 'pick' на 'edit' в строке, фиксацию которой вы хотите изменить. Сделайте свои изменения и затем поставьте их на

$ git add <filepattern>

Теперь вы можете использовать

$ git commit --amend

изменить коммит, и после этого

$ git rebase --continue

вернуться к предыдущему главному коммиту.

Шоаиб Уд-Дин
источник
1
Если вы хотите убедиться, что ваше изменение git commit --amendвступило в силу, вы можете использовать git showего, и оно покажет новое сообщение.
Стив Таубер
279
  1. Если вы хотите изменить только последнее сообщение о коммите, то выполните:

    git commit --amend
    

Это приведет вас в ваш текстовый редактор и позволит вам изменить последнее сообщение о коммите.

  1. Если вы хотите изменить последние три сообщения фиксации, или любой из сообщения фиксации до этого момента, поставки HEAD~3в git rebase -iкоманде:

    git rebase -i HEAD~3
    
Хина Хуссейн
источник
6
Этот более ранний ответ уже говорит, что вы можете использовать git commit --amend, и он также говорит, что вы можете использовать git rebase -i HEAD~commit_count, все, что вы сделали, это подключить 3для commit_count.
Понижено также. Люди просто не удосужились прочитать существующие ответы .
Дан Даскалеску
261

Если вам нужно изменить старое сообщение о коммите в нескольких ветвях (т. Е. Коммит с ошибочным сообщением присутствует в нескольких ветвях), вы можете использовать:

git filter-branch -f --msg-filter \
'sed "s/<old message>/<new message>/g"' -- --all

Git создаст временный каталог для перезаписи и дополнительно создаст резервную копию старых ссылок в refs/original/.

  • -fобеспечит выполнение операции. Это необходимо, если временный каталог уже существует или если в нем уже есть ссылки refs/original. Если это не так, вы можете сбросить этот флаг.

  • -- отделяет параметры ветви фильтра от параметров ревизии.

  • --allубедитесь, что все ветви и теги переписаны.

Благодаря резервному копированию ваших старых ссылок, вы можете легко вернуться в состояние перед выполнением команды.

Скажем, вы хотите восстановить своего мастера и получить к нему доступ в ветке old_master:

git checkout -b old_master refs/original/refs/heads/master
sebers
источник
3
Этот ответ не отвечает на вопрос OP, поскольку они просто заинтересованы в фиксации коммита, который они только что сделали. Я регулярно использую, git commit --amendчтобы исправить комментарии или добавить файлы, которые я забыл git add, но только когда-либо прежде, чем я редактировал git push. Я также использую, git filter-branchкогда я хочу полностью возиться с историей версий, но OP не хочет этого, поэтому этот ответ нуждается в большом предупреждении о вреде для здоровья - не пытайтесь делать это дома, подсматривает !!
kbro
226

использование

git commit --amend

Чтобы понять это подробно, отличный пост - 4. Переписывание Git History . Это также говорит о том, когда не использовать git commit --amend .

кожа
источник
2
Есть ли хороший способ исправить сообщения коммита, уже отправленные в публичный репозиторий? До сих пор я пришел к выводу, что после опечатки мои сообщения о коммитах и ​​thinkos должны жить вечно.
stackunderflow
2
Одним словом, НОПЕ! Нет ХОРОШЕГО способа убрать то, что вы нажали. Все ретракции ПЛОХО в большей или меньшей степени. Вы должны принять дисциплину работы в ветке в своем личном репозитории, делая несколько коммитов, когда вы добавляете немного, проверяете немного, настраиваете немного. Затем объедините всю ветку в один коммит, напишите новое сообщение коммита, описывающее общее изменение, PROOFREAD и нажмите.
kbro
1
Просто чтобы указать на очевидное, что не нужно делать ни одного коммита при возвращении из ветви функций. Многие люди делают перебаз в целевой ветви (чтобы все выглядело чисто), а затем объединяются с опцией подавления быстрой пересылки. Согласитесь с главным моментом, чтобы быть осторожным, прежде чем подтолкнуть вверх, хотя.
ShawnFumo
1
git commit --amendОтвет уже был дан ( в несколько раз) , прежде чем вы написали ваши. Почему вы отправили это снова? Если вы хотите добавить ссылку на «Переписывание истории Git», вы можете отредактировать один из существующих ответов или оставить комментарий.
Дан Даскалеску
199

изменить

У вас есть несколько вариантов здесь. Ты можешь сделать

git commit --amend

пока это ваш последний коммит.

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

В противном случае, если это не ваш последний коммит, вы можете сделать интерактивный ребаз,

git rebase -i [branched_from] [hash before commit]

Затем в интерактивном ребазе вы просто добавляете правку в этот коммит. Когда он появится, сделайте git commit --amendи измените сообщение коммита. Если вы хотите откатиться до этой точки фиксации, вы также можете использовать git reflogи просто удалить эту фиксацию. Тогда вы просто делаете git commitснова.

wallerjake
источник
191

Если это ваш последний коммит, просто изменить фиксацию:

git commit --amend -o -m "New commit message"

(Использование флага -o( --only), чтобы убедиться, что вы изменяете только сообщение фиксации)


Если это скрытый коммит, используйте потрясающую интерактивную ребазу :

git rebase -i @~9   # Show the last 9 commits in a text editor

Найдите нужный коммит, измените pickна r( reword), сохраните и закройте файл. Выполнено!



Миниатюрный учебник Vim (или, как сделать перебаз только с 8 нажатиями клавиш 3jcwrEscZZ):

  • Беги, vimtutorесли есть время
  • hjkl соответствуют клавишам движения
  • Все команды могут иметь префикс «диапазон», например, 3jперемещается вниз на три строки
  • i для входа в режим вставки - введенный вами текст появится в файле
  • Escили Ctrlcдля выхода из режима вставки и возврата в «нормальный» режим
  • u отменить
  • Ctrlr переделать
  • dd, dw, dlЧтобы удалить строку, слово или букву, соответственно
  • cc, cw, clЧтобы изменить строку, слово или букву, соответственно ( такой же , какddi )
  • yy, yw, ylКопировать ( «дернул») линию, слово или букву, соответственно
  • pили Pвставить после или перед текущей позицией соответственно
  • :wEnter сохранить (записать) файл
  • :q!Enter выйти без сохранения
  • :wqEnterили ZZсохранить и выйти

Если вы много редактируете текст, переключитесь на раскладку клавиатуры Dvorak , научитесь печатать на клавиатуре и изучите Vim. Стоит ли усилий? Да.



ProTip ™: не бойтесь экспериментировать с «опасными» командами, которые переписывают историю * - Git по умолчанию не удаляет ваши коммиты в течение 90 дней; вы можете найти их в reflog:

$ git reset @~3   # Go back three commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Остерегайтесь опций, как --hardи --forceхотя - они могут отказаться от данных. * Кроме того, не переписывайте историю ни в каких ветвях, над которыми вы сотрудничаете.

Zaz
источник
3
Часть vim полностью не по теме, и вместо того, чтобы поощрять пользователей тратить время на изучение использования тайного редактора, почему бы не научить их чему-то более тематическому, например, как настроить редактор git по умолчанию, чтобы он был чем-то удобным для пользователя, например nano? Мы говорим о тривиальных модификациях, которые необходимо внести в текстовый файл, а не о жестком кодировании, которое вызвало бы ожесточенную войну за «лучший» текстовый редактор.
Дан Даскалеску
1
@DanDascalescu: потому что быстрее изучить Vim, используя приведенные выше инструкции, чем выполнить несколько ребаз, используя nano. Причина, по которой git открывает текстовый редактор, а не собственный интерфейс для перебазирования, заключается в том, что Vim существует: он легок, установлен по умолчанию на большинстве систем и очень прост в освоении, чтобы достаточно легко выполнить перебазирование: например, ddjjpZZперемещает коммит 2 вниз. В базовых знаниях Vim нет ничего загадочного; Требуется 10 минут, чтобы стать более комфортным с Vim, чем с nano.
Zaz
185

Если вы используете графический интерфейс Git, вы можете изменить последний коммит, который не был добавлен:

Commit/Amend Last Commit
gulchrider
источник
168

Я использую графический интерфейс Git, насколько могу, и это дает вам возможность изменить последний коммит:

Отметьте эту клеточку

Кроме того, git rebase -i origin/masterэто хорошая мантра, которая всегда представит вам коммиты, которые вы сделали на вершине мастера, и даст вам возможность изменить, удалить, изменить порядок или сквош. Нет необходимости сначала получать этот хеш.

Хавард Графф
источник
4
Как мне добраться до того экрана, который вы показали в своем примере?
Марван مروان
2
Это нижняя правая часть Windows Git Gui. Просто выберите переключатель «Amend Last Commit», и он будет заполнен самой последней информацией о коммите.
wbdarby
138

Вау, так что есть много способов сделать это.

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

git reset --soft HEAD~1
git commit -m 'New and corrected commit message'

Я всегда делаю это, если забываю добавить файл или внести изменения.

Не забудьте указать --softвместо --hard, иначе вы потеряете этот коммит полностью.

Раду Мурзеа
источник
5
Это делает то же самое, git commit --amendза исключением того, что это двухэтапный процесс.
Джозеф К. Штраус
3
@ JosephK.Strauss Я полагаю, что внесение изменений в коммит также сохраняет оригинальную информацию об авторе и дате коммита, а также информацию о новом коммитере и дате отдельно. Я не уверен, что такой подход делает это.
Everton
4
@EvertonAgner Вы правы. --amendбудет хранить информацию об авторе, но вопрос только просит изменить сообщение.
Джозеф К. Штраус
131

Для тех, кто ищет графический интерфейс для Windows / Mac, чтобы помочь с редактированием старых сообщений (т.е. не только самого последнего сообщения), я бы порекомендовал Sourcetree . Шаги, чтобы следовать ниже.

Sourcetree интерактивная перебазировка

Для коммитов, которые еще не были переданы на удаленное устройство:

  1. Убедитесь, что вы зафиксировали или сохранили все текущие изменения (т. Е. На вкладке «Состояние файла» нет файлов) - иначе это не сработает.
  2. На вкладке «Журнал / история» щелкните правой кнопкой мыши запись с примыкающей линией на графике под коммитом, который вы хотите отредактировать, и выберите «Перебазировать потомков в <commit ref> интерактивно ...»
  3. Выберите всю строку для коммит-сообщения, которое вы хотите изменить (нажмите на столбец «Сообщение») .
  4. Нажмите кнопку «Редактировать сообщение».
  5. Отредактируйте сообщение, как требуется, в появившемся диалоговом окне, а затем нажмите OK.
  6. Повторите шаги 3-4, если есть другие сообщения коммита для изменения.
  7. Нажмите OK: начнется ребазинг. Если все хорошо, вывод закончится «Завершено успешно». ПРИМЕЧАНИЕ: я иногда видел эту ошибку Unable to create 'project_path/.git/index.lock': File exists.при попытке изменить несколько сообщений коммита одновременно. Не знаю точно, в чем проблема, или будет ли она исправлена ​​в будущей версии Sourcetree, но если это произойдет, рекомендую менять их по одному (медленнее, но кажется более надежным).

... или ... для коммитов, которые уже были выдвинуты:

Выполните действия в этом ответе , которые аналогичны приведенным выше, но требуют, чтобы из командной строки ( git push origin <branch> -f) выполнялась дополнительная команда для принудительного нажатия на ветвь. Я бы рекомендовал прочитать все это и применить необходимую осторожность!

Стив Чемберс
источник
из всех ответов - это наиболее подходящий для всех новичков git ^^^ (используйте бесплатную программу SourceTree и примените «Rebase children of» к коммиту перед тем, который вы хотите отредактировать)
наслаждайтесь
127

Если вы просто хотите отредактировать последний коммит, используйте:

git commit --amend

или

git commit --amend -m 'one line message'

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

git rebase -i <hash of one commit before the wrong commit>

Git rebase редактирование

В файле, как показано выше, напишите edit/e или одну из других опций и нажмите «Сохранить и выйти».

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

git commit --amend

Сохраните и выйдите из этого и введите

git rebase --continue

перейти к следующему выбору, пока не закончите со всеми вашими выборами.

Обратите внимание, что эти вещи изменяют все ваши хэши SHA после этой конкретной фиксации.

Shubham Chaudhary
источник
2
git rebase -i <хэш одного коммита до неправильного коммита> работает для меня. Спасибо.
Viraths
127

Если вы хотите изменить только ваше последнее сообщение, вы должны использовать --onlyфлаг или его ярлык -oс commit --amend:

git commit --amend -o -m "New commit message"

Это гарантирует, что вы случайно не улучшите свой коммит с помощью инсценировки. Конечно, лучше иметь правильную $EDITORконфигурацию. Затем вы можете опустить -mопцию, и Git предварительно заполнит сообщение коммита старым. Таким образом, это может быть легко отредактировано.

Дэвид Онгаро
источник
1
«Верхний» ответ не отвечает на вопрос. Это просто дает общее представление о git commit --amend. Вопрос был очень конкретным, поэтому дольше! = Лучше. Решающее упоминание о -oфлаге, вероятно, будет похоронено в остальной части информации. Мне также не удобно редактировать ответ, у которого уже так много голосов.
Дэвид Онгаро
2
При этом вы можете редактировать верхний ответ, поскольку существует реальная опасность того, что люди используют его в качестве «правильного» ответа. Может случиться так, что вы исправите ваш коммит с помощью инсценировки - это случилось со мной, и это действительно раздражает, когда вы сталкиваетесь с этим. Но все же количество не является гарантией правильности. Ни по количеству ответов, ни по количеству голосов.
Дэвид Онгаро
1
Я бы не пошел так далеко, чтобы сказать, что верхний ответ «неправильный» и что он «не отвечает на вопрос». Это определенно работает и отвечает на вопрос, вам просто нужно убедиться, что у вас нет внесенных изменений, когда вы пытаетесь внести изменения. Но я понимаю вашу мысль о необходимости предупреждать людей об этом. Я отредактирую это позже, если у меня будет время.
1
Чтобы быть справедливым: хотя --onlyопция с --amendдоступна с git 1.3.0, она не работала правильно, пока не была исправлена ​​в 1.7.11.3 ( ea2d4ed35902ce15959965ab86d80527731a177c ). Таким образом, правильный ответ еще в 2008 году, вероятно, было что - то вроде: git stash; git commit --amend; git stash pop.
Дэвид Онгаро
103

Обновите свое последнее неверное сообщение о коммите новым сообщением о коммите в одной строке:

git commit --amend -m "your new commit message"

Или попробуйте Git reset, как показано ниже:

# You can reset your head to n number of commit
# NOT a good idea for changing last commit message,
# but you can get an idea to split commit into multiple commits
git reset --soft HEAD^

# It will reset you last commit. Now, you
# can re-commit it with new commit message.

Использование сброса для разделения коммитов на коммиты меньшего размера

git reset может помочь вам разбить один коммит на несколько коммитов:

# Reset your head. I am resetting to last commits:
git reset --soft HEAD^
# (You can reset multiple commit by doing HEAD~2(no. of commits)

# Now, reset your head for splitting it to multiple commits
git reset HEAD

# Add and commit your files separately to make multiple commits: e.g
git add app/
git commit -m "add all files in app directory"

git add config/
git commit -m "add all files in config directory"

Здесь вы успешно разбили свой последний коммит на два коммита.

przbadu
источник
3
Если все, что вы хотите сделать, это отредактировать сообщение вашего последнего коммита, то для этой цели используется программный сброс, а затем - избыточное уничтожение . Просто используйте git commit --amend, точно так, как написано в топ-ответе . Кроме того, git reset --soft HEAD^работает аналогично программному сбросу в этом предыдущем ответе , потому что они оба возвращаются к первому родительскому коммиту.
3
Я лишь добавляю git resetрешение, чтобы дать идею разбить одно сообщение о коммите на несколько сообщений о коммите. Потому что я столкнулся с этой проблемой, когда я начал использовать git. Иногда это может быть очень полезным. :)
przbadu
87

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

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

Допустим, вы хотите изменить свои пять последних коммитов, а затем введите это в терминале:

git rebase -i HEAD~5

* Где 5 - количество сообщений о коммитах, которые вы хотите изменить (поэтому, если вы хотите изменить с 10-го на последний коммит, введите 10).

Эта команда приведет вас в Vim, где вы сможете «редактировать» историю коммитов. Вы увидите свои последние пять коммитов наверху, как это:

pick <commit hash> commit message

Вместо pickвас нужно написать reword. Вы можете сделать это в Vim, набрав i. Это заставляет вас войти в режим вставки . (Вы видите, что находитесь в режиме вставки по слову INSERT внизу.) Для фиксации, которую вы хотите изменить, введите rewordвместо pick.

Затем вам нужно сохранить и выйти из этого экрана. Вы делаете это, сначала переходя в «командный режим» нажатием Escкнопки (вы можете проверить, что находитесь в командном режиме, если слово INSERT внизу исчезло). Затем вы можете ввести команду, набрав :. Команда для сохранения и выхода есть wq. Так что, если вы введете, :wqвы на правильном пути.

Затем Vim просматривает каждое сообщение коммита, которое вы хотите перефразировать, и здесь вы можете изменить сообщения коммита. Вы сделаете это, войдя в режим вставки, изменив сообщение фиксации, войдя в командный режим, сохраните и выйдите. Сделайте это пять раз, и вы вне Vim!

Затем, если вы уже выдвинули свои неправильные коммиты, вам нужно git push --forceих перезаписать. Помните, что git push --forceэто довольно опасная вещь, поэтому следите за тем, чтобы никто не извлекал данные с сервера, поскольку вы выдвинули неверные коммиты!

Теперь вы изменили свои сообщения коммитов!

(Как вы видите, я не настолько опытен в Vim, поэтому, если я использовал неправильный «жаргон», чтобы объяснить, что происходит, смело поправляйте меня!)

Marijn
источник
4
<nitpick>В переполнении стека нет «тем», потому что это не дискуссионный форум, а только «вопросы», «ответы» и «сообщения». </nitpick>, Кроме того, не все версии Vim одинаковы, не все из них позволяют удалять символы в режиме вставки (в некотором смысле, имеет смысл, верно?). Если вы хотите всегда иметь возможность удалять символы в Vim, Xи xбудете это делать (мало xудаляет символы перед курсором, Xудалит сзади). Если вы делаете ошибки, вы можете использовать uнесколько раз, чтобы отменить. Наконец, rэто сокращение для rewordинтерактивного редактора ребаз.
1
Для изменения слова в vim cwнабирается в его начале (хотя вопрос не о vim, я согласен).
Ярослав Никитенко
Вам не нужно использовать эту мерзость . Вы можете установить в своем редакторе git что-то вменяемое и удобное для пользователя, например nanomcedit Midnight Commander.
Дан Даскалеску
79

Вы можете использовать git-rebase-reword

Он предназначен для редактирования любого коммита (не только последнего) так же, как commit --amend

$ git rebase-reword <commit-or-refname>

Он назван в честь действия по перебазированию в интерактивном режиме для изменения коммита: «reword». Смотрите этот пост и человек -сече- интерактивный Режим-

Примеры:

$ git rebase-reword b68f560
$ git rebase-reword HEAD^
albfan
источник
6
Это требует установки внешней программы. На мой взгляд, было бы лучше научиться более эффективно использовать встроенные инструменты и псевдонимы. Я бы набрал: g c; g rb -i @~9(commit и rebase), переместил новый коммит туда, куда я хочу, изменил commitна f( fixup) и сохрани. Если бы вы хотели что-то более быстрое, вы могли бы использовать псевдоним git commit --fixup=<commit>; git rebase -i --autosquash <commit>^
Zaz
79

Я добавил псевдонимы reciи recmдля recommit (amend)этого. Теперь я могу сделать это с помощью git recmили git recm -m:

$ vim ~/.gitconfig

[alias]

    ......
    cm = commit
    reci = commit --amend
    recm = commit --amend
    ......
Чу-Сян Лай
источник
57

Я понял, что вставил коммит с опечаткой. Чтобы отменить, я сделал следующее:

git commit --amend -m "T-1000, advanced prototype"
git push --force

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

neoneye
источник
7
Ничто никогда не перезаписывается в git. В этом случае указатель ветви будет установлен на ваш новый коммит, а старый коммит устареет, если на него не останется никаких ссылок, и он может быть очищен через несколько недель. (До тех пор другие люди все еще могут найти и сослаться на него, например, заглянув в журнал.)
Дэвид Онгаро
51

Мне нравится использовать следующее:

  1. git status
  2. git add --all
  3. git commit -am "message goes here about the change"
  4. git pull <origin master>
  5. git push <origin master>
Кедар Адхикари
источник
46

Если вы не отправили код в удаленную ветку ( GitHub / Bitbucket ), вы можете изменить сообщение коммита в командной строке, как показано ниже.

 git commit --amend -m "Your new message"

Если вы работаете над определенной веткой, сделайте это:

git commit --amend -m "BRANCH-NAME: new message"

Если вы уже нажали код с неправильным сообщением, и вам нужно быть осторожным при изменении сообщения. То есть, после того, как вы измените сообщение коммита и попытаетесь нажать его снова, у вас возникнут проблемы. Чтобы сделать это гладко, выполните следующие действия.

Пожалуйста, прочитайте весь мой ответ, прежде чем делать это.

git commit --amend -m "BRANCH-NAME : your new message"

git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

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

 git commit --amend -m "BRANCH-NAME : your new message"
 git pull origin BRANCH-NAME
 git push -f origin BRANCH-NAME

Это лучший метод при изменении сообщения фиксации, если оно уже было отправлено.

Прабхакар Ундурти
источник