처음 잘못된 견적이 나온 버전 찾기

GitBeginner
지금 연습하기

소개

Little Pine Goods는 작은 선물의 수령용 견적을 만듭니다. 고객이 FRIEND10 혜택에 약속된 할인이 더 이상 적용되지 않는다고 알려 왔습니다. 최근 이력에는 유용한 상품, 문구, 수령 정보 업데이트도 있으므로 매장 전체를 과거 버전으로 돌리면 올바른 작업을 잃게 됩니다.

정상 주문과 문제가 있는 선물 주문을 실행한 뒤, 준비된 결정적 업무 테스트로 과거 버전을 분류하세요. 먼저 Git 이진 탐색을 조금 수동으로 연습한 다음 같은 테스트로 탐색을 자동화합니다. 처음 문제가 생긴 스냅샷과 바로 앞 부모를 비교하고 탐색을 종료한 뒤, 후속 업데이트를 유지하면서 현재 매장을 수정하세요. 수정 커밋뿐 아니라 고객이 사용할 완전한 견적 파일도 전달합니다.

기본적인 터미널 경로 이동, 커밋, 브랜치, 간단한 log/diff 읽기를 알고 있어야 합니다. Git bisect, 임시 분리 체크아웃, 테스트 종료 상태, 작은 혜택 파일 편집은 여기서 설명합니다. Python과 견적 프로그램은 준비되어 있으며 Python 코드를 작성하지 않고 실행만 합니다. 하나의 교육용 머신에서 실제 로컬 Git 이력과 파일 기반 견적 도구를 사용하며 주문은 가상이고 가격은 EUR 단위입니다. 웹사이트, 호스팅 계정, 네트워크 배포는 필요하지 않습니다. 기본 Terminal을 사용하세요. 소요 시간 50분은 저자의 추정치입니다.

처음 잘못된 견적이 나온 버전 찾기

이 단계에서는 올바른 업무 결과를 정하고 실제 과거 스냅샷을 테스트하여 할인이 잘못되기 시작한 경계를 찾습니다.

Terminal에서 시작하여 매장 저장소로 들어가세요.

cd /home/labex/project/quote-desk/shop

cd는 이 터미널의 디렉터리를 바꿉니다. 경로를 잘못 입력했다면 pwd로 현재 위치를 출력하고 ls로 해당 디렉터리를 나열한 다음 위의 전체 cd 명령을 다시 실행하세요. 일반적인 이동 오류 때문에 VM을 초기화할 필요는 없습니다.

고객 요청을 읽으세요. cat은 텍스트 파일을 표시하고 ..는 부모 디렉터리를 뜻합니다.

cat ../request.txt

FRIEND10은 상품 소계의 10% 할인을 약속합니다. 배송비나 세금은 없습니다. 선물 주문은 개당 EUR 16.00인 캠프 머그 세 개이므로 소계 EUR 48.00, 할인 EUR 4.80, 합계 EUR 43.20입니다. 기존 카탈로그, 주문, 정책이 업무상 기준입니다. 잘못된 결과에 맞추려고 이를 바꾸지 마세요.

먼저 정상 주문을 실행하세요. python3는 제공된 프로그램 quote.py를 실행하고, 그 다음 인수는 준비된 주문 파일입니다. Python 소스를 편집하거나 이해할 필요는 없습니다.

python3 quote.py ../orders/plain.order

머그 하나 주문은 쿠폰 NONE을 사용합니다. 소계와 합계 EUR 16.00, 할인 EUR 0.00, 현재 환영 문구, 토요일 16:00까지의 수령 정보가 표시되어야 합니다. 이를 통해 실제로 쓸 수 있는 정상 견적을 확인합니다.

문제가 보고된 주문을 실행하세요.

python3 quote.py ../orders/gift.order

직전 명령의 원래 종료 상태를 읽으려면 셸 값 $?를 사용합니다. echo는 그 값을 출력합니다. 견적 명령 직후에 실행하세요.

echo $?

0이 표시되어야 합니다. 금액 결과는 틀렸지만 프로그램 자체는 정상적으로 실행되었습니다.

