Я знаю два способа изменить сообщение коммита в git.
Первый — это git amend
, который работает только для последнего коммита. Поскольку я хочу иметь возможность напрямую изменять старые сообщения фиксации, это не то, что я ищу.
Второй — это интерактивная перебазировка, как описано, например, в этом ответе, которая также может изменять сообщения фиксации старых коммитов. Процедура заключается в использовании
git rebase -i HEAD~n
где я должен вручную подсчитать размер n
для моего конкретного случая, затем прокрутить список всех этих коммитов и изменить один коммит с pick
на reword
, затем, наконец, ввести новое сообщение коммита и принудительно нажать.
Честно говоря, пока это работает, делать это безумно сложно и утомительно. Итак, мой вопрос: есть ли более простой в использовании вариант (возможно, в виде псевдонима), где эта процедура автоматически выполняется за один шаг?
В идеале я хотел бы иметь такую команду:
git reword <hash> -m "New commit message"
и после этого просто принудительно нажмите. Это возможно?
Редактировать: я хочу избавиться от интерактивности, потому что я хочу программно автоматизировать некоторые команды git из моей программы. Необходимость вручную взаимодействовать с git во время этого процесса сводит на нет цель такой автоматизации.
Вы знаете, что HEAD~n
— это просто синтаксис ревизии? Вы можете указать версию, как хотите, просто используя <hash>
Связанный: Как запустить git rebase --interactive в неинтерактивном режиме?
@DanielA.White Не понимаю, как это помогает. Как я уже писал, я хочу изменить старые сообщения, а не только последнее.
@ Brian61354270 Нет, я не знал об этом. Это лучше моего решения, спасибо.
amend работает с любым коммитом, а не только с последним. И последующая перебазировка не обязательно должна быть интерактивной.
Вы можете ссылаться на ревизию непосредственно перед целевым коммитом вместо того, чтобы вручную отсчитывать коммиты из HEAD. Бегать
$ git rebase -i <rev>^
где <rev>
— коммит, который вы хотите перефразировать.
Оттуда вам все равно нужно будет завершить перебазирование вручную (измените целевую строку на reword
и запустите git rebase --continue
). Вы можете дополнительно автоматизировать этот процесс с помощью некоторой комбинации умных сценариев оболочки и GIT_SEQUENCE_EDITOR
, но я не уверен, что рекомендовал бы это делать. Перебазирование — чрезвычайно инвазивная операция в git. Наличие истории, которую вы собираетесь полностью переписать, на короткое время на экране и возможность прервать ее — это хорошо, и это может сэкономить вам много слез и git reflog
часов в будущем.
Спасибо, это лучше, чем раньше. Тем не менее, я все еще ищу неинтерактивное решение, потому что я хочу сделать этот скрипт на основе (я отредактировал свой вопрос, чтобы включить эту информацию). Я взгляну на GIT_SEQUENCE_EDITOR, но я действительно не понимаю, почему мы можем без проблем сбрасывать и принудительно вставлять в одну строку (обе операции также опасны), но не делать такую простую вещь, как редактирование сообщения коммита. .. (Я знаю, что это переписывает историю, но это настолько распространенная проблема, что, по моему мнению, тем не менее, у нее должно быть более простое в использовании решение)
@SampleTime К счастью, на помощь пришла вязаная пряжа :). Хотя я бы предположил, что аппаратный сброс и принудительное нажатие менее неприятны, чем перебазирование, поскольку оба они только перемещают ссылки и их легко исправить, просто переместив ссылку назад. Перебазирование, с другой стороны, перемещает ссылки и записывает неограниченное количество новых объектов.
Мне нравится четко указывать, какие шаги я предпринимаю, особенно для «деструктивных» операций, таких как перебазирование. Имея это в виду, то, что вам нужно, определенно возможно, используя переменную GIT_SEQUENCE_EDITOR. Он определяет «редактор», используемый для редактирования списка задач интерактивной перебазировки. Редактор не обязательно должен быть интерактивным редактором и может быть любым исполняемым файлом, который изменяет текстовый файл, например:
GIT_SEQUENCE_EDITOR='sed -i "1s/^pick/reword/"' git rebase -i commit-you-want-to-amend^
При перемещении до родительского коммита, который вы хотите изменить, этот коммит будет первым в списке, и вы можете легко переключить sed
на pick
с помощью простого сценария sed.
Все это можно легко преобразовать в псевдоним:
git config --global alias.reword '!f() {
GIT_SEQUENCE_EDITOR = "sed -i 1s/^pick/reword/" git rebase -i "$1^";
}; f'
Тогда reword
.
Вышеупомянутое по-прежнему требует, чтобы вы вводили сообщение фиксации вручную. Если вы хотите избежать и этого, вам может помочь хитрый лайфхак с git reword commit-you-want-to-amend
:
git config --global alias.reword '!f() {
GIT_SEQUENCE_EDITOR = "sed -i 1s/^pick/reword/" GIT_EDITOR = "printf \"%s\n\" \"$2\" >" git rebase -i "$1^";
}; f'
Обратите внимание на стандартное перенаправление вывода GIT_EDITOR
в значении >
.
Тогда звоните как GIT_EDITOR
.
Вторым вариантом может быть использование git replace, которое сохраняет исходные коммиты, но вместо этого использует ссылки замены Git для отображения других коммитов.
В более поздних версиях Git самым простым вариантом кажется git commit --fixup=reword:commit:
--fixup=[(amend|reword):]<commit>
Создайте новый коммит, который «исправляет»
<commit>
при применении сgit rebase --autosquash
. […]--fixup=reword:<commit>
создает "исправлять!" коммит, который заменяет сообщение журнала<commit>
своим собственное сообщение журнала, но не вносит изменений в содержимое<commit>
.[…]
--fixup=reword:<commit>
— это сокращение от--fixup=amend:<commit> --only
. Это создает "исправление!" зафиксируйте только с сообщением журнала (игнорируя любые изменения, внесенные в индекс). При раздавливанииgit rebase --autosquash
он заменяет сообщение журнала<commit>
без внесения каких-либо других изменений.
Итак, вы должны запустить следующие команды:
git commit --fixup=reword:commit-to-amend
git rebase -i --autosquash commit-to-amend^
Но это не позволяет указать сообщение фиксации с помощью аргументов CLI, поэтому нам нужно имитировать поведение Git, создав правильное сообщение фиксации, требуемое autosqash:
git config alias.reword2 '!f() {
git commit --allow-empty --only -m "amend! $1
$2" &&
GIT_SEQUENCE_EDITOR=: git rebase -i --autosquash "$1^";
}; f'
А затем выполняется с помощью git reword commit-to-amend 'your new message'
.
Использовать исправление в качестве флага