Bunun git bisect
harika olduğunu söyleyen bazı makaleler okudum . Ancak, ana dili İngilizce değilim ve neden harika olduğunu anlayamıyorum.
Birisi lütfen bazı kod örneği ile gösterebilir:
- Bu nasıl kullanılır?
- Aynen öyle
svn blame
mi?
Bunun git bisect
harika olduğunu söyleyen bazı makaleler okudum . Ancak, ana dili İngilizce değilim ve neden harika olduğunu anlayamıyorum.
Birisi lütfen bazı kod örneği ile gösterebilir:
svn blame
mi?Yanıtlar:
Bunun arkasındaki fikir git bisect
, tarihte belirli bir gerileme bulmak için ikili bir arama yapmaktır. Aşağıdaki geliştirme geçmişine sahip olduğunuzu düşünün:
... --- 0 --- 1 --- 2 --- 3 --- 4* --- 5 --- current
Programınızın current
revizyonda düzgün çalışmadığını ve revizyonda çalıştığını biliyorsunuz 0
. Regresyon olasılıkla kaydedilmesini birinde tanıtıldı Yani 1
, 2
, 3
, 4
, 5
, current
.
Her bir taahhüdü kontrol etmeyi, inşa etmeyi, regresyonun var olup olmadığını kontrol etmeyi deneyebilirsiniz. Çok sayıda taahhüt varsa, bu uzun zaman alabilir. Bu doğrusal bir aramadır. İkili arama yaparak daha iyisini yapabiliriz. Bu ne git bisect
komut yok. Her adımda potansiyel olarak kötü olan revizyon sayısını yarı yarıya azaltmaya çalışır.
Komutu şu şekilde kullanacaksınız:
$ 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
Bu komuttan sonra, git
bir taahhütte bulunulur. Bizim durumumuzda, taahhüt edilecek 3
. Programınızı oluşturmanız ve regresyonun mevcut olup olmadığını kontrol etmeniz gerekir. git
Bu düzeltmenin durumunu git bisect bad
, regresyon git bisect good
varsa veya yoksa da söylemeniz gerekir .
Diyelim ki regresyon tamamlandı 4
. O zaman bu revizyonda regresyon mevcut değildir ve bunu söyleriz git
.
$ make
$ make test
... ... ...
$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[< ... sha ... >] 5
Daha sonra başka bir taahhütte bulunacaktır. Ya 4
ya 5
(sadece iki taahhüt olduğu için). Diyelim ki onu aldım 5
. Bir derlemeden sonra programı test ediyoruz ve regresyonun mevcut olduğunu görüyoruz. Daha sonra şunu söyleriz git
:
$ make
$ make test
... ... ...
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[< ... sha ... >] 4
Son revizyonu test ediyoruz 4
. Ve regresyonu başlatan kişi olduğu için şunu söylüyoruz git
:
$ make
$ make test
... ... ...
$ git bisect bad
< ... sha ... > is the first bad commit
< ... commit message ... >
Bu basit durumda, sadece teste 3 sürümleri vardı ( 3
, 4
, 5
) yerine 4 ( 1
, 2
, 3
, 4
). Bu küçük bir galibiyet, ama bunun nedeni tarihimizin çok küçük olması. Arama aralığı N olarak ayarlanmışsa, git bisect
kabaca N / 2'nin doğrusal bir arama ile yapması yerine, 1 + log2 N'nin test etmesini beklemeliyiz .
Regresyonu başlatan taahhüdü bulduktan sonra, sorunu bulmak için çalışabilirsiniz. Bu yapıldıktan sonra, komutu git bisect reset
kullanmadan önce her şeyi orijinal durumuna geri koymak için git bisect
kullanın.
git bisect bad <rev> [<rev>...]
Belirli düzeltmeleri kötü (veya iyi git bisect good <rev> [<rev>...]
) olarak işaretlemek için kullanabilirsiniz . rev
bir şube adı, bir etiket, bir karma karması (veya karma karmasının benzersiz öneki), ... gibi herhangi bir düzeltme tanımlayıcısı olabilir ...
git bisect reset
her şeyi son
git bisect run
otomatik ikiye bölme./test
Test tamamsa 0 çıkış durumuna sahip otomatik bir komut dosyanız varsa, hatayı otomatik olarak şu şekilde bulabilirsiniz 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
Bu, elbette, test komut dosyası ./test
git izlenirse, ikiye ayırma sırasında daha önceki bazı taahhütlerde kaybolmadığını varsayar .
Çok sık, sadece ağaç içi komut dosyasını ağaçtan kopyalayarak ve muhtemelen- PATH
benzeri değişkenlerle oynayarak ve oradan çalıştırarak kurtulabileceğinizi gördüm .
Tabii ki, test
daha eski taahhütlere bağlı olan test altyapısı varsa, çözüm yoktur ve işleri nasıl yapacağınızı tek tek nasıl yapacağınıza karar vererek işleri manuel olarak yapmanız gerekecektir.
Bununla birlikte, bu otomasyonu kullanmanın genellikle işe yaradığını ve görevlerin birikiminde yatan daha yavaş testler için büyük bir zaman tasarrufu sağlayabildiğini gördüm, burada bir gecede çalışmasına izin verebilirsiniz ve muhtemelen hatalarınızı ertesi sabah tanımlamanıza değer deneyin.
İki noktadan sonra yerine geri dönmek yerine ilk başarısızlık taahhüdünde kalın master
:
git bisect reset HEAD
start
+ ilk bad
ve good
bir seferde:
git bisect start KNOWN_BAD_COMMIT KNOWN_GOOD_COMMIT~
aynıdır:
git checkout KNOWN_BAD_COMMIT
git bisect start
git bisect bad
git bisect good KNOWN_GOOD_COMMIT
Şimdiye kadar nelerin test edildiğini görün (manuel good
ve bad
veya run
):
git bisect log
Örnek çıktı:
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
Daha iyi bir zaman kavramı elde etmek için git günlüğünde iyi ve kötü referansları göster:
git log --decorate --pretty=fuller --simplify-by-decoration master
Bu sadece karşılık gelen bir ref ile taahhütleri gösterir, bu da gürültüyü büyük ölçüde azaltır, ancak türün otomatik olarak oluşturulmuş ref'lerini içerir:
refs/bisect/good*
refs/bisect/bad*
hangi taahhütleri iyi veya kötü olarak işaretlediğimizi söyler.
Komutla oynamak istiyorsanız bu test deposunu düşünün .
Ara sıra:
Bu gibi durumlarda, örneğin hatanın her zaman 5 saniye ile gerçekleştiğini varsayarsak ve testi gerçekten olması gerektiği gibi daha spesifik hale getirmek için tembel kalırsak, aşağıdaki gibi kullanabiliriz timeout
:
#!/usr/bin/env bash
timeout 5 test-command
if [ $? -eq 1 ]; then
exit 1
fi
Bu yana çalışan timeout
çıkışların 124
başarısızlığı ise test-command
çıkışlarında 1
.
git bisect run
çıkış durumları hakkında biraz seçici:
127'nin üzerindeki herhangi bir şey, bölünmeyi aşağıdaki gibi bir şeyle başarısız kılar:
git bisect run failed:
exit code 134 from '../test -aa' is < 0 or >= 128
Özellikle, bir C assert(0)
bir SIGABRT
134'e yol açar ve çok rahatsız edici olan durum 134 ile çıkar.
125 büyülüdür ve koşuyu atlar git bisect skip
.
Bunun amacı, ilgisiz nedenlerden dolayı kırık yapıların atlanmasına yardımcı olmaktır.
Ayrıntılar man git-bisect
için bakınız.
Yani şöyle bir şey kullanmak isteyebilirsiniz:
#!/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'de test edilmiştir.
test_script
+ modüler test takımıyla gerekli test plakasını ekleyin ve ikiye ayırırken ayrı dosyadan çalıştırın. Düzelttiğinizde, testi ana test paketiyle birleştirin.
bisect run
Testin tamamlanması uzun zaman aldığında özellikle yararlı buluyorum ve test sisteminin kırılmayacağından eminim. Bu şekilde, onu herhangi bir beyin bağlamı geçiş zamanını kaybetmeden arka planda çalıştırabilir veya çok fazla kaynak alırsa bir gecede bırakabilirim.
$ git bisect start
$ git bisect bad
$ git bisect good <goodcommit>
Bisecting: X revisions left to test after this (roughly Y steps)
Sorun hala var mı?
$ git bisect bad
$ git bisect good
<abcdef> is the first bad commit
git bisect reset
git bisect good
sonraki işleme geçmek için düzeltin .
Sadece bir nokta daha eklemek için:
git bisect start
Hatanın belirli dosyalardan geldiğini bilmemiz durumunda bir dosya adı veya yolu belirleyebiliriz . Örneğin, regresyona neden olan değişikliklerin com / workingDir dizininde olduğunu bildiğimizi varsayalım, o zaman çalıştırabiliriz git bisect start com/workingDir
.
Ayrıca, belirli bir taahhüdün iyi mi kötü mü olduğunu söylemek zorsa, çalıştırabilirsiniz git bisect skip
, bu da görmezden gelir. Yeterli başka taahhüt olduğu düşünüldüğünde, git bisect aramayı daraltmak için bir başkasını kullanacaktır.
$ git bisect ..
temelde hata ayıklama için bir Git aracı . 'Git Bisect' son (bilinen) çalışma taahhüdünüzden bu yana önceki taahhütlerden geçerek hata ayıklar . Tüm bu taahhütleri atlatmak, regresyon / hatayı tanıtan birine ulaşmak için ikili arama kullanır.
$ git bisect start
# Başlangıç bisect
$ git bisect bad
# geçerli işlemin (v1.5) regresyon / ayar 'kötü' noktasına sahip olduğunu belirterek
$ git bisect good v1.0
# son iyi çalışma taahhüdünden bahsediyor (regresyon olmadan)
'Kötü' ve 'iyi' noktalardan bahsetmek git bisect'in (ikili arama) orta elemanı seçmesine yardımcı olacaktır (v1.3 taahhüdü). Regresyon, v1.3 komutunda varsa, bunu yeni 'kötü' nokta olarak ayarlarsınız, yani ( İyi -> v1.0 ve Kötü -> v1.3 )
$ git bisect bad
veya benzer bir şekilde v1.3 komutu hatasız ise, yeni 'İyi nokta' olarak ayarlarsınız (yani * İyi -> v1.3 ve Kötü -> v1.6).
$ git bisect good
Not: Belirli bir mülkle veya belirli bir mülk olmadan bir taahhüdü işaretlemek için kullanabileceğiniz terimler good
ve bad
yalnızca terimler değildir.
Git 2.7 (4. Çeyrek 2015) yeni git bisect
seçenekler sundu .
git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
Belgeler eklenerek:
Bazen bir kırılma getiren taahhüdü değil, başka bir "eski" durum ile "yeni" durum arasında bir değişikliğe neden olan bir taahhüdü arıyorsunuz .
Örneğin, belirli bir düzeltmeyi getiren taahhüdü arıyor olabilirsiniz.
Veya kaynak kod dosya adlarının sonunda şirketinizin adlandırma standardına dönüştürüldüğü ilk taahhüdü arıyor olabilirsiniz. Ya da her neyse.Bu gibi durumlarda, "değişiklikten önceki durum" ve "değişiklikten sonraki durum" anlamına gelmek için "iyi" ve "kötü" terimlerini kullanmak çok kafa karıştırıcı olabilir.
Bunun yerine, aşağıdaki terimleri "kullanabilirsiniz
old
" ve "new
" yerine sırasıyla "good
" ve "bad
".
(Ama "karıştırmak olamaz notugood
" ve "bad
" "ileold
" ve "new
tek bir oturumda".)Bu daha genel kullanımda,
git bisect
"new
" taahhüdünün bir özelliği vardır veold
bu özelliği olmayan bir " " taahhüdü sağlarsınız.
git bisect
Bir taahhüdü her kontrol ettiğinde, söz konusu taahhüdün özelliği olup olmadığını test edersiniz:
Varsa, taahhüdü "new
" olarak işaretleyin ; aksi halde "old
" olarak işaretleyin .İkiye bölme bittiğinde,
git bisect
hangi taahhüdün mülkü tanıttığını rapor edecektir.
Bkz. Taahhüt 06e6a74 , taahhüt 21b55e3 , taahhüt fe67687 (29 Haziran 2015), Matthieu Moy ( moy
) .
Bakınız Antoine Delaite ( ) tarafından 21e5cfd (29 Haz 2015) taahhüdüCanardChouChinois
.
(Tarafından Birleştirilmiş Junio C Hamano - gitster
- içinde taahhüt 22dd6eb , 5 Ekim 2015)