В предыдущих ответах рассматривалось использование git rebase -i
для редактирования коммита, который вы хотите разделить, и фиксации его по частям.
Это хорошо работает при разбиении файлов на разные коммиты, но если вы хотите разбить изменения на отдельные файлы, вам нужно знать больше.
Добравшись до коммита, который вы хотите разделить, используя rebase -i
и отметив его как edit
, у вас есть два варианта.
После использования git reset HEAD~
, проходите патчи по отдельности, используя git add -p
, чтобы выбрать те, которые вы хотите в каждом коммите
Отредактируйте рабочую копию, чтобы удалить изменения, которые вам не нужны; совершить это временное состояние; и затем верните полный коммит для следующего раунда.
Вариант 2 полезен, если вы разбиваете большой коммит, поскольку он позволяет вам проверить, что промежуточные версии создаются и работают правильно как часть слияния. Это происходит следующим образом.
После использования rebase -i
и edit
с фиксацией используйте
git reset --soft HEAD~
, чтобы отменить фиксацию, но оставить зафиксированные файлы в индексе. Вы также можете сделать смешанный сброс, пропустив --soft, в зависимости от того, насколько близок к конечному результату ваш первоначальный коммит. Разница лишь в том, начинаете ли вы со всех этапов внесения изменений или со всеми без изменений.
Теперь зайдите и отредактируйте код. Вы можете удалить изменения, удалить добавленные файлы и сделать все, что хотите, чтобы создать первый коммит из серии, которую вы ищете. Вы также можете собрать его, запустить и подтвердить, что у вас есть согласованный набор источников.
Как только вы будете довольны, поставьте / разархивируйте файлы по мере необходимости (мне нравится использовать git gui
для этого) и зафиксируйте изменения через пользовательский интерфейс или командную строку
git commit
Это первый сделанный коммит. Теперь вы хотите восстановить свою рабочую копию в состояние, которое она имела после разделения коммита, чтобы вы могли принять больше изменений для вашего следующего коммита. Чтобы найти sha1 коммита, который вы редактируете, используйте git status
. В первых нескольких строках состояния вы увидите команду rebase, которая выполняется в данный момент, в которой вы можете найти sha1 вашего исходного коммита:
$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
pick 4847406 US135756: add debugging to the file download code
e 65dfb6a US135756: write data and download from remote
(see more in file .git/rebase-merge/done)
...
В этом случае редактируемый мной коммит имеет sha1 65dfb6a
. Зная это, я могу проверить содержимое этого коммита в моем рабочем каталоге, используя форму git checkout
, которая принимает как коммит, так и местоположение файла. Здесь я использую .
в качестве местоположения файла для замены всей рабочей копии:
git checkout 65dfb6a .
Не пропустите точку на конце!
Это будет проверять и обрабатывать файлы такими, какими они были после коммита, который вы редактируете, но относительно предыдущего коммита, который вы сделали, поэтому любые изменения, которые вы уже зафиксировали, не будут частью коммита.
Вы можете либо пойти дальше и зафиксировать его как есть, чтобы завершить разделение, либо снова обойти, удалив некоторые части коммита перед выполнением другого временного коммита.
Если вы хотите повторно использовать исходное сообщение о коммите для одного или нескольких коммитов, вы можете использовать его прямо из рабочих файлов rebase:
git commit --file .git/rebase-merge/message
Наконец, после внесения всех изменений
git rebase --continue
продолжит и завершит операцию перебазирования.