프로그램은 실행되지만 견적은 잘못되어 할인 EUR 0.48, 합계 EUR 47.52가 나옵니다. 프로그램의 성공적인 종료와 올바른 업무 답변은 다릅니다.

준비된 테스트는 저장소 밖에 있으므로 과거 버전을 체크아웃해도 교체되지 않습니다. 여러 수량과 쿠폰 없는 대조 주문으로 실제 견적 프로그램을 실행하고, 전체 결과를 변경되지 않은 혜택 정책과 비교합니다. 실행하세요.

python3 /opt/labex/quote-desk/check.py

같은 셸 값으로 이 테스트의 상태를 즉시 읽으세요.

echo $?

1이 표시되어야 합니다. 테스트가 업무 결과의 불일치를 발견한 것입니다.

FRIEND10에 대한 FAIL 줄과 원래 종료 상태 1이 예상됩니다. NONE 대조 주문은 통과합니다. 테스트는 올바른 견적이면 0, 이 업무 오류이면 1, 버전을 테스트할 수 없으면 128을 반환합니다. 테스트 불가능 상태에서는 할인 회귀 오류라고 추측하지 말고 탐색을 중단해야 합니다. 준비된 이력에는 빌드 실패나 건너뛰는 버전이 없습니다.

현재 브랜치와 깨끗한 상태를 확인하세요. branch --show-current는 브랜치를 출력하고 --short는 간결한 파일 목록을 만듭니다.

git branch --show-current
git status --short

main이 표시되고 변경 파일 출력은 없어야 합니다. 탐색 중에는 매장을 깨끗하게 유지하세요. 이력을 읽으세요. --no-pager는 스크롤 뷰어에 들어가지 않고 바로 출력하고, --oneline은 항목을 짧게 표시하며, --decorate는 브랜치와 태그에 이름표를 붙입니다.

git --no-pager log --oneline --decorate

고정 태그 incident-tip은 처음 전달받은 현재 끝 커밋을, known-good는 이전의 정상 버전을 표시합니다. 커밋 제목은 작업을 설명하지만 그 문구가 언제 견적에 문제가 생겼는지 입증하지는 않습니다. 두 태그와 처음 전달받은 모든 커밋을 보존하세요.

테스트의 --revision 옵션은 체크아웃을 바꾸거나 수정하지 않고 임시 격리 디렉터리에서 선택한 커밋 스냅샷을 실행합니다. 실제 동작으로 양 끝을 확인하세요.

python3 /opt/labex/quote-desk/check.py --revision known-good
python3 /opt/labex/quote-desk/check.py --revision incident-tip

첫 명령은 상태 0으로 통과해야 합니다. 두 번째는 상태 1로 실패해야 합니다. 정상 버전과 그 뒤의 잘못된 버전이 탐색 범위를 정합니다. 이 연습에서는 해당 구간에서 오류가 한 번 도입되며 그 뒤의 수정은 없습니다.

두 버전 직접 분류하기

Git bisect는 경계 사이의 버전을 테스트하여 구간을 좁힙니다. 알려진 잘못된 리비전을 먼저, 알려진 정상 리비전을 두 번째로 지정하여 시작하세요.

git bisect start incident-tip known-good

Git은 중간 스냅샷을 체크아웃하고 남은 구간을 출력합니다. 탐색 중 detached HEAD는 main을 이동시키는 대신 커밋을 직접 보고 있다는 뜻입니다. 이 임시 버전에서 편집하거나 커밋하지 마세요.

체크아웃된 스냅샷에 같은 테스트를 실행하세요.

python3 /opt/labex/quote-desk/check.py

준비된 이 첫 선택은 상태 1로 실패합니다. 관찰한 버전을 bad로 분류하세요. bad는 커밋 메시지가 아니라 업무 테스트 결과를 설명합니다.

git bisect bad

Git이 다른 스냅샷을 선택합니다. 추측하지 말고 테스트하세요.

python3 /opt/labex/quote-desk/check.py

이 선택은 상태 0으로 통과합니다. 관찰한 결과를 기록하세요.

git bisect good

