Как git bisect skip выбрать следующую фиксацию, чтобы попробовать?

При использовании git bisect можно запустить git bisect skip, чтобы пометить текущую фиксацию как незастроенную/непроверенную, чтобы попытаться получить Git, чтобы выбрать другую фиксацию для проверки.

Как Git решить, какой фиксатор попробовать после git bisect skip? Эксперимент показывает, что это не только смежная фиксация, но я не могу выработать шаблон.

Изменить. Я знаю, что базовый git bisect - это двоичный поиск, но мне любопытно git bisect skip, что явно делает что-то более сложное.

Эксперимент показывает, что он не просто выбирает смежную фиксацию; ниже создается 100 коммитов с номером 0 – 99 затем начинается их деление пополам. Первый фиксатор git bisect выбирается посередине, но каждый git bisect skip после этого кажется более или менее случайным.

$ git init
Initialized empty Git repository in .git/

$ for (( i=0; i<100; i++ )); do echo $i > file; git add file; git commit -m $i >/dev/null; done  # Create some dummy commits

$ git bisect start HEAD $(git rev-list --max-parents=0 HEAD)  # HEAD is bad, root commit is good.
Bisecting: 49 revisions left to test after this (roughly 6 steps)
[099e5cf2ccde625f92dc369da6cad0bdf2852ce4] 49

$ git bisect skip
Bisecting: 49 revisions left to test after this (roughly 6 steps)
[88c8208a7c4322222124167e49f07c741af7d3d8] 60

$ git bisect skip
Bisecting: 49 revisions left to test after this (roughly 6 steps)
[04695f2e5b2473c3ac72435c0dbfc3ba1375abda] 88

$ git bisect skip
Bisecting: 49 revisions left to test after this (roughly 6 steps)
[1e9bf3d29589bcac2d8c467245ae8d446c195252] 40

$ git bisect skip
Bisecting: 49 revisions left to test after this (roughly 6 steps)
[9459ed79e4112d674681c8f0f921127217c7ebc6] 13

Ответ 1

Я немного покопался в исходном коде Git и сам нашел большую часть ответа...

Начиная с Git v1.6.4 (в частности, с коммитом ebc9529f), Git использует "PRNG (генератор псевдослучайных чисел) со смещением", чтобы определить, какой коммит следует предпринять следующим после пропуска.

Я не могу сказать, что следую самому алгоритму (который, начиная с v2.8.1, кажется, что он принципиально не затронут с тех пор, как он был впервые добавлен), но сообщение commit делает разумную работу, объясняя, что происходит:

bisect: используйте PRNG с уклоном, когда пропускаете непроверяемые коммиты

Использование PRNG (генератора псевдослучайных чисел) со смещением должно быть лучше, чем чередование трех фиксированных соотношений.

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

HPA предложила использовать PRNG и обнаружила, что наилучшим смещением является повышение отношения между 0 и 1, заданным PRNG, к мощности 1,5.

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

Ответ 2

Как следует из названия Git, короткий ответ: Это не ваш бизнес.

Идея git bisect заключается в том, что вы указываете две конечные точки и Git фигурируете в ней, например, фиксацию, которая, по ее мнению, является полезной для снижения количества тестов.

Как говорится в документации, это всего лишь двоичный поиск, но не указывает, какой алгоритм используется

Затем Git bisect выбирает фиксацию между этими двумя конечными точками

Это может быть не простой бинарный поиск pick-the-middle-commit, Git может использовать любой алгоритм решения, который он хочет, и он явно не хочет, чтобы вы знали его, чтобы вы не делали предположений на commit, который будет поднят.

Когда дело доходит до изменения собранного фиксации, он дает вам две возможности:

  • Вы вручную выбираете новый коммит. Например, с помощью git reset --hard.
  • Вы скажете Git сделать новый выбор, git bisect skip.

В последнем случае, когда вы обновляете конечные точки с помощью good и bad, решение принимается Git, как он хочет.


Из любопытства я сделал простой одноинтерфейсный репозиторий и попробовал команду git bisect skip.
Моя версия Git взяла предыдущую фиксацию.