Git log list фиксирует за исключением вишневого выбора из первой ветки - PullRequest
2 голосов
/ 24 мая 2019

Например, у меня есть эта история коммитов

git history enter image description here

Скажем, в какой-то момент release1 был выпущенк производству и через пару дней ветвь release2 была выпущена.

  • ветвь relase1 содержит 2 коммита (4 и 5), которые были выбраны из основной ветки
  • release2 содержит 2 коммита (8 и 9), которые также были выбраны вишней от мастера.

вишня никогда не делалась с аргументом -x.

Я хочуполучить весь коммит для release2, который «еще не был выпущен в тот момент», это означает коммит (6,7,8,9), помеченный зеленым кружком.

Что было бы самым простым способомсделать это?

Пример хранилища в github

Обновление 1 (git cherry)

$ git cherry -v release1 release2
- 91785f2be363244a1da4459746fce6a6ea28c2b5 4
- e88de1f8b62213089b300e3143c4caf509b5c13b 5
- 9d23e9c7e6f769c3bbb44ad42bc7b708b4b0a9e6 6
- 6fb71e4406e0b127e06f6e5b145de8a9d39db01e 7
- 6276becc413494b7724a4dd8b852234f4b71e913 8
- 6dd3b5b75222c02c921c9c20bcaee83e1c8be746 9

С cherry, похоже, у меня все еще есть 4 и 5, оба из которых являются master master

Update 2 (--left-right --cherry-mark)

$ git log --left-right --cherry-mark --pretty=oneline --abbrev-commit  release2...release1
= 6dd3b5b 9
= 6276bec 8
> caa4e2f 5
= 0230a1f 4
= 6fb71e4 7
= 9d23e9c 6
= e88de1f 5
= 91785f2 4

Это дает мне все, кроме 5 вишняотмечен, что мне трудно объяснить

Обновление 3 с непустым коммитом

При первоначальной попытке я создал каждый коммит с --allow-empty.Как указано ниже, он создал хэш пустого дерева.

После воссоздания хранилища с реальным содержимым я получаю желаемый результат с обоими ответами ниже git cherry и --left-right --cherry-mark

Ответы [ 2 ]

3 голосов
/ 24 мая 2019

Обратите внимание, что ваш связанный репозиторий содержит 15 полностью пустых коммитов.Под «пустыми коммитами» я подразумеваю не просто тот тип коммитов без изменений, который git commit --allow-empty позволяет, а скорее полностью пустой: каждый коммит вообще не имеет файлов, просто сообщение коммита.(Точнее, каждый коммит имеет пустое дерево 4b825dc642cb6eb9a060e54bf8d69288fbee4904 в качестве своего дерева.) Таким образом, каждый коммит в вашем хранилище имеет идентификатор патча, эквивалентный каждому другому commit в вашем репозитории.

Это (в основном) объясняет, почему ваш раздел update-2 показывает вывод, который он делает: commit 6dd3b5b эквивалентен патчу для коммитов 6276bec, 9d23e9c и т. д.,Загадка заключается в том, почему коммит caa4e2f не связан с другим коммитом, поскольку он также эквивалентен патчу для любого другого коммита.В любом случае, это почти пример ложного положительного результата, но здесь это действительно больше истинного положительного результата: эти коммиты равны и являются одинаковыми, и поэтому могут быть отброшены без эффекта.


Команды Git для обхода ревизий (git log и git rev-list) могут использовать git patch-id для отметки эквивалента патча коммитов.Это не надежно, но если коммит был выбран без ручного вмешательства, идентификаторы патчей копии и оригинала будут совпадать.

Чтобы увидеть, как это использовать, посмотрите на git log или git rev-list документация (раздел об этом разделен между обоими наборами документации - как и базовая реализация - поэтому я связал только одну).Перейдите к разделу на --left-right опции .Обратите внимание, что --left-right имеет смысл только в сочетании с симметричной разностью , что в данном случае означает использование синтаксиса release1...release2 или release2...release1.Обратите внимание, что между этими двумя именами есть три , а не две точки.

Используя три точки и --left-right, Git будет перечислять коммиты 5 и 4, которые доступны из release1, а также два разных коммита 5 и 4, которые доступны с release2.(Конечно, Git сначала перечислит коммиты 9, 8, 7 и 6, доступные с release2, прежде чем перечислять 5 и 4, достижимые с release2, но не release1. Как вы можете видеть, этовозможно, ошибочно называть эти четыре разных коммита одинаковыми именами. У них разные хэш-идентификаторы по причине: это разные коммиты. Назовите их 5A и 5B и 4A и 4B, если хотите,или, возможно, 5.1 и 5.2, чтобы добавить номер релиза, но дать им разные имена!)

Пока что это не очень помогает: у вас есть Git, показывающий, что вы делаете коммиты 5.1 и 4.1 из release1, помеченный < или > в зависимости от того, с какой стороны из трех точек указано имя release1.И у вас есть Git, показывающий, что вы фиксируете 9, 8, 7, 6, 5.2 и 4.2 из release2, помеченные другим маркером.Но это важнейшая отправная точка.Теперь вы можете переключиться с --left-right на --left-only или --right-only, чтобы сказать Git не показывать мне один из двух наборов, даже если выпо-прежнему перечисляя все коммиты.

С или без опций влево или вправо, вы можете добавить --cherry-mark, чтобы сказать Git: Run git patch-id на каждом коммите в обоих наборах.Если коммит в левом наборе имеет тот же идентификатор патча, что и коммит в правом наборе, пометьте этот коммит знаком равенства =.В противном случае пометьте коммит знаком плюс +.

Итак, в этом случае, если вы запустите:

git rev-list --left-right --cherry-mark --abbrev-commit release2...release1

, вы увидите (при условии хеш-идентификаторакоммит 9 начинается с 999999 и т. д.):

<9999999
<8888888
<7777777
<6666666
=5200000
=4200000
=5100000
=4100000

Таким образом, вы хотите именно те коммиты, которые отмечены <.Используя release1...release2, вы хотите получить именно те коммиты, которые отмечены >.

. Предполагая, что все вышеперечисленное имеет смысл, прочитайте раздел --cherry-pick .

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

1 голос
/ 24 мая 2019

С помощью команды git cherry вы можете найти коммиты, которые не были применены в вышестоящей ветке.Начиная с man git-cherry, синопсис выглядит следующим образом:

git cherry [<upstream> [<head> [<limit>]]]

и описание

Определите, есть ли в <head>..<upstream> коммиты, эквивалентные коммитам в диапазоне <limit>..<head>.

Проверка эквивалентности основана на разнице после удаления пробелов и номеров строк.git-cherry, следовательно, определяет, когда коммиты были «скопированы» с помощью git-cherry-pick(1), git-am(1) или git-rebase(1).

Выводит SHA1 каждого коммита в <limit>..<head> с префиксом - длякоммиты, которые имеют эквивалент в <upstream> и + для коммитов, которые этого не делают.

Итак, чтобы найти коммиты в release2, которые не имеют эквивалентного коммита в release1, вы могли быделать

git cherry release1 release2 | grep '^+' | cut -d' ' -f2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...