git bisect run automatyczna dwusieczna
Jeśli masz zautomatyzowany ./testskrypt, który ma status wyjścia 0, jeśli test jest OK, możesz automatycznie znaleźć błąd za pomocą 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
To oczywiście zakłada, że jeśli skrypt testowy ./testjest śledzony przez git, to nie znika po wcześniejszym zatwierdzeniu podczas bisekcji.
Przekonałem się, że bardzo często możesz uciec, po prostu kopiując skrypt z drzewa z drzewa i prawdopodobnie bawiąc się PATHzmiennymi podobnymi do niego i uruchamiając go stamtąd.
Oczywiście, jeśli infrastruktura testowa, od której testzależy test, psuje się na starszych zatwierdzeniach, nie ma rozwiązania i trzeba będzie wykonać czynności ręcznie, decydując, jak testować zatwierdzenia jeden po drugim.
Przekonałem się jednak, że korzystanie z tej automatyzacji często działa i może być ogromną oszczędnością czasu dla wolniejszych testów leżących w zaległych zadaniach, gdzie możesz po prostu pozwolić jej działać przez noc i być może wykryć swój błąd do następnego ranka, warto próba.
Więcej porad
Pozostań przy pierwszym nieudanym zatwierdzeniu po bisecta zamiast wracać do master:
git bisect reset HEAD
start+ inicjał badi goodza jednym razem:
git bisect start KNOWN_BAD_COMMIT KNOWN_GOOD_COMMIT~
jest taki sam jak:
git checkout KNOWN_BAD_COMMIT
git bisect start
git bisect bad
git bisect good KNOWN_GOOD_COMMIT
Zobacz, co zostało przetestowane do tej pory (ręcznie goodi badlub run):
git bisect log
Przykładowe dane wyjściowe:
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
Pokaż dobre i złe referencje w dzienniku git, aby uzyskać lepszy obraz czasu:
git log --decorate --pretty=fuller --simplify-by-decoration master
To pokazuje tylko zatwierdzenia z odpowiednim ref, co zmniejsza szarość, ale obejmuje automatycznie generowane ref:
refs/bisect/good*
refs/bisect/bad*
które mówią nam, które zobowiązania oznaczyliśmy jako dobre lub złe.
Rozważ to testowe repozytorium, jeśli chcesz pobawić się poleceniem.
Awaria jest szybka, sukces powolna
Czasami:
- awaria zdarza się szybko, np. jeden z pierwszych testów się psuje
- sukces zajmuje trochę czasu, np. zepsuty test zdaje, a wszystkie inne testy, których nie obchodzi nas przestrzeganie
W takich przypadkach, np. Zakładając, że awaria zawsze zdarza się w ciągu 5 sekund, a jeśli jesteśmy leniwi, aby uczynić test bardziej szczegółowym, tak jak powinniśmy, możemy użyć timeoutjak w:
#!/usr/bin/env bash
timeout 5 test-command
if [ $? -eq 1 ]; then
exit 1
fi
Działa to od timeoutwyjścia, 124podczas gdy awaria test-commandwyjść 1.
Magiczne statusy wyjścia
git bisect run jest nieco wybredny co do statusów wyjścia:
cokolwiek powyżej 127 powoduje, że bisekcja zawodzi z czymś takim jak:
git bisect run failed:
exit code 134 from '../test -aa' is < 0 or >= 128
W szczególności C assert(0)prowadzi do a SIGABRTi wychodzi ze statusem 134, co jest bardzo denerwujące.
125 to magia i sprawia, że bieg jest pomijany git bisect skip.
Ma to na celu pomóc w pomijaniu uszkodzonych wersji z niepowiązanych powodów.
Zobacz man git-bisectszczegóły.
Więc możesz chcieć użyć czegoś takiego:
#!/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"
Testowane na git 2.16.1.