Несоответствия различий GitHub при сравнении ветки с фиксацией слияния и другой, отменяющей слияние

Вопрос

У меня есть репозиторий git на GitHub (демо), который имеет 3 ветки:

  • main: ветка по умолчанию
  • branch-modify : разветвлен на main, содержит модифицирующий коммит на main
  • branch-revert : разветвлен на branch-modify, содержит еще один коммит, возвращающий модифицирующий коммит.

В этом репозитории я сделал PR с branch-modify против main и объединил его с объединенным коммитом (#1).
А еще я сделал еще один пиар с branch-revert против main (#2).

Я ожидал, что второй PR покажет, что разница возвращает изменения, внесенные модифицирующим коммитом.
Однако GitHub показывает пустой diff.

Почему дифф оказался пустым? Если это намеренное поведение, какова его причина?

Git-график репо после операций:

% git log --all --oneline --graph
*   97d2b9b (HEAD -> main, origin/main) Merge pull request #1 from nekomachi-touge/branch-modify
|\
| | * 6d23f11 (origin/branch-revert, branch-revert) Revert "modify test.txt"
| |/
| * eaec7f6 (origin/branch-modify, branch-modify) modify test.txt
|/
* c1f094b add test.txt

Предыдущие исследования

Я нашел похожие вопросы:

Оба предполагают разницу между двухточечными и трехточечными различиями, но в моем случае я не вижу никакой разницы.

% git diff main..branch-revert
diff --git a/test.txt b/test.txt
index 55b5f1f..323fae0 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-foofoo
+foobar
% git diff main...branch-revert
diff --git a/test.txt b/test.txt
index 55b5f1f..323fae0 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-foofoo
+foobar

Кроме того, я обнаружил, что функция «Сравнение изменений» создает различия, которые не обратятся, если я сравниваю main с branch-revert, а затем меняю местами ветки:
https://github.com/nekomachi-touge/github-revert-test-20240814/compare/main...branch-revert
https://github.com/nekomachi-touge/github-revert-test-20240814/compare/branch-revert...main


Фон

В моей работе у меня есть репозиторий IaC, управляющий двумя кластерами с избыточностью в активном/резервном стиле.
Чтобы переключить активный кластер, мне нужно внести изменения в репо.

Я хотел проверить избыточность, сделав PR, а затем отменив его другим PR.
Однако после слияния первого PR дифф второго PR стал пустым, что было совершенно неожиданно.
Попытка воспроизвести и понять проблему привела меня к публикации этого вопроса.


Обновлять

(24.08.2024) Базой слияния между main и branch-revert является коммит «modify test.txt»:

% git merge-base main branch-revert
eaec7f69baf9c990021537ad269cb4e6527a7b37

68
1

Ответ:

Решено

Проблема в том, что вы создали два одновременных запроса на включение, один из которых зависит от другого, и то, как вы это сделали, привело к такому поведению GitHub.

  • Вы ответвились branch-revert от branch-modify.
  • Затем вы создали два запроса на включение: один для branch-modify и один для branch-revert.
  • И (это ключевой момент) вы настроили свой второй запрос на включение, тот, что для branch-revert, попросив объединить его с main. (Это простую конфигурацию, поскольку она используется по умолчанию.)

Таким образом, даже после того, как вы объединили первый запрос на включение, второй (branch-revert) запрос на включение включает в себя как фиксацию branch-modify, так и фиксацию branch-revert (поскольку база слияния между branch-revert и main является корневой фиксацией):

Вот как можно посмотреть, из чего «состоит» запрос на включение. Ну и конечно же, общая сумма изменений файлов за все время этих двух коммитов равна нулю; test.txt переходит от «foobar» к «foofoo» и обратно к «foobar».

Как еще вы могли бы поступить и каков был бы результат?

  • Поскольку branch-revert был ответвлением от branch-modify, вы могли бы создать второй запрос на включение, попросив объединиться с branch-modify. Если бы вы это сделали, то, когда первый (branch-modify) запрос на включение был бы объединен, GitHub переназначил бы цель слияния для второго запроса на включение как main, и запрос на включение состоял бы только из одного коммита, коммита возврата и «файлы изменены» включали бы test.txt — «правильный» результат.

  • Альтернативно, вы могли бы подождать, пока первый запрос на включение не будет объединен, прежде чем создавать второй запрос на включение. Это также дало бы тот же «правильный» результат.

Если вы будете делать все так, как вы это сделали, в долгосрочной перспективе никакого серьезного вреда не будет, потому что объединение второго запроса на извлечение приведет к ожидаемому результату. Просто отображение GitHub того, из чего «состоит» второй запрос на включение, вышло таким образом, что вас удивило (отсюда и ваш вопрос).


Keep in mind, too, that this is entirely a matter of how GitHub displays things at its site. It has almost nothing to do with Git! Pull requests are not a Git feature. A pull request is effectively a trick performed by the hosting site, as a convenience for people doing collaborative development. (That is why looking at the Git log locally didn't help you very much. Git knows nothing of what's going on here.) Every hosting site that adds this sort of feature can do it in its own way and can display the info in its own way. In this case, you simply stumbled across a quirk of the way GitHub does things.