создание различий между двумя ветвями после частичного просмотра

Допустим, у меня есть такая ситуация в git:

  B---D---F---H---J---K--->topic
 /       /       /
A---C---E---G---I--->master

Дойдя до коммита F, я отправляю ветку темы на проверку. Рецензент вносит некоторые предложения, и мир движется дальше, поэтому выполняется еще одно слияние. Как ответил здесь Git diff on тематическая ветка, исключая коммиты слияния, которые произошли за это время? способ сгенерировать diff от A до F просто git diff master..topic. Однако теперь ревизии B и D уже проверены, и я хотел бы исключить их из нового diff для проверки. Однако git diff E..topic включает G и I.

Как мне получить разницу H, J и K, исключая вещи, втянутые через G и I?


person Rich L    schedule 28.10.2013    source источник


Ответы (2)


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

(Здесь стоит отметить, что ответ на связанный вопрос замалчивает тот факт, что x..y в git diff интерпретируется иначе, чем в других командах git.)

Когда вы запрашиваете E..topic, git преобразует topic в конкретную фиксацию — в данном случае K — и затем сравнивает дерево в E с деревом в K. Вот почему вы видите изменения из G и I, потому что эти изменения были внесены в J посредством слияния.

Вы можете сравнить F и K, но это все равно покажет изменения в G и I, потому что опять же, эти изменения на самом деле в J.

На самом деле есть только один способ игнорировать то, что произошло в J, сохраняя при этом F и H нетронутыми, и это построить дерево, которое либо пропускает это, либо возвращает его. Например, начиная с H, вы можете добавить патч, основанный на разнице между J и K:

                K'        <-- HEAD[detached]
               /
  B---D---F---H---J---K   <-- topic
 /       /       /
A---C---E---G---I         <-- master

(для этого git checkout topic~2 отсоединиться при фиксации H, затем git cherry-pick topic добавить к уже отсоединенному HEAD сделанные изменения для перехода от J к K).

Теперь вы можете сравнить дерево в коммите E с деревом в HEAD (в коммите K'):

git diff E HEAD   # or   git diff E..HEAD   or   git diff E..

Но в целом это не то, что люди хотят пересматривать. На самом деле, поскольку вы почти наверняка впоследствии полностью откажетесь от версии K' (создав ее только для проверки), они будут проверять версию кода, которая никогда не используется!

Вот почему принятым ответом на связанный вопрос является просто git diff master..topic, что означает то же самое, что и git diff master topic, и в данном случае сравнивает дерево для I с деревом для K. Вы предлагаете разместить на ветке topic дерево, похожее на K. Это код, который будет в topic. Он имеет некоторое отличие от кода, который находится в версии I в версии master. Разница, которую он имеет по сравнению с I, представляет собой сумму изменений в F, H, K и любой работы с прокладками, которая была проделана, чтобы J соответствовала. Он действительно имеет изменения, сделанные в G (и, конечно, в самом I), но это не изменения в I, это просто изменения, включенные в I.

Более тщательный способ просмотреть код — представить на проверку четыре отличия:

  1. E vs F
  2. F vs H
  3. H против J (возможно, комбинированный дифференциал, H и I против J)
  4. J vs K

Первая разница сообщает вашим рецензентам, что, если они ее примут, можно будет проверить дерево, похожее на F (что, безусловно, верно, просто git checkout F). Вторая разница говорит вашим рецензентам, что, имея F в своих репозиториях, можно будет проверить H (если они примут это) и т. д. Очевидно, что четыре обзора сложнее, чем один, поэтому люди принимают такие сокращения, как сравнение I против K.

person torek    schedule 28.10.2013

Предложение Торека (выполнить несколько обзоров) возможно, но имеет неприятный побочный эффект, означающий, что код, который, как было сказано, нуждается в улучшении после F и исправлен в H, должен быть проверен дважды: один раз в его неудовлетворительном состоянии и один раз когда это было закончено. Хорошая вещь в git diff master..topic заключалась в том, что он раздавил их и просто дал окончательную разницу между ветвями.

Чтобы решить эту проблему, я создал ветку из F, объединил с ней master, а затем выполнил различие между моей новой временной веткой и веткой topic. Таким образом, все изменения в master были скрыты, и использовались только изменения в ветке topic с момента предыдущей точки обзора.

person Rich L    schedule 29.10.2013