Как в Git перенести commit из одной ветки в другую?
Нередко возникает ситуация, когда срочно требуется выполнить небольшую задачу. Разработчик быстро пробегается глазами по ТЗ и старается максимально оперативно вникнуть в суть задачи. При этом можно попросту забыть создать новую ветку, и понять об ошибке уже после финального каммита.
В такой ситуации, когда возникает необходимость перенести commit из одной ветки в другую на помощь приходит команда git cherry-pick
, применяющая к дереву проекта изменения, которые были внесены указанным каммитом.
Рассмотрим ситуацию на примере. Мы находились в master
и сделали в него случайно коммит. Тогда чтобы вынести его в отдельную ветку и отправить на merge request нам потребуется выполнить следующие команды:
1. Смотрим историю изменений и запоминаем хэш коммита <hash-commit-0>
, соответствующего правильному состоянию ветки master
, то есть когда ещё в неё не было добавлено лишних коммитов по ошибке.
git log
2. Также следует запомнить хэш коммита <hash-commit-1>
, который был лишним в ветке master
. Иногда бывает, что лишними оказываются сразу несколько коммитов, тогда если они расположены последовательно друг за другом следует запомнить самый давний <hash-commit-begin>
и самый последний <hash-commit-end>
.
3. Перейдём на найденный коммит <hash-commit-0>
. Другими словами переходим на то состояние ветки master
, от которого нам нужно создать новую ветку.
git checkout <hash-commit-0>
4. Создадим новую ветку, в которую планируется вынести неверно расположенный коммит, и перейдем на неё.
git checkout -b <name-branch>
5. Переносим коммит в новую ветку.
git cherry-pick <hash-commit-1>
В случае, когда необходимо перенести последний коммит ветки master
, можно вместо хэша коммита просто написать master
, поскольку в данный момент указатель master
ссылается на последний коммит.
git cherry-pick master
Если же нужно перенести не один, а несколько подряд идущих коммитов от <hash-commit-begin>
до <hash-commit-end>
, то это делается похожим образом.
git cherry-pick <hash-commit-begin>..<hash-commit-end>
Если же вы хотите, чтобы при переносе изменений коммит не создавался, то используйте параметр -n (—no-commit):
git cherry-pick -n d112ecf96
Как и при операции git rebase
в процессе переноса коммита могут возникнуть конфликты. Как и при обычном git merge
их следует разрешить, добавить изменения в индекс с помощью git add
, а затем продолжить запустив git cherry-pick --continue
.
6. Теперь когда коммиты перенесены в ветку <name-branch>
, следует удалить их из ветки master
. Поэтому переключаемся на ветку master
git checkout master
Смещаем указать master
на коммит <hash-commit-0>
git reset --hard <hash-commit-0>
Благодарю за одновременно подробную и лаконичную статью, — очень выручила!