Почему 'git rev-list --left-right', сравнивающий A..B, не согласуется с B..A? - PullRequest
0 голосов
/ 09 мая 2019

Я пытаюсь сравнить два коммита, чтобы получить их различия впереди / сзади, используя ответ https://stackoverflow.com/a/27940027/1949430

"git rev-list --left-right --count A..B", где Aи B - ссылки SHA1.

В одном случае сравнение A..B дает 0 Ahead и 17 Behind.Если я повторно выполню ту же команду для B..A, то получу 0 Ahead и 0 Behind, тогда как я ожидаю, что это будет простая обратная последовательность 17 Ahead и 0 Behind.В другом случае я получаю 0/6 в одном направлении и 0/2 в другом.Это противоречит моей цели - попытаться лучше визуализировать различия, в этом случае ссылка на субмодуль и проверенный коммит.

Почему я получаю совершенно другие результаты для A..B, чем я для B..A?Мне нужно / ожидается, что я получу непротиворечивое значение независимо от порядка, просто меняя местами счетчики впереди и сзади ...

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

1 Ответ

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

TL; DR: вы хотите git rev-list --left-right --count A...B. Примечание три точки, а не два .

Двухточечная запись означает 1 коммитов, достижимых с B, минус любые коммиты, достижимые с A. Предположим, что существует 17 таких коммитов, потому что история изменений выглядит так:

...--o--o--o   <-- A
            \
             o--o--o--...--o   <-- B (17 commits in total, 13 not shown here)

Все коммиты в верхнем ряду достижимы с A, поэтому они вычитаются из набора коммитов, достижимых с B (обе строки). Это оставляет 17, которые вы подсчитываете.

Замена ордера означает, что коммиты достижимы с A минус любые коммиты, достижимые с B. Поскольку все коммиты достижимы с B, мы вычитаем их из набора коммитов, достижимых с A, не оставляя коммитов вообще. Поэтому счет равен нулю.

три -точечная нотация A...B означает 2 коммитов, достижимых с либо A или B минус все коммиты, доступные с оба A и B. На приведенной выше диаграмме 17 коммитов, доступных с B, но не A и нулевые коммиты достижимы от A, а не B. Использование --left-right разбивает их на подгруппы; использование --count считает их; сложив оба, вы получите два числа, и два числа займут левую или правую позицию в зависимости от того, используете ли вы A...B или B...A.

Трехточечная запись более полезна на графике, который выглядит следующим образом:

       o--o   <-- A
      /
...--*
      \
       o--o--o   <-- B

Здесь есть два коммита, доступных с A, но не B, и три коммита, доступных с B, но не A. Все коммиты в среднем ряду * и более ранние доступны из обеих подсказок и, следовательно, исключены трехточечной нотацией.


1 Для git diff обозначения с двумя и тремя точками означают нечто совершенно иное. Команды diff в большинстве случаев требуют только двух коммитов, а A..B или A...B довольно часто означают много коммитов - больше, чем те, которые git diff нравится - поэтому git diff A..B просто означает: используйте A в качестве левой стороны и B в качестве правой , что в точности соответствует git diff A B. На самом деле это не так уж и полезно, поскольку вы могли бы самостоятельно заменить две точки пробелом, но это означает .

2 В git diff трехточечный синтаксис приобретает новое и совершенно другое (и полезное!) Значение. Вместо сравнения коммитов A и B запись A...B означает: Найдите исключенный коммит в середине - это, более или менее, базу слияния - и используйте это как левая сторона. Используйте B в качестве правой стороны. Для последнего случая, показанного выше, исключенный коммит в середине - это коммит *, который действительно является базой слияния. Таким образом, git diff A...B означает diff commit * vs commit B, тогда как git diff B...A означает diff commit * vs commit A.


Боковая панель: простой способ думать об этом

Для тех, кто ориентирован на визуальное представление, представьте, что у вас есть печатная версия графика и два разноцветных маркера выделения, красный и зеленый. Вы берете график, например:

       o--o   <-- A
      /
...--*
      \
       o--o--o   <-- B

Вы берете маркер выделения красный и отмечаете коммит, на который указывает A. Затем следуйте за обратными соединителями от этого коммита до его родителя (ей). Отметьте эти красные тоже. Продолжайте двигаться назад до тех пор, пока все, что вы можете сделать таким образом - двигаясь назад, через все родительские коммиты при любых слияниях, - не будет отмечено красным.

Затем возьмите зеленый маркер выделения и отметьте коммит, на который B указывает. Следуйте за этим назад к его родителю (родителям), и отметьте те зеленые. Делайте пометки зелеными, пока все, что вы можете сделать таким образом, не будет помечено зелеными.

Любое сотрудничествоmmits с только зеленым выделением включены.Любые коммиты с красным или обоим выделением исключаются.То, что вы действительно сделали, это вычитание набора из двух наборов достижимых коммитов, но об этом легко думать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...