LabHub
배우기 러닝패스 코스

Git実戦

取り消した機能を入れ直そうとしたら、合わせるものがないと言われた

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

병합 커밋을 되돌리고 되살리고, 릴리스 브랜치의 수정을 출처를 남기며 가져옵니다. 그리고 무엇이 이미 들어갔는지 기계가 어떻게 판정하는지까지 확인합니다.

왜 중요한가

reset 은 커밋을 지우고 revert 는 뒤집는 커밋을 더합니다. 이미 남에게 간 이력에는 revert 밖에 쓸 수 없는데, 병합 커밋에서는 그 뒤집기가 간단하지 않습니다. 부모가 둘이라 어느 쪽 상태로 돌아갈지를 사람이 말해 주어야 합니다. 그리고 되돌린 다음이 더 중요합니다 — merge 는 이력의 도달 가능성으로 판단하므로, 되돌린 기능을 다시 merge 해도 "합칠 것이 없다" 고 답합니다. 이 두 가지를 모르면 장애 대응 중에 같은 자리에서 30분을 잃습니다. 마지막 두 단계는 백포트 운영의 기본기입니다. 같은 변경이 이미 들어갔는지를 해시가 아니라 patch-id 로 판정한다는 것, 그리고 충돌을 해결해 가져온 커밋은 그 판정에서 빠진다는 것을 직접 만들어 봅니다.

단계

  1. /root/gitx7/repo 에 병합 커밋과 릴리스 브랜치가 있는 이력을 만듭니다.
  2. 병합 커밋을 -m 없이 되돌려 보고, 거절 메시지를 notes/revert-m.txt 에 남긴 뒤 -m 1 로 되돌립니다.
  3. git merge feature 가 무엇이라고 답하는지 notes/reland.txt 에 적고, 되돌림을 되돌려 기능을 되살립니다.
  4. 릴리스의 핫픽스 커밋을 -xmain 에 가져옵니다.
  5. 릴리스의 설정 변경 커밋을 가져오다 충돌하면 --abort 로 물러섰다가, 다시 해서 --continue 로 마칩니다. 과정을 notes/conflict.txt 에 남깁니다.
  6. git cherry -v main release 결과를 notes/cherry.txt 에 남깁니다.
  7. 원본과 가져온 커밋의 patch-id 를 notes/patchid.txt 에 나란히 적습니다.
  8. notes/report.md 에 언제 무엇을 쓰는지 정리합니다.

참고

병합 커밋과 릴리스 브랜치가 있는 이력

/root/gitx7/repo 에 병합 커밋과 릴리스 브랜치가 있는 이력을 만듭니다.

main 에 기본 파일들을 커밋하고, feature 브랜치에서 feature.txt 를 더하고 app.txt 의 둘째 줄을 고친 뒤 --no-ff 로 병합합니다. 그 자리에서 release 를 따서 핫픽스·설정 변경·릴리스 메모 셋을 쌓고, main 으로 돌아와 같은 설정 값을 다르게 고칩니다. 이 마지막 하나가 5단계의 충돌을 만듭니다.

병합 커밋은 어느 쪽으로 돌아갈지 말해야 한다

병합 커밋을 -m 없이 되돌려 보고, 거절 메시지를 notes/revert-m.txt 에 남긴 뒤 -m 1 로 되돌립니다.

병합 커밋 해시는 git rev-list --merges main 으로 찾습니다. 그냥 git revert <해시> 를 하면 거절당합니다 — 그 줄을 그대로 남기세요. -m 1 이 무엇을 기준으로 삼는다는 뜻인지도 적고, --no-edit 을 붙여 편집기 없이 되돌립니다.

다시 merge 해도 합칠 것이 없다

git merge feature 가 무엇이라고 답하는지 notes/reland.txt 에 적고, 되돌림을 되돌려 기능을 되살립니다.

git merge feature 를 그냥 해 보세요. 한 줄로 답합니다. 왜 그렇게 답하는지 적으세요 — merge 는 내용이 아니라 이력의 도달 가능성으로 판단합니다. 되살리는 방법은 방금 만든 되돌림 커밋을 다시 git revert 하는 것입니다.

출처를 남기며 가져오기

릴리스의 핫픽스 커밋을 -xmain 에 가져옵니다.

hotfix.txt 를 더한 릴리스 커밋의 해시는 git rev-list release -- hotfix.txt 로 찾습니다. git cherry-pick -x <해시> 를 하면 새 커밋 메시지 끝에 한 줄이 붙습니다. git log -1 --format=%B 로 확인하세요.

충돌하면 물러섰다 다시 온다

릴리스의 설정 변경 커밋을 가져오다 충돌하면 --abort 로 물러섰다가, 다시 해서 --continue 로 마칩니다. 과정을 notes/conflict.txt 에 남깁니다.

conf.txt 를 고친 릴리스 커밋을 git cherry-pick 하면 충돌합니다. 먼저 git status --shortUU 를 보고 git cherry-pick --abort 로 깨끗이 물러서 보세요. 그다음 다시 가져와서 conf.txt 를 릴리스가 정한 값으로 손봐 git add 하고, GIT_EDITOR=true git cherry-pick --continue 로 마칩니다. 충돌 표시 줄이 파일에 남지 않았는지 꼭 확인하세요.

무엇이 이미 들어갔는지 세어 보기

git cherry -v main release 결과를 notes/cherry.txt 에 남깁니다.

git cherry -v <upstream> <head>head 의 커밋 하나하나가 upstream 에 이미 있는지를 patch-id 로 판정합니다. - 는 있다, + 는 없다입니다. 세 커밋 중 하나만 - 로 나오는데, 충돌을 해결해 가져온 것이 왜 + 인지를 반드시 적으세요. 이 도구의 한계가 거기 있습니다.

해시는 다른데 patch-id 는 같다

원본과 가져온 커밋의 patch-id 를 notes/patchid.txt 에 나란히 적습니다.

git show <커밋> | git patch-id --stable 은 두 값을 냅니다 — 앞이 patch-id, 뒤가 커밋 해시입니다. 4단계에서 -x 로 가져온 커밋은 원본과 patch-id 가 같습니다. 그 커밋은 git log --grep 'cherry picked from commit <해시>' 로 찾을 수 있습니다.

언제 무엇을 쓰는가

notes/report.md 에 언제 무엇을 쓰는지 정리합니다.

reset 과 revert 를 가르는 질문, 병합 커밋을 되돌릴 때의 -m, 되살릴 때 merge 가 아니라 revert 의 revert 를 쓰는 이유, -x 를 규칙으로 두는 이유, 그리고 patch-id 판정의 한계까지 다섯 덩어리로 쓰세요.