Я прочитав деякі статті, які говорять, що git bisect
це приголомшливо. Однак я не є носієм мови і не можу зрозуміти, чому це приголомшливо.
Може хтось, будь ласка, продемонструє якийсь зразок коду:
- Як ним користуватися?
- Це просто так
svn blame
?
Я прочитав деякі статті, які говорять, що git bisect
це приголомшливо. Однак я не є носієм мови і не можу зрозуміти, чому це приголомшливо.
Може хтось, будь ласка, продемонструє якийсь зразок коду:
svn blame
?Відповіді:
Ідея git bisect
полягає в тому, щоб здійснити двійковий пошук в історії, щоб знайти певний регрес. Уявіть, що у вас є така історія розвитку:
... --- 0 --- 1 --- 2 --- 3 --- 4* --- 5 --- current
Ви знаєте, що ваша програма не працює належним чином при current
перегляді, і що вона працювала в редакції 0
. Таким чином, регресія , ймовірно , введений в одному з фіксацій 1
, 2
, 3
, 4
, 5
, current
.
Ви можете спробувати перевірити кожну комісію, побудувати її, перевірити, чи є регресія чи ні. Якщо існує велика кількість комітетів, це може зайняти тривалий час. Це лінійний пошук. Ми можемо зробити краще, зробивши двійковий пошук. Це те, що git bisect
робить команда. На кожному кроці вона намагається зменшити кількість ревізій, які потенційно погані вдвічі.
Ви скористаєтесь такою командою:
$ git stash save
$ git bisect start
$ git bisect bad
$ git bisect good 0
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[< ... sha ... >] 3
Після цієї команди git
перевірятиме фіксацію. У нашому випадку це буде фіксація 3
. Потрібно скласти свою програму та перевірити, чи є регресія чи ні. Вам також потрібно буде повідомити git
про стан цієї версії або за git bisect bad
наявності регресії, або git bisect good
якщо її немає.
Припустимо, що регресія була введена в комі 4
. Тоді в цій редакції регресії немає, і ми це повідомляємо git
.
$ make
$ make test
... ... ...
$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[< ... sha ... >] 5
Потім він перевірить інший комітет. Або 4
або 5
(оскільки існує лише два коміти). Припустимо, він вибрав 5
. Після складання ми тестуємо програму і бачимо, що регресія присутня. Потім ми повідомляємо це git
:
$ make
$ make test
... ... ...
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[< ... sha ... >] 4
Ми тестуємо останню версію, 4
. А оскільки саме той ввів регресію, ми говоримо про це git
:
$ make
$ make test
... ... ...
$ git bisect bad
< ... sha ... > is the first bad commit
< ... commit message ... >
У цій простій ситуації, ми повинні були тільки тест 3 версії ( 3
, 4
, 5
) замість 4 ( 1
, 2
, 3
, 4
). Це невеликий виграш, але це тому, що наша історія така маленька. Якщо діапазон пошуку становить N комітів, слід очікувати тестування 1 + log2 N комірокgit bisect
замість приблизно N / 2 здійснює при лінійному пошуку.
Після того як ви знайшли комісію, яка запровадила регресію, ви можете вивчити її, щоб знайти проблему. Як тільки це буде зроблено, ви використовуєте, git bisect reset
щоб повернути все до початкового стану, перш ніж використовувати git bisect
команду.
git bisect bad <rev> [<rev>...]
для позначення конкретних змін як поганих (або хороших з git bisect good <rev> [<rev>...]
). rev
може бути будь-який ідентифікатор редакції, наприклад, ім'я гілки, тег, хеш-
git bisect reset
все, щоб повернути все на нещодавнє зобов’язання
git bisect run
автоматичний бісектЯкщо у вас є автоматизований ./test
скрипт, який має статус виходу 0, якщо тест у порядку, ви можете автоматично знайти помилку за допомогою bisect run
:
git checkout KNOWN_BAD_COMMIT
git bisect start
# Confirm that our test script is correct, and fails on the bad commit.
./test
# Should output != 0.
echo $?
# Tell Git that the current commit is bad.
git bisect bad
# Same for a known good commit in the past.
git checkout KNOWN_GOOD_COMMIT
./test
# Should output 0.
echo $?
# After this, git automatically checks out to the commit
# in the middle of KNOWN_BAD_COMMIT and KNOWN_GOOD_COMMIT.
git bisect good
# Bisect automatically all the way to the first bad or last good rev.
git bisect run ./test
# End the bisect operation and checkout to master again.
git bisect reset
Це, звичайно, передбачає, що якщо тестовий скрипт ./test
відслідковується, він не зникає на деяких попередніх фіксаціях під час поділу.
Я виявив, що дуже часто ви можете піти, просто скопіювавши сценарій дерева з дерева та, можливо, погравши зі PATH
змінними -подобними, і замість цього запустивши його.
Звичайно, якщо тестова інфраструктура, від якої test
залежать перерви на більш старі домовленості, то рішення не знайдеться, і вам доведеться робити вручну, вирішуючи, як тестувати фіксацію по черзі.
Однак я виявив, що використання цієї автоматики часто спрацьовує, і це може бути величезною економією часу для повільніших тестів, що лежать у вашому відставанні завдань, де ви можете просто дозволити їй працювати протягом ночі, і, можливо, визначити свою помилку до наступного ранку, варто спробу.
Залишайтеся на першому невдалому комітеті після бісектриси, а не повертайтеся до master
:
git bisect reset HEAD
start
+ початковий bad
та good
за один раз:
git bisect start KNOWN_BAD_COMMIT KNOWN_GOOD_COMMIT~
те саме, що:
git checkout KNOWN_BAD_COMMIT
git bisect start
git bisect bad
git bisect good KNOWN_GOOD_COMMIT
Подивіться, що було протестовано до цього часу (вручну good
та bad
або run
):
git bisect log
Вибірка зразка:
git bisect log
git bisect start
# bad: [00b9fcdbe7e7d2579f212b51342f4d605e53253d] 9
git bisect bad 00b9fcdbe7e7d2579f212b51342f4d605e53253d
# good: [db7ec3d602db2d994fe981c0da55b7b85ca62566] 0
git bisect good db7ec3d602db2d994fe981c0da55b7b85ca62566
# good: [2461cd8ce8d3d1367ddb036c8f715c7b896397a5] 4
git bisect good 2461cd8ce8d3d1367ddb036c8f715c7b896397a5
# good: [8fbab5a3b44fd469a2da3830dac5c4c1358a87a0] 6
git bisect good 8fbab5a3b44fd469a2da3830dac5c4c1358a87a0
# bad: [dd2c05e71c246f9bcbd2fbe81deabf826c54be23] 8
git bisect bad dd2c05e71c246f9bcbd2fbe81deabf826c54be23
# bad: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05] 7
git bisect bad c536b1b7242d5fcf92cd87e9a534bedb1c0c9c05
# first bad commit: [c536b1b7242d5fcf92cd87e9a534bedb1c0c9c0
Показуйте хороші та погані рефлекси в журналі git, щоб краще зрозуміти час:
git log --decorate --pretty=fuller --simplify-by-decoration master
Це показує лише коміти з відповідним посиланням, що зменшує жирність, але не включає автогенеровані посилання типу:
refs/bisect/good*
refs/bisect/bad*
які говорять нам, які вчинки ми позначили як добрі чи погані.
Розгляньте це тестове репо, якщо ви хочете пограти з командою.
Іноді:
У таких випадках, наприклад, якщо припустимо, що зрив завжди трапляється за 5 секунд, і якщо ми лінуємося зробити тест більш конкретним, як насправді, ми можемо використовувати timeout
як:
#!/usr/bin/env bash
timeout 5 test-command
if [ $? -eq 1 ]; then
exit 1
fi
Це працює з timeout
виходами в 124
той час як відмова test-command
виходів 1
.
git bisect run
трохи вибагливий щодо статусів виходу:
все, що перевищує 127, змушує ділити провал з чимось на кшталт:
git bisect run failed:
exit code 134 from '../test -aa' is < 0 or >= 128
Зокрема, C assert(0)
призводить до SIGABRT
виходу зі статусом 134, що дуже дратує.
125 - це магія і змушує пропустити пробіг git bisect skip
.
Наміром цього є допомогти пропустити розбиті конструкції через незв’язані причини.
Дивіться man git-bisect
деталі.
Тому ви можете використовувати щось на кшталт:
#!/usr/bin/env bash
set -eu
./build
status=0
./actual-test-command || status=$?
if [ "$status" -eq 125 ] || [ "$status" -gt 127 ]; then
status=1
fi
exit "$status"
Перевірено на git 2.16.1.
test_script
+ модульним набором тесту та запустіть її з окремого файлу під час розбиття на бік. Коли ви виправите, об'єднайте тест у основний тестовий набір.
bisect run
особливо корисним, коли тест потребує тривалого часу, і я майже впевнений, що тестова система не зламається. Таким чином, я можу просто залишити його працювати на задньому плані або на ніч, якщо це забирає занадто багато ресурсів, не втрачаючи часу на перемикання контексту мозку.
$ git bisect start
$ git bisect bad
$ git bisect good <goodcommit>
Bisecting: X revisions left to test after this (roughly Y steps)
Проблема все ще існує?
$ git bisect bad
$ git bisect good
<abcdef> is the first bad commit
git bisect reset
git bisect good
щоб перейти до наступної фіксації.
Просто, щоб додати ще один момент:
Ми можемо вказати ім’я або шлях до файлу, git bisect start
якщо ми знаємо, що помилка походить з певних файлів. Наприклад, припустимо, що ми знали, що зміни, які спричинили регресію, були в каталозі com / workingDir, тоді ми можемо запустити. git bisect start com/workingDir
Це означає, що перевірятимуться лише ті записи, які змінили вміст цього каталогу, і це робить все ще швидшим.
Крім того, якщо важко сказати, чи є певна фіксація доброю чи поганою, ви можете запустити git bisect skip
, що ігнорує це. Зважаючи на те, що є достатньо інших комітетів, git bisect використовуватиме інший, щоб звузити пошук.
$ git bisect ..
в основному інструмент Git для налагодження . Налагодження "Git Bisect", пройшовши попередні коміти з часу останнього (відомого) робочого комітету. Він використовує двійковий пошук, щоб пройти всі ці коміти, щоб дістатися до того, який ввів регресію / помилку.
$ git bisect start
# Починаючи бісект
$ git bisect bad
# заявляючи, що поточна фіксація (v1.5) має регресію / встановлення 'поганої' точки
$ git bisect good v1.0
# згадування про це останньому доброму робочому зобов'язанні (без регресу)
Ця згадка про «погані» та «хороші» точки допоможе git bisect (бінарний пошук) вибрати середній елемент (commit v1.3). Якщо регресія є в команді v1.3, ви встановите її як нову "погану" точку, тобто ( Добре -> v1.0 і погано -> v1.3 )
$ git bisect bad
або аналогічно, якщо команда v1.3 відсутня помилок, ви встановите її як нову "Добру точку", тобто (* Добре -> v1.3 і Погано -> v1.6).
$ git bisect good
Примітка. Умови good
та терміни bad
не є єдиними, які ви можете використовувати для позначення комісії з певним властивістю або без неї.
Git 2.7 (Q4 2015) представив нові git bisect
варіанти.
git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
З додаванням документації:
Іноді ви не шукаєте зобов’язання, яке ввело розрив, а скоріше зобов'язання, що спричинило зміну між якоюсь іншою "старою" державою та "новою" державою .
Наприклад, ви можете шукати комісію, яка ввела певне виправлення.
Або ви можете шукати першу комісію, в якій назви файлів вихідного коду нарешті були перетворені на стандарт іменування вашої компанії. Або що завгодно.У таких випадках може бути дуже заплутаним використання термінів "хороший" та "поганий" для позначення "стан перед зміною" та "стан після зміни".
Тож замість цього ви можете використовувати терміни "
old
" і "new
" відповідно замість "good
" і "bad
".
(Але зауважте, що ви не можете змішувати "good
" і "bad
" з "old
" і "new
" за один сеанс.)У цьому більш загальному використанні ви надаєте,
git bisect
що "new
" коміт має деяку властивість та "old
" комісію, яка не має цього властивості.Кожен раз, коли
git bisect
перевіряєш зобов’язання, ти перевіряєш, чи має цей властивість:
Якщо це так, позначає комісію як "new
"; в іншому випадку позначте його як "old
".Коли бісекція буде зроблена,
git bisect
повідомить про те, який комітет ввів майно.
Див. Команду 06e6a74 , фіксувати 21b55e3 , фіксувати fe67687 (29 червня 2015 р.) Матьє Моя ( moy
) .
Див. Комітет 21e5cfd (29 червня 2015 р.) Від Антуана Делейта (CanardChouChinois
) .
(Об’єднав Хуніо С Хамано - gitster
- у комітеті 22dd6eb , 05 жовтня 2015 р.)