Git이 구간을 다시 좁힙니다. 각 결과가 탐색 공간의 일부를 제거하는 것을 확인했습니다. 같은 원래 경계에서 자동 방식을 연습하려면 먼저 미완성 탐색을 종료하세요. bisect reset은 탐색 상태를 지우고 시작한 브랜치와 리비전으로 돌아갑니다. 커밋을 되돌리지는 않습니다.

git bisect reset
git branch --show-current

main이 표시되어야 합니다. 연습 중 버전을 잘못 분류했다면 같은 reset 후 새로 시작하여 파일을 버리지 않고 실제 테스트 결과에 따라 반복할 수 있습니다.

테스트로 탐색 진행하기

다시 시작한 다음 bisect run에 같은 전체 테스트 명령을 전달하세요. Git은 각 실행의 원래 종료 상태로 good 또는 bad를 자동 선택합니다.

git bisect start incident-tip known-good
git bisect run python3 /opt/labex/quote-desk/check.py

여러 번의 테스트와 is the first bad commit으로 끝나는 줄이 표시되어야 합니다. 일부 개별 견적 테스트가 실패하더라도 경계를 찾는 데 성공하면 탐색 명령 자체는 상태 0으로 끝납니다. 커밋 ID는 다를 수 있습니다.

Git의 bisect/bad 참조는 찾아낸 첫 번째 잘못된 커밋을 가리킵니다. 현재 HEAD는 마지막으로 테스트한 정상 버전에 머물러 있을 수 있습니다. 보고된 결과와 같다고 가정하지 마세요. 실제 후보 패치를 읽으세요. show는 해당 커밋과 패치를 선택하고 --는 파일 경로를 구분합니다.

git --no-pager show bisect/bad -- discounts.txt

FRIEND10 비율이 10에서 1로 바뀌었습니다. 외부 테스트로 양쪽을 확인하세요. 뒤에 붙는 ^는 커밋의 직접적인 첫 번째 부모 하나를 선택하므로, bisect/bad^는 범위 전체가 아니라 후보 바로 이전 버전입니다.

python3 /opt/labex/quote-desk/check.py --revision bisect/bad
python3 /opt/labex/quote-desk/check.py --revision bisect/bad^

후보는 상태 1로 실패하고 부모는 상태 0으로 통과해야 합니다. 값과 실제 동작이 일치합니다. 이 확인 항목을 위해 완료된 탐색을 열린 상태로 두세요. 다음에는 편집 전에 현재 매장으로 돌아갑니다.

현재 매장 수정하고 견적 전달하기

이 단계에서는 과거 이력 탐색을 종료하고 현재 브랜치에 필요한 부분만 수정한 커밋을 만든 뒤, 후속 상품이나 수령 정보를 잃지 않고 완전한 견적을 전달합니다.

Terminal의 /home/labex/project/quote-desk/shop에서 계속 진행하세요. 배운 탐색 reset으로 원래 브랜치로 돌아가세요.

git bisect reset
git branch --show-current
git --no-pager log -1 --oneline --decorate
git status --short

main, incident-tip으로 표시된 처음 전달받은 끝 커밋이 표시되고 변경 파일 출력은 없어야 합니다. log 옵션 -1은 출력을 최신 커밋 하나로 제한합니다. 분리된 과거 버전을 수정하거나 매장 전체를 known-good로 교체하지 마세요. 이후의 올바른 작업도 결과에 포함되어야 합니다.

작은 혜택 파일과 보존해야 할 현재 정보를 읽으세요.

cat discounts.txt
cat welcome.txt pickup.txt care.txt
cat catalog.json

현재 트리에는 Trail pin, 새 환영 문구, 토요일 16:00까지의 수령 정보가 있습니다. 잘못된 것은 FRIEND10 비율뿐입니다. 혜택 파일은 한 줄에 CODE=integer-percent 설정 하나를 씁니다. TRAIL15는 15, STUDENT5는 5로 유지합니다.

이 작은 파일만 교체하세요. printf는 형식에 따라 값을 출력합니다. %s는 텍스트를 뜻하고 \n은 전달한 각 값 뒤에 줄바꿈을 추가합니다. 작은따옴표는 텍스트를 그대로 유지합니다. >는 지정한 파일에 출력을 써서 해당 파일만 교체합니다.

