Я разболтал свою историю и хочу внести в нее некоторые изменения. Проблема в том, что у меня есть коммит с двумя несвязанными изменениями, и этот коммит окружен некоторыми другими изменениями в моей локальной (не выдвинутой) истории.
Я хочу разделить этот коммит до того, как выложу его, но большинство руководств, которые я вижу, имеют отношение к разделению вашего последнего коммита или незафиксированных локальных изменений. Возможно ли сделать это с коммитом, который немного утопает в истории, без необходимости «заново делать» мои коммиты с тех пор?
Ответы:
В справочной странице rebase есть руководство по разделению коммитов . Краткое резюме:
Выполните интерактивное обновление, включая целевой коммит (например
git rebase -i <commit-to-split>^ branch
), и отметьте его для редактирования.Когда rebase достигнет этого коммита, используйте
git reset HEAD^
для сброса перед коммитом, но сохраняйте свое рабочее дерево нетронутым.Добавляйте изменения постепенно и фиксируйте их, делая столько коммитов, сколько пожелаете.
add -p
может быть полезно добавить только некоторые изменения в данный файл. Используйте,commit -c ORIG_HEAD
если вы хотите повторно использовать исходное сообщение о коммите для определенного коммита.Если вы хотите протестировать то, что вы делаете (хорошая идея!), Используйте,
git stash
чтобы скрыть часть, которую вы не сделали (илиstash --keep-index
даже прежде, чем вы это сделаете), протестируйте, а затемgit stash pop
верните остальное в рабочее дерево. Продолжайте делать коммиты до тех пор, пока не получите все коммиты изменений, т.е. получите чистое дерево работ.Выполните,
git rebase --continue
чтобы продолжить применение коммитов после коммита, разделенного сейчас.источник
git rebase -i <sha1_of_the_commit_to_split>^ branch
. Иgit gui
это хороший инструмент для задачи расщепления, который можно использовать для добавления разных частей файла в разные коммиты.git add -p
, что может сделать больше, чемgit gui
может в этом отделе (особенно редактирование фрагментов, постановка всего, начиная с текущего фрагмента, и поиск фрагментов с помощью регулярных выражений).Вот как это сделать с Magit .
Скажите, что вы хотите изменить ed417ae; он содержит два несвязанных изменения и скрыт под одним или несколькими коммитами. Нажмите,
ll
чтобы показать журнал, и перейдите к ed417ae:Затем нажмите,
r
чтобы открыть всплывающее окнои
m
изменить коммит в точке.Обратите внимание на
@
то, как теперь существует коммит, который вы хотите разделить - это означает, что HEAD теперь находится на этом коммите:Мы хотим переместить HEAD к родителю, поэтому перейдите к родителю (47e18b3), нажмите
x
(magit-reset-quickly
привязано,o
если вы используетеevil-magit
) и введите, чтобы сказать «да, я имел в виду фиксацию в точке». Ваш журнал должен выглядеть так:Теперь нажмите,
q
чтобы перейти в обычный статус Magit, затем используйте обычнуюu
команду unstage, чтобы удалить из сценария то, что не происходит в первом коммите, зафиксироватьc
остальные как обычно, затем изменитьs
иc
пропустить то, что происходит во втором коммите, и когда это будет сделано: нажмите,r
чтобы открыть всплывающее окнои еще один,
r
чтобы продолжить, и все готово!ll
сейчас показывает:источник
Чтобы разделить коммит
<commit>
и добавить новый коммит до этого и сохранить дату автора<commit>
, выполните следующие действия:Изменить коммит до
<commit>
NB: возможно, это также понадобится для редактирования
<commit>
.Вишневый коврик
<commit>
в указательИнтерактивный сброс ненужных изменений из индекса и сброс рабочего дерева
В качестве альтернативы, просто скопируйте ненужные изменения в интерактивном режиме:
git stash push -p -m "tmp other changes"
Внесите другие изменения (если есть) и создайте новый коммит
При желании повторите пункты 2-4, чтобы добавить дополнительные промежуточные коммиты.
Продолжить ребазинг
источник
Существует более быстрая версия, если вы хотите извлечь содержимое только из одного файла. Это быстрее, потому что интерактивная перебазировка на самом деле больше не является интерактивной (и, конечно, еще быстрее, если вы хотите извлечь из последнего коммита, тогда вообще не нужно перебазировать)
the_file
. Закрытьthe_file
. Это единственное, что вам нужно, все остальное - просто команды git.Этап удаления в индексе:
Восстановите только что удаленные строки обратно в файл, не влияя на индекс !
«SHA1» - это коммит, из которого вы хотите извлечь строки:
Создайте второй, совершенно новый коммит с содержимым для извлечения, восстановленным на шаге 3:
Не редактируйте, не останавливайте / продолжайте - просто примите все:
Конечно, еще быстрее, когда коммит для извлечения является последним коммитом:
Если вы используете,
magit
то шаги 4, 5 и 6 представляют собой одно действие: фиксация, мгновенное исправлениеисточник
Если вы еще не нажали, просто используйте
git rebase
. Более того, используйтеgit rebase -i
для перемещения коммитов в интерактивном режиме. Вы можете переместить оскорбительный коммит на передний план, затем разделить его, как вам нравится, и переместить патчи назад (при необходимости).источник