В чем разница между git merge - сквош и git cherry-pick?

Если я работаю в стандартном рабочем процессе с основными функциями, в чем будет разница между разделением ветви функций на мастер и выбором вишни на мастер?

Примеры веток:

m1 -- m2                 master
  \-- f1 -- f2           feature

Я думаю, что оба имеют одинаковый выход, т.е.

m1 -- m2 -- -- -- m3     master
  \-- f1 -- f2           feature

1 ответ

Есть два важных различия между merge --squash а также cherry-pick:

1. Вишня выбирает только один коммит

То есть, если у вас есть ситуация, которую вы описали выше, и вы (на master) сделать git cherry-pick feature Полученная ветка будет выглядеть так:

m1 -- m2 -- f2’           master
  \-- f1 -- f2           feature

Это означает, что изменения от f1 не присутствуют на мастере (и сбор вишни может быть неудачным, если f2 зависит от них.

2. Сбор вишни создает коммит

merge --squash не сразу фиксирует, а создает сводку всех изменений и готовит их к фиксации. По сути, это патч ваших полных изменений ветки, git diff m1..feature показал бы.

На моей машине быстрый тест дал такой вывод:

$ test git:(master) git merge --squash testbranch
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested

Важным моментом здесь является "не обновлять HEAD", что означает "я не передал то, что сделал". Второе предложение на самом деле гораздо удобнее для пользователя...

Эта функция удобна, если вы хотите разрабатывать пошагово (совершая все маленькие шаги, которые привели к решению, например, с фиксацией после каждого успешного запуска теста. В этом случае ваша история, вероятно, будет загромождена сотнями коммиты в одну строку. Так что, вероятно, лучше время от времени делать коммит-сквош-коммит (например, после того, как вы разработали один бит функциональности).

Выбор вишни позволяет применить изменение, внесенное другим коммитом в вашу текущую ветку.

Слияние со сжатием (с последующим фиксированием) делает то же самое, что и слияние (в отношении результирующего рабочего каталога и индекса, а не истории).

Вот пример (некоторые выходные данные git не показаны).

Настроить

$ git init
$ echo sahred file > shared-file.txt
$ git add .
$ git commit -m 'added shared-file.txt in master branch'
$ git checkout -b dev
$ touch dev.txt
$ git add .
$ git commit -m 'added dev.txt in dev branch'
$ echo shared file > shared-file.txt 
$ git add .
$ git commit -m 'fixed typo in shared-file.txt in dev branch'
$ git checkout master

Теперь у нас есть филиал dev с дополнительным файлом (dev.txt) и где опечатка в shared-file.txtфиксированный. Мы вернулись кmaster ветка для сравнения сбора вишен и слияния.

Сбор вишни

$ git cherry-pick dev
$ git log --oneline --graph
* 8019b05 (HEAD -> master) fixed typo in shared-file.txt in dev branch
* 7dbd3aa added shared-file.txt in master branch
$ ls
shared-file.txt
$ cat shared-file.txt 
shared file

Как видите, после выбора изменения последняя фиксация вdev введена ветка (исправление опечатки в shared-file.txt) но дополнительный файл dev.txt не был перенесен, потому что он не был создан в последней фиксации в dev ветвь.

Теперь мы отменяем выбор и сравниваем с результатом слияния.

Слияние (с раздавливанием и фиксацией)

$ git reset HEAD~1 --hard # undo cherry-pick
$ git merge dev --squash
$ git commit -m 'merged dev'
$ git log --oneline --graph
* 01dd755 (HEAD -> master) merged dev
* 7dbd3aa added shared-file.txt in master branch
$ ls
dev.txt  shared-file.txt
$ cat shared-file.txt 
shared file

Как видите, и опечатка была исправлена, и dev.txtбыл перенесен. Это связано с тем, что слияние со сжатием (с последующим фиксированием) совпадает с обычным слиянием двух коммитов в отношении результирующего рабочего каталога и индекса (но, конечно, не истории).

Другие вопросы по тегам