Git cherry pick и целостность данных

Учитывая, что две ветви разошлись, и конкретная фиксация от одной ветви (и не от всего) должна быть представлена ​​другой, git cherry pick достигает именно этого.

Через некоторое время возникает необходимость полностью объединить две ветви. Как git узнает, что у него уже есть коммит, который был выбран вишней в прошлом, чтобы он не вводил его заново?

2 ответа

Решение

Вы можете прочитать

Git Cherry-pick против Merge Workflow для хорошего сравнения между merge и cherry-pick, особенно в том, что cherry-pick не хранит родительский идентификатор, и, следовательно, не будет знать, что у него уже есть коммит, который был выбран вишней в прошлом, так что он не будет вводить это снова.

а также

http://davitenio.wordpress.com/2008/09/27/git-merge-after-git-cherry-pick-avoiding-duplicate-commits/ о том, как избежать дублирования коммитов в этом случае, используя rebase,

В статье "Как избежать дублирования", упомянутой в ответе Тонио, говорится:

Представьте, что у нас есть основная ветка и ветка b:

  o---X   <-- master
   \
    b1---b2---b3---b4   <-- b

Теперь нам срочно нужны коммиты b1 и b3 в master, а не остальные коммиты в b. Итак, что мы делаем, это проверяем основную ветку и коммиты cherry-pick b1 и b3:

$ git checkout master
$ git cherry-pick “b1’s SHA”
$ git cherry-pick “b3’s SHA”

Результат будет:

  o---X---b1'---b3'   <-- master
   \
    b1---b2---b3---b4   <-- b

Допустим, мы делаем еще один коммит на master и получаем:

  o---X---b1'---b3'---Y   <-- master
   \
    b1---b2---b3---b4   <-- b

Если бы мы теперь слили ветку b в master:

$ git merge b

Мы получили бы следующее:

  o---X---b1'---b3'---Y--- M  <-- master
   \                     /
     b1----b2----b3----b4   <-- b

Это означает, что изменения, внесенные b1 и b3, появятся дважды в истории. Чтобы избежать этого, мы можем сделать ребаз вместо слияния:

$ git rebase master b

Что даст:

  o---X---b1'---b3'---Y   <-- master
                       \
                        b2---b4   <-- b

В заключение:

$ git checkout master
$ git merge b

дает нам:

  o---X---b1'---b3'---Y---b2---b4   <-- master, b

(после этой темы)


ОП добавляет в комментарии:

Но все же кажется, что я не совсем понимаю, как работает rebase... Я имею в виду, даже после перебазирования разве не должны появляться выбранные вишни коммиты?

git commit Страница man явно упоминает:

Если вышестоящая ветвь уже содержит внесенные вами изменения (например, из-за того, что вы отправили по почте исправление, которое было применено в восходящем потоке), то этот коммит будет пропущен.
Например, запустив git rebase master в следующей истории (в которой A и A вводят одинаковый набор изменений, но имеют разную информацию о коммитере):

      A---B---C topic
     /
D---E---A'---F master

приведет к:

               B'---C' topic
              /
D---E---A'---F master

Вы можете определить, присутствует ли коммит на мастере с помощью git cherry master (если вы на topic ветка).

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