Добавить изменения в предыдущий коммит с помощью Magit

44

У меня есть 2 коммита, А затем Б, готовые к толканию. Я понимаю, что забыл добавить что-то в А.

Как я могу добавить это изменение в A с помощью Magit? Я даже не знаю, какую часть документации Git мне следует посмотреть.

Матье Маркес
источник

Ответы:

69

Давайте на мгновение представим, что вы хотите добавить что-то к HEADкоммиту, например, «второй коммит B» в вашем примере.

Во всплывающем окне коммитов cесть привязка « aAmend». Нажатие этой клавиши «исправит» поэтапные изменения в HEADкоммите. Поскольку коммиты не изменяемы в Git, это фактически заменит старый коммит новым коммитом. Появится буфер со старым сообщением о фиксации, так что вы можете изменить его, если добавленное изменение также требует настройки сообщения. Как всегда, нажмите, C-c C-cкогда закончите редактирование сообщения. Это эквивалентно запуску git commit --amendв командной строке.

  • a Изменить - добавить поэтапные изменения HEADи отредактировать сообщение о коммите.

Поскольку часто бывает так, что вам нужно только изменить изменение или сообщение, Magit предлагает два дополнительных варианта:

  • e Расширить - добавить поэтапные изменения, HEADне редактируя сообщение фиксации
  • w Reword - изменить сообщение, HEADне добавляя в него поэтапные изменения

Если вы хотите отредактировать коммит, которого нет HEAD, вышеприведенное не сработает. Эти команды всегда «изменяют» (то есть заменяют) HEADкоммит. Git не предоставляет ни одной команды для изменения коммита, кроме HEADтого, что это немного сложнее.

Magit ли обеспечить такую команду, а потому , что есть ситуации , в которых желательно делать это в несколько этапов, мы обсудим , что первый.

Изменение коммита, отличного от, HEADможно разбить на три этапа:

  1. Временно сделать этот другой commit ( A) HEAD.
  2. Модифицируйте HEAD(как описано выше), в результате чего получите коммит A'.
  3. Скажите Git повторно применить последующие коммиты A, но сверху A'.

Это можно сделать с помощью интерактивной перебазировки. Введите, rчтобы показать всплывающее окно rebase. Затем напечатайте, mчтобы вызвать вариант rebase «edit a commit». Появляется буфер с последними коммитами. Перейдите к коммиту, который вы хотите изменить, и введите его, C-c C-cчтобы выбрать. Затем Git перематывает историю на этот коммит и показывает информацию о текущей перебазировке в буфере состояния.

Изменить, HEADкак описано выше. Затем скажите Git, что вы сделали, набрав r r. Если A'и Bконфликт, то перебазирование остановится на Bи вам придется разрешить конфликт. После этого нажмите, r rчтобы продолжить.

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


Git позволяет создавать "фиксации фикса" используя git commit --fixup A. Это создает новый коммит, в котором записываются изменения, которые «должны были быть сделаны в другом коммите». Этот коммит становится новым HEAD. Там также существует --squashвариант. Для получения информации о различиях см. git-commitСправочную страницу.

Чтобы на самом деле объединить Aкоммит и новый коммит, A'а затем снова применить Bего, вы должны использовать rebase. Magit предоставляет удобную команду для этого r f.

Основное отличие от вышеуказанного подхода заключается в том, что здесь мы сначала создаем новый коммит, а затем перезагружаем его, чтобы объединить его с «целью» и повторно применить B. Выше мы начали с перебазирования вместо совершения.

В Magit --fixupи --squashварианты, и варианты доступны во всплывающем окне фиксации, на fи s. Но Magit также предоставляет «мгновенные» варианты команд fixup и squash on Fи S. Эти варианты создают новый коммит, такой как «не мгновенные» варианты, но затем они мгновенно комбинируют фиксацию фиксации с целевым коммитом, используя rebase, без необходимости вызывать другую команду.

«Мгновенное исправление» ( c F) по сути то же самое, что и «extension HEAD» ( c e), за исключением того, что оно работает для любого коммита, а не только HEAD.


Дальнейшее чтение:

Tarsius
источник
Кристально чистый! Спасибо, потрясающий пакет BTW.
Матье Маркес
1
Ну, я думаю, что во второй половине моего ответа есть какие-то мягкие детали. Но чтобы избежать этого, мне пришлось бы удвоить длину этого длинного ответа, поэтому я рад, что это
сработает
Спасибо за этот ответ Tarsius, это действительно работает для меня.
anquegi
Ясность первой половины этого объяснения делает чтение второй половины, за которой гораздо труднее следовать, довольно неприятно!
Лин Хедли
git-commitСтраница man перенаправляет на git-rebase(1)эти строки: предлагаемое сообщение о коммите для свернутого коммита - это конкатенация сообщений коммита первого коммита и сообщений с командой «squash», но пропускает сообщения коммитов коммитов с «fixup» команда. IOW, используйте fixup, если вы просто хотите исправить код в предыдущем коммите, используйте squash, если вы также хотите исправить сообщение фиксации.
Ясуши Сёдзи,
3

git commit --amend –C HEADэто команда Git, которую вы хотите искать, и с помощью которой вы можете вносить исправления в Magit C-c C-a.

Райан
источник
Я использую последнюю версию Magit, C-c C-aот более старой версии (я думаю). Кроме того, я не вижу никаких следов "исправления" в буфере помощи ( ?).
Матье Маркес
См . Ответ Реми для эквивалента Magit 2.x.
npostavs
3

Итак, один рабочий процесс:

  • внести изменения
  • c (commit) f (fixup - выберите фиксацию вашего исправления)

затем

  • r (rebase) -a (автосквош, можно по умолчанию) i (интерактивно)

Autosquash автоматически переместит все коммиты! Fixup в нужное место и установит их для подавления при повторном основании.

stsquad
источник
Единственное, что я сделал, что ты не сказал, - это вставил между первой и второй пулями. Удар iдает мне Cannot rebase: Your index contains uncommitted changes. Please commit or stash them.. За исключением того, что у меня нет никаких незафиксированных изменений. : /
Матье Маркес
Попробовал еще раз после вытягивания Proceed despite merge in rebase range? [c]ontinue, [s]elect other, [a]bort. Это пытается сказать мне, что мое исправление может покарать предстоящее слияние?
Матье Маркес
@MathieuMarques: «За исключением того, что у меня нет никаких незафиксированных изменений» - Git думает, что вы делаете. Обратите внимание, что сообщение предлагает поэтапные изменения, а не неустановленные. Re: merge in rebaseсм. Ошибки под git help rebase. Я предлагаю сделать исправление, прежде чем тянуть вверх по течению.
npostavs
1

Для внесения изменений в последний коммит это "c a". Исправление для исправления некоторых старых коммитов.

Рэй
источник
В таком случае я совершил А потом Б. Обновил пост для наглядности.
Матье Маркес