printf '%s\n' 'FRIEND10=10' 'TRAIL15=15' 'STUDENT5=5' > discounts.txt

실제 수정 내용을 검토하세요. 일반 diff는 작업 파일과 Git의 스테이징 영역인 인덱스를 비교합니다.

git --no-pager diff -- discounts.txt

FRIEND10이 1에서 10으로 돌아가는 변경만 표시되어야 합니다. 수정을 기록하기 전에 저장소 로컬 커밋 작성자 정보를 설정하세요. --local은 전역 설정을 바꾸지 않으며, 따옴표는 공백이 있는 이름을 하나로 묶습니다. 다음 가상 예시는 바꿔도 됩니다.

git config --local user.name "Little Pine Maintainer"
git config --local user.email "maintainer@little-pine.example"

add로 해당 파일을 스테이징하세요. 인덱스와 현재 커밋을 비교하는 --cached로 스테이징된 패치를 살펴보세요.

git add discounts.txt
git --no-pager diff --cached -- discounts.txt

필요한 부분만 고친 수정을 커밋하세요. -m은 의미 있는 메시지를 직접 지정합니다.

git commit -m "Restore the promised FRIEND10 discount"

처음 전달받은 고정 끝 커밋과 비교하세요. 이력을 다시 쓰지 않고 모든 원래 커밋을 유지하면서 새 수정 커밋 하나를 추가한 것입니다.

git --no-pager diff incident-tip HEAD
git --no-pager log -2 --oneline --decorate
git status --short

비율 수정만 있고, 수정 커밋이 incident-tip 바로 다음에 있으며, 추적 파일 상태가 깨끗해야 합니다. 정확한 메시지나 작성자 값은 성공 기준이 아닙니다.

실제 현재 프로그램에 준비된 테스트를 실행하세요.

python3 /opt/labex/quote-desk/check.py

이제 모든 사례가 상태 0으로 통과합니다. 고객의 견적을 생성하세요.

python3 quote.py ../orders/gift.order

현재 머그 설명과 환영 문구, 수량 3, FRIEND10, 소계 EUR 48.00, 할인 EUR 4.80, 합계 EUR 43.20, 토요일 16:00까지의 현재 수령 정보가 표시되어야 합니다.

실제 출력을 준비된 quotes 디렉터리에 전달하세요. 배운 대로 >는 표준 출력을 이 이름의 파일에 저장하며 주문이나 프로그램은 바꾸지 않습니다.

python3 quote.py ../orders/gift.order > ../quotes/mug-gift.txt
cat ../quotes/mug-gift.txt

파일 이름만 보지 말고 저장된 견적 전체를 읽으세요. 파일은 고객이 사용할 결과물이며 커밋은 수정을 반복해서 사용할 수 있게 합니다.

계속 사용할 수 있어야 하는 정상 주문과 후속 상품을 확인하세요.

python3 quote.py ../orders/plain.order
python3 quote.py ../orders/new-item.order

일반 머그는 EUR 16.00으로 유지됩니다. STUDENT5를 적용한 Trail pin 두 개는 소계 EUR 10.00, 할인 EUR 0.50, 합계 EUR 9.50입니다. 둘 다 현재 환영 문구와 수령 정보를 유지합니다. 확인 항목은 실제 현재 커밋, 보존된 전체 트리, 과거 경계의 동작, 전달된 견적을 관찰하며, 명령 실행 기록이나 메시지 키워드를 채점하지 않습니다.

요약

정상 주문과 잘못된 주문으로 업무 테스트를 정의하고 과거 버전을 수동으로 분류한 뒤 Git bisect로 같은 탐색을 자동화했습니다. 첫 번째 잘못된 커밋을 가리키는 참조와 HEAD를 구분하고 후보와 부모를 검증한 뒤 main으로 돌아와, 후속 매장 업데이트를 잃지 않고 필요한 부분만 수정하여 커밋했습니다. 고객은 완전하고 정확한 견적을 받았습니다.

독립 챌린지에서는 쿠폰, 고객 주문, 오류 위치가 달라지지만 같은 제공 프로그램, 정책, 테스트 형식을 사용합니다. 커밋 오프셋을 복사하지 말고 실제 증거를 보고 선택하세요.