자식 bisect를 사용하는 방법?


438

나는 그것이 git bisect굉장 하다는 기사를 읽었습니다 . 그러나 나는 원어민이 아니며 왜 멋진 지 이해할 수 없습니다.

누군가 코드 샘플로 시연 할 수 있습니까?

  1. 사용 방법?
  2. 그냥 같은 svn blame가요?

@ 01 : git book에서 말한 것처럼 : 프로젝트 기록을 통해 무차별 검색을 수행하십시오 .
eckes

7
/// brute :-) 이진 검색을 사용합니다.
cojocar

"git blame"은 "svn blame"과 유사합니다. "git bisect"는 완전히 다른 것입니다
William Pursell

그 가치에 대해서는 Pro Git 에도 bisect에 대한 좋은 설명이 있습니다. 실뱅의 대답은 또 다른 좋은 기회입니다. 모든 것을 살펴본 후에도 여전히 이해가 가지지 않으면 더 구체적인 질문을하시기 바랍니다. 일반적인 질문은 일반적인 답변을 얻습니다.
Cascabel

답변:


655

아이디어 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커밋을 체크 아웃합니다. 우리의 경우에는 commit 3입니다. 프로그램을 작성하고 회귀가 있는지 확인해야합니다. 또한 회귀가 존재하거나 존재 하지 않는 git경우이 개정의 상태 를 알려야 합니다 .git bisect badgit bisect good

회귀가 commit에 도입되었다고 가정 해 봅시다 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 커밋 인 git bisect경우 선형 검색 을 사용하여 대략 N / 2 커밋 대신 1 + log2 N 커밋을 테스트해야합니다 .

회귀를 도입 한 커밋을 발견하면 문제를 찾기 위해이를 연구 할 수 있습니다. 이 작업이 완료되면 명령 git bisect reset을 사용하기 전에 모든 것을 원래 상태로 되돌릴 수 있습니다 git bisect.


5
여기서는 반대로, 이것은 bisect에 대한 좋은 설명이지만 실제로 사용하는 데 도움이되지 않습니다. 특히 나는 좋은 커밋을 찾았고 지금 그 지점에 있습니다. 이 입장에서이 설명은 전혀 도움이되지 않습니다. 예를 들어 체크 아웃하지 않고 불량 브랜치를 지정하는 방법
PandaWood

4
git bisect bad <rev> [<rev>...]특정 개정을 불량 (또는 양호 git bisect good <rev> [<rev>...]) 으로 표시 하는 데 사용할 수 있습니다 . rev모든 수정 지점 이름 같은 식별자, 태그, 커밋 해시 (또는 고유 접두어 커밋 해시), ... 일 수있다
실뱅 Defresne

39
... 그리고 당신이 완료되면, 당신 git bisect reset은 최근 커밋에 모든 것을 다시 넣어 입력 합니다
peetonn

17
스택에서 가장 멋진 답변 중 하나입니다. 아주 잘 표현되어 있습니다. 나는 수년간이 과정을 수동으로 수행해 왔으며, 좋은 커밋과 나쁜 커밋 사이의 임의의 중간 지점을 선택한 다음 그 자체가 좋은지 나쁜지에 따라 다시 한 번 좋은 쪽과 나쁜 쪽 사이를 선택합니다. 그것은 항상 엉덩이에 큰 고통이었고 오늘 까지이 자식 하위 명령을 들어 본 적이 없었습니다 ... hahaha
Chev

3
@Nemoden, 예, 기본적으로 모든 유형의 프로젝트에 유용 할 수 있습니다. "웹 사이트 배포 및 문제 재현"으로 "make test"단계를 교체하면됩니다.
alex.b

159

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가 git track되면, bisection 동안 이전 커밋에서 사라지지 않는다고 가정합니다.

인 트리 스크립트를 트리에서 복사하고 PATH비슷한 변수로 재생하고 대신 거기에서 실행하면 매우 자주 벗어날 수 있습니다 .

물론, 테스트 인프라가 test이전 커밋에 영향을 미치는 경우 솔루션이 없으므로 커밋을 하나씩 테스트하는 방법을 결정하여 수동으로 작업을 수행해야합니다.

그러나이 자동화를 사용하면 종종 작동하며 작업 백 로그에 누워있는 느린 테스트의 경우 시간을 절약 할 수 있다는 것을 알았습니다. 시도.

더 많은 팁

bisect 후 다음으로 돌아 가지 않고 첫 번째 실패 커밋을 유지하십시오 master.

git bisect reset HEAD

start+ 이니셜 badgood한 번에 :

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

지금까지 테스트 한 내용을 참조하십시오 (수동 goodbad또는 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 log에 좋고 나쁜 참조를 표시하십시오.

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)는 a로 이어지고 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"

자식 2.16.1에서 테스트되었습니다.


7
git은 이전 / 나쁜 개정판 (새로 작성된 시험이 없었던)으로 되돌릴 때 다시 새 시험이 사라지지 않도록 어떻게 알 수 있습니까?
thebjorn

