Изменить сообщение git commit без интерактивной перебазировки

Я знаю два способа изменить сообщение коммита в git.

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

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

git rebase -i HEAD~n

где я должен вручную подсчитать размер n для моего конкретного случая, затем прокрутить список всех этих коммитов и изменить один коммит с pick на reword, затем, наконец, ввести новое сообщение коммита и принудительно нажать.

Честно говоря, пока это работает, делать это безумно сложно и утомительно. Итак, мой вопрос: есть ли более простой в использовании вариант (возможно, в виде псевдонима), где эта процедура автоматически выполняется за один шаг?

В идеале я хотел бы иметь такую ​​​​команду:

git reword <hash> -m "New commit message"

и после этого просто принудительно нажмите. Это возможно?

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

Использовать исправление в качестве флага

Daniel A. White 29.07.2023 17:33

Вы знаете, что HEAD~n — это просто синтаксис ревизии? Вы можете указать версию, как хотите, просто используя <hash>

Brian61354270 29.07.2023 17:33

@DanielA.White Не понимаю, как это помогает. Как я уже писал, я хочу изменить старые сообщения, а не только последнее.

SampleTime 30.07.2023 09:25

@ Brian61354270 Нет, я не знал об этом. Это лучше моего решения, спасибо.

SampleTime 30.07.2023 09:26

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

user7860670 30.07.2023 10:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
54
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете ссылаться на ревизию непосредственно перед целевым коммитом вместо того, чтобы вручную отсчитывать коммиты из HEAD. Бегать

$ git rebase -i <rev>^

где <rev> — коммит, который вы хотите перефразировать.

Оттуда вам все равно нужно будет завершить перебазирование вручную (измените целевую строку на reword и запустите git rebase --continue). Вы можете дополнительно автоматизировать этот процесс с помощью некоторой комбинации умных сценариев оболочки и GIT_SEQUENCE_EDITOR, но я не уверен, что рекомендовал бы это делать. Перебазирование — чрезвычайно инвазивная операция в git. Наличие истории, которую вы собираетесь полностью переписать, на короткое время на экране и возможность прервать ее — это хорошо, и это может сэкономить вам много слез и git reflog часов в будущем.

Спасибо, это лучше, чем раньше. Тем не менее, я все еще ищу неинтерактивное решение, потому что я хочу сделать этот скрипт на основе (я отредактировал свой вопрос, чтобы включить эту информацию). Я взгляну на GIT_SEQUENCE_EDITOR, но я действительно не понимаю, почему мы можем без проблем сбрасывать и принудительно вставлять в одну строку (обе операции также опасны), но не делать такую ​​простую вещь, как редактирование сообщения коммита. .. (Я знаю, что это переписывает историю, но это настолько распространенная проблема, что, по моему мнению, тем не менее, у нее должно быть более простое в использовании решение)

SampleTime 30.07.2023 09:33

@SampleTime К счастью, на помощь пришла вязаная пряжа :). Хотя я бы предположил, что аппаратный сброс и принудительное нажатие менее неприятны, чем перебазирование, поскольку оба они только перемещают ссылки и их легко исправить, просто переместив ссылку назад. Перебазирование, с другой стороны, перемещает ссылки и записывает неограниченное количество новых объектов.

Brian61354270 30.07.2023 14:47
Ответ принят как подходящий

Мне нравится четко указывать, какие шаги я предпринимаю, особенно для «деструктивных» операций, таких как перебазирование. Имея это в виду, то, что вам нужно, определенно возможно, используя переменную 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'.

Другие вопросы по теме