Что случилось
Вы имеете в виду изменить, а не добавить, верно? Я собираюсь притвориться, что это было на ветке под названием master, для удобства. Вот как выглядит ваш репозиторий:
A---B' (master)
\
\-B---C---D
Коммиты Git явно зависят от их родителей - один и тот же патч поверх другого родителя - это другой коммит.
Как восстановить
Вы можете восстановить предыдущую позицию несколькими способами. Есть хороший сокращенный вариант для предыдущих позиций, который вы можете использовать, чтобы непосредственно проверить его или создать ветку:
git checkout master@{1}
git branch oldmaster master@{1}
Предполагается, что это первая предыдущая позиция. Это может быть второй (master@{2}
) ... или, если вы знаете, когда это было, вы можете использовать master@{7:35}
или master@{23.hours.ago}
. Краткое описание этих форм см. В разделе «Определение редакций» man git-rev-parse
( онлайн здесь ).
Если вы не уверены, как именно к нему добраться, попробуйте
git reflog show master
Это даст вам список предыдущих позиций на master
, и вы сможете суметь узнать из описаний, какое вы хотите (или, может быть, попробовать несколько). Вы можете просто скопировать хэши из списка и использовать git checkout
или git branch
, как указано выше.
Что вы должны были сделать
Предупреждение: редактирование истории - плохая идея, если она уже была опубликована - в этом случае вам следует просто зафиксировать исправление. Да, некрасиво разделять его на две коммиты в репозитории, но другие пользователи должны иметь возможность доверять тому, что они видели в публичном репо, чтобы не изменяться!
Тем не менее, чтобы сделать этот конкретный вид редактирования истории, вам нужно интерактивное обновление:
git rebase -i master~4 master
master~4
представляет собой коммит за четыре коммита до кончика мастера. Здесь вы можете использовать любую форму, какую захотите - может быть, это другая ветка, может быть хеш коммита - что угодно.
Откроется в редакторе список коммитов, с которыми вы играете:
pick <hash-A> <message-A>
pick <hash-B> <message-B>
pick <hash-C> <message-C>
pick <hash-D> <message-D>
# Rebase <hash-A^>..<hash-D> onto <hash-A^>
#
# Commands:
# p, pick = use commit
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
Текст закомментированной справки довольно понятен. В этом случае вы хотите изменить 'pick' на 'edit' в строке коммита B. сохранить и выйти. Начнется ребазирование, и оно будет приостановлено после применения B
, чтобы позволить вам внести изменения. Вы будете делать то, что вам нужно, добавить, использовать git commit --amend
, а затем git rebase --continue
. Это будет применяться C
и D
, и все будет готово. Если в середине что-то пойдет не так, используйте git rebase --abort
, чтобы вернуться к тому, с чего вы начали.
Перебазировка может быть довольно страшной - например, не удаляйте случайно строки в этом списке! Если вам это пока не удобно, рекомендуется интенсивно использовать gitk
и резервные имена ветвей.