Подтвердить что ты не робот

Как вы получаете 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

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

4b9b3361

Ответ 1

Я тоже искал что-то подобное. Насколько мне известно, 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 и продолжите оттуда.

Ответ 2

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

Отметьте всех второстепенных родителей всех слияний в основной ветке как хорошие

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

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

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

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

Учитывая историю, изложенную в этом вопросе, использование однострочной строки даст вам:

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

Это приведет к тому, что пополам будет проходить только коммиты на главной ветки:

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

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

Ответ 3

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

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 - соответствующие шары, похоже, делают то, что вы хотите.

Ответ 4

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

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

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

Ответ 5

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

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

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

Ответ 6

Ответ бьорна Штайнбринка прекрасно работает, но недавно начал печатать так:

hint: Support for /info/grafts is deprecated
hint: and will be removed in a future Git version.
hint: 
hint: Please use "git replace --convert-graft-file"
hint: to convert the grafts into replace refs.
hint: 
hint: Turn this message off by running
hint: "git config advice.graftFileDeprecated false"

Вот более современная версия его решения с использованием "git replace" вместо трансплантатов:

git rev-list --first-parent --merges --parents HEAD | \
  while read COMMIT PARENT1 PARENT2; do 
    git replace --graft $COMMIT $PARENT1; 
  done

К сожалению, это намного медленнее для больших репозиториев (около 3 минут для 150k коммитов); git replace, похоже, еще не имеет режима объемного воспроизведения. Возможно, вы захотите ограничить список ревью только коммитами в рамках вашего раздела.

Чтобы удалить замены, когда вы закончите, вы можете rm .git/refs/replace/*.

Ответ 7

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

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

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

Ответ 8

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

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

Ответ 9

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