8
@thebjorn 당신은 요점을 알 수 있습니다 : 내가 아는 한, 테스트는 PATH의 외부 실행 파일 또는 저장소의 추적되지 않은 파일에 있어야합니다. 대부분의 경우 이것이 가능합니다. 테스트를 별도의 파일에 놓고 잘 만들어진 test_script+ 모듈 식 테스트 스위트가 포함 된 필요한 테스트 상용구를 포함 시키고 이등분하는 동안 별도의 파일에서 실행하십시오. 수정하면 테스트를 기본 테스트 스위트로 병합하십시오.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 六四 事件 法轮功 纳米比亚 威 视 죄송합니다. 초보자에게 더 설명이 필요하고 답변에 더 많은 포인트를 추가하기 때문에 아래 편집 내용을 롤백했습니다. 포인트 추가)
Nicks

1
'git bisect run'으로 잘못하는 방법에는 여러 가지가 있습니다. 그것은 들어오고 나왔다 다시 들어오고 마지막 "나쁜"나쁘다. 그러나 항상 수동 'git bisect'를 수행 할 수 있습니다. bisect이므로 몇 단계 만 거치면됩니다 (예 : 10 단계에서 1024 개의 커밋).
combinatorist

1
@ combinatorist 당신은 그것이 실패 할 수도 있습니다 맞습니다. 내가 찾아 bisect run테스트를 완료하는 데 시간이 오래 걸립니다 때 특히 유용합니다, 나는 확신 테스트 시스템이 중단되지 않습니다입니다. 이렇게하면 백그라운드에서 실행하거나 뇌 컨텍스트 전환 시간을 잃지 않고 너무 많은 리소스를 사용하는 경우 밤새도록 할 수 있습니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

124

TL; DR

스타트:

$ 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

3
git repo의 루트에 있는지 확인하십시오. 그렇지 않으면 이상한 "작업 트리의 최상위에서이 명령을 실행해야합니다." 오류.
PR Whitehead

따라서 오류가 없으면 첫 번째 커밋에서 git bad and git good을 잘 수행했습니다. 다음에 무엇을해야합니까? 버그가 없으면 git bisect는 다음 커밋으로 이동하는 것이 좋습니까?
Gobliins 2019

@Gobliins 버그가 없으면 git bisect good다음 커밋으로 이동하도록 수정하십시오 .
Geoffrey Hale

40

추가 포인트를 추가하려면 다음을 수행하십시오.

git bisect start버그가 특정 파일에서 왔다는 것을 알 수 있도록 파일 이름이나 경로를 지정할 수 있습니다. 예를 들어, 회귀의 원인이 된 변경 사항이 com / workingDir 디렉토리에 있다는 것을 알고 있다고 가정 git bisect start com/workingDir하면이 디렉토리의 내용을 변경 한 커밋 만 검사하여 훨씬 빠르게 처리 할 수 ​​있습니다.

또한 특정 커밋이 좋은지 나쁜지를 판단하기 어려운 경우을 실행 git bisect skip하면 무시할 수 있습니다. 다른 커밋이 충분하면 git bisect는 다른 커밋을 사용하여 검색 범위를 좁 힙니다.


15

$ git bisect ..기본적으로 디버깅을위한 Git 도구입니다 . 'Git Bisect' 마지막으로 알려진 커밋 이후 의 이전 커밋을 통해 디버그합니다 . 바이너리 검색을 사용하여 모든 커밋을 거쳐 회귀 / 버그를 도입 한 커밋을 얻습니다.

$ git bisect start # 이등분 시작

$ git bisect bad # 현재 커밋 (v1.5)에 회귀 / 설정 '나쁜'지점이 있음을 나타냅니다.

$ git bisect good v1.0 # 마지막으로 성공한 커밋을 언급 (회귀없이)

'나쁜'점과 '좋은'점을 언급하면 git bisect (바이너리 검색)가 중간 요소 (커밋 v1.3)를 선택하는 데 도움이됩니다 . 커밋 v1.3에 회귀가있는 경우 새로운 '나쁜'포인트로 설정합니다 (예 : Good-> v1.0 및 Bad-> v1.3 )

$ git bisect bad

또는 커밋 v1.3에 버그가없는 경우이를 새로운 'Good point'(예 : * Good-> v1.3 및 Bad-> v1.6)로 설정합니다.

$ git bisect good

2

참고 : 용어 good및 용어 bad는 특정 속성의 유무에 관계없이 커밋을 표시하는 데 사용할 수 있는 용어 는 아닙니다.

Git 2.7 (2015 년 4 분기)에는 새로운 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 커밋 에 의해 (2015년 6월 29일) 마티유 Moy와을 ( moy) . Antoine Delaite ( )의 commit 21e5cfd (2015 년 6 월 29 일)를
참조하십시오 . (가 합병 Junio C 하마노 - -커밋 22dd6eb , 2015년 10월 5일)CanardChouChinois
gitster

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.