Вопрос
У меня есть репозиторий 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
Соответствующая проблема обсуждалась в сообществе GitHub: github.com/orgs/community/discussions/39031
Проблема в том, что вы создали два одновременных запроса на включение, один из которых зависит от другого, и то, как вы это сделали, привело к такому поведению 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.
Спасибо за ответ, но не является ли это ошибкой (пользователям Git этого делать не следует)? В данном случае мы можем этого избежать. Но учтите, что когда мы сначала вводим исправление, изменяющее строку, то надежное исправление позже отменяет это изменение. Это звучит как вполне обоснованный сценарий.
@nekomachi-touge Это совершенно верно. Вы не сделали ничего плохого. Вы были только удивлены тем, как Github справляется с ситуацией.
Согласен, доработаю, чтобы убрать "неправильно".
@nekomachi-touge Посмотрим, покажется ли вам это изменение немного более обнадеживающим.
@j6t @matt Спасибо за разъяснения, но я все еще в замешательстве. Поскольку main
изменяется при слиянии branch-modify
, PR №2 «состоит» из возврата, следовательно, разница должна что-то содержать? Кроме того, базой слияния между main
и branch-revert
является eaec7f6
, а не c1f094b
, поэтому трехточечная разница содержит возврат, как показывает исходный вопрос. Почему GitHub не показывает разницу (дизайнерское решение GitHub или что-то еще)?
Я добавил вывод git merge-base main branch-revert
в раздел «Обновление» моего вопроса, чтобы прояснить мою точку зрения выше.
Не имеет значения, какая сейчас база слияния. На момент создания второго PR, поскольку вы попросили объединить branch-revert
в main
, базой слияния была c1f094b
. В любом случае, копание в местном репо здесь не поможет. Как я объяснил в своем последнем абзаце (мелким шрифтом), то, что делает GitHub, полностью зависит от GitHub; запросы на включение не являются функцией Git. И я здесь не для того, чтобы оправдывать действия GitHub; Я просто объясняю это. Я рассказал вам, как получить «правильный» ответ в следующий раз, когда одна отрасль PR будет зависеть от другой. Это лучшее, что можно сделать в данной ситуации.
@matt Плохо, ты щелкнул мной после того, как я понял, что база слияния до слияния PR № 1 была c1f094b
. Теперь я вижу, что здесь происходит!
Я предполагаю, что Github показывает вам разницу с c1f094b, а не разницу с 97d2b9b.