Как вы получаете git bisect, чтобы игнорировать объединенные ветки?

Я знаю, что git bisect поддерживает ветвь по дизайну, так что если между хорошим коммитом, G и плохой фиксацией B вы слились в ветку, необходимо также учитывать эти изменения, так как ошибка может содержаться в ветке.

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

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

Я бы просто хотел бы рассмотреть каждое объединение ветвей как единое целое при выполнении деления пополам.

Обходной путь, который я нашел до сих пор, составляет список допустимых коммитов G..B с git log --first-parent, а затем, в то время как bisecting, do git bisect skip, если текущая фиксация isn ' т в этом списке. Это занимает много времени (много файлов для проверки/изменения для каждого пропуска).

Итак, вопрос: есть ли способ сделать - первый родитель с git bisect или предоставление списка коммитов, которые я чувствую, действительны, чтобы быть в состоянии избежать проверки ветвей, которые, как я знаю, уже не компилируются? Как мы можем проверить только фиксации, отмеченные o на диаграмме?

G---o---o---o---o---o---o---B main project branch
 / / / 
 x---x---x---x---x dependency
 \ /
 x' dependency project taskbranch

Изменить: добавлена ​​диаграмма для ясности

8 ответов

Я тоже искал что-то подобное. Насколько мне известно, git rev-list --bisect --first-parent делает то, что вы хотите, а документы для rev-list подразумевают, что параметр --bisect - это то, что bisect использует внутренне, но получая git bisect, чтобы добавить этот флаг в его вызов в rev-list кажется менее тривиальным:

Команда bisect реализуется оболочкой script git -bisect, которая, в свою очередь, использует встроенную команду bisect--helper, чтобы на самом деле сделать интересную часть ( "вычисление, отображение и проверка" говорит комментарий...), по-видимому, основанный на связке файлов состояния магии в .git/. И, похоже, это команда rev-list, которая повторно использует код из bisect-helper, а не наоборот, как вы могли бы ожидать.

Итак, вам нужно будет расширить фильтрацию фиксации bisect-helper-кода, чтобы сделать это, я думаю.

В качестве обходного пути может возникнуть что-то вроде этого: после того, как bisect проверит что-то для вас, reset другому, используя git rev-list --bisect --first-parent, проверьте это и пометьте его good/bad/skip и продолжите оттуда.


Я подумал о одном возможном решении, но я все еще надеюсь найти что-то более элегантное:

Отметьте всех второстепенных всех сливов в основную ветку как хорошие

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

git rev-list --first-parent --merges --parents GOOD..BAD \
| sed 's/^[^ ]\+ [^ ]\+ //' \
| xargs git bisect good

(замените GOOD и BAD соответствующими коммитами)

Регулярное выражение в sed удаляет первые две записи каждой строки; слияние происходит и первый родитель, оставляя остальных родителей (обычно только второй).

Учитывая историю, указанную в вопросе, запуск oneliner даст вам:

G---o---o---o---o---o---o---B main project branch
 / / / 
 G---x---G---x---G dependency
 \ /
 x' dependency project taskbranch

Это сделало бы bisect пройденным только фиксации в основной ветке:

o---o---o---o---o---o

Если какая-либо из объединенных ветвей косвенно является причиной проблемы, она будет обнаружена, когда вы проверите фиксацию слияния через bisect, что может быть основанием для дальнейшего изучения этой ветки.


Если история выглядит так:

A - B - C - H - I - J - K - L
 \ /
 D - E - F - G

где L плохо, B хорош, и вы хотите игнорировать ветвь DEFG, а затем запустить

$ git bisect start
$ git bisect skip $( git rev-list G ^C )
$ git bisect bad L
$ git bisect good B

где B, C, G и L - соответствующие шары, похоже, делают то, что вы хотите.


Вы можете сделать git обрабатывать историю как линейную, используя графты. Чтобы линеаризовать всю первую родительскую историю, вы можете использовать:

git rev-list --first-parent --merges --parents HEAD | cut -d' ' -f1,2 > .git/info/grafts

Просто отпустите файл графтов, когда закончите с делением пополам.


Вы можете проинструктировать git -bisect, чтобы пройти только первые родители слияния, выполнив следующую команду:

git bisect skip $(comm -23 <(git rev-list G | sort) <(git rev-list --first-parent G | sort))


Я не вижу одношагового метода, однако, исходя из вашего текущего решения: git bisect skip может взять список коммитов для пропуска. git log branchname перечислит коммиты в ветке branchname. Таким образом, это должно позволить вам указать список коммитов.

Если ваша зависимость и ваш основной код находятся в разных пространствах файловой системы, вы можете указать пути, которые нужно включить в начало git bisect start. В зависимости от вашего макета кода это может быть лучшим вариантом. (Почти наверняка, если у вас есть список файлов, которые могут содержать ошибку!)

В справочной странице есть детали; также есть интересное чтение.


Итак, предположение о том, что первый родитель слияния является всегда одной ветвью, не всегда корректен. Например, если вы отключены от ветки темы и сгенерируете ее, чтобы обновиться (так что для этого слияния, первым родителем является ветвь темы), а затем верните мастер и смените тему, вы получите ускоренное слияние вперед, которое просто перемещает главный объект в транзакцию слияния, у которой был первый родитель, как ваша ветка темы. Это может показаться надуманным, но на самом деле это довольно нормальный рабочий процесс. Я всегда объединяю мастер в свою ветку, чтобы слияние с мастером было тривиальным слиянием (т.е. Ускоренным переходом вперед) (Извините, Джеймс, всегда забывайте его переустанавливать).

Есть один способ, который я нашел, чтобы помочь выяснить, какой из родителей является вашей веткой - сам комментарий коммита. По умолчанию git содержит комментарий компиляции слияния, в котором говорится, какая ветка была объединена, и вы можете использовать это, чтобы вывести, какой из родительских элементов является интересующей вас ветвью, если человек, выполняющий коммит слияния, не перезаписал это объединение комментарий.

Итак, я попробовал это и, похоже, работает для меня. Я написал Python script, чтобы помочь сделать это в github. Если вы запустите этот script, он попытается проследить назад и следовать за вашей веткой и испустить список идентификаторов фиксации, которые являются советами ветвей, которые объединены в вашу ветку. С помощью этого списка вы можете дать им "git bisect good", и bisect затем опустит все коммиты на объединенных ветвях из вашего деления пополам, достигнув желаемого результата.


Возможно, вы сможете использовать git bisect start --no-checkout, чтобы избежать фактической проверки фиксации в рабочем дереве. Тогда я подозреваю, что вы можете сделать git checkout BISECT_HEAD для коммитов, которые вы действительно хотите протестировать (т.е. Только первый родитель совершает на главной ветке). Я не пробовал это, но надеюсь, что это сработает.

licensed under cc by-sa 3.0 with attribution.