git rebase 중 충돌이 나면 새 커밋을 임의로 만드는 것이 아니라, 현재 적용 중인 커밋의 충돌을 해결하고 rebase를 계속 진행해야 한다. 흐름은 status → 수정 → 검증 → add → rebase --continue다.
충돌은 한 번만 발생한다는 보장이 없다. rebase는 대상 커밋을 하나씩 새 기준 위에 다시 적용하므로, 여러 커밋이 같은 부분을 바꿨다면 이 과정을 반복하게 된다.
시작 전에는 작업 트리를 정리한다
rebase를 시작하기 전에 다음 두 가지를 확인한다.
git status
git log --oneline --decorate --graph -10
커밋하지 않은 수정이 남아 있으면 먼저 목적에 맞게 커밋하거나 안전하게 보관한다. rebase할 브랜치와 기준 브랜치도 다시 확인한다.
git switch feature/login
git fetch origin
git rebase origin/main
여기서는 feature/login의 커밋을 최신 origin/main 위에 다시 적용한다. rebase는 커밋의 부모 관계를 바꾸므로 새 커밋 ID가 만들어진다.
충돌이 나면 이 순서로 해결한다
1. 현재 상태와 충돌 파일 확인
git status
git diff
git status에는 현재 rebase 단계와 충돌 파일이 표시된다. 파일 안에는 보통 다음과 같은 충돌 표식이 생긴다.
<<<<<<< HEAD
기준 브랜치 쪽 내용
=======
현재 적용 중인 커밋의 내용
>>>>>>> commit-message
표식의 위쪽이나 아래쪽 중 하나를 기계적으로 고르기보다, 두 변경의 의도를 확인한 뒤 최종 코드가 되어야 할 형태로 직접 편집한다. rebase 중 표시되는 ours와 theirs는 merge 때의 직관과 다르게 느껴질 수 있으므로 이름만 보고 결정하지 않는 편이 안전하다.
2. 남은 표식과 문법 오류 확인
git diff --check
git diff
git diff --check는 남은 충돌 표식과 일부 공백 오류를 찾는 데 도움이 된다. 그다음 프로젝트에 맞는 테스트와 린트를 실행한다. 충돌 표식을 없앴다는 사실만으로 두 변경이 논리적으로 잘 합쳐졌다는 뜻은 아니다.
3. 해결한 파일을 스테이징
git add path/to/resolved-file
git status
git add는 이 파일의 충돌을 해결했다는 표시 역할을 한다. 의도하지 않은 파일까지 섞이지 않도록 git add .보다 해결한 파일을 명시하는 편이 확인하기 쉽다.
4. rebase 계속 진행
git rebase --continue
편집기가 열리면 현재 적용 중인 커밋 메시지를 확인하고 저장한다. 다시 충돌이 발생하면 status → 수정 → 검증 → add → continue를 반복한다.
일반적인 충돌 해결 흐름에서 다음처럼 별도의 커밋을 만드는 것은 피한다.
git commit -m "Resolve conflict"
rebase가 이미 어떤 커밋을 재적용하는지 관리하고 있으므로, 해결한 변경을 스테이징한 뒤 git rebase --continue로 넘기는 것이 맞다.
계속할 수 없다면 abort, 버릴 커밋이면 skip
rebase를 시작하기 전 상태로 돌아가려면 다음 명령을 사용한다.
git rebase --abort
현재 적용 중인 커밋의 변경을 의도적으로 버릴 때만 skip을 사용한다.
git rebase --skip
skip은 충돌 파일 하나를 건너뛰는 명령이 아니라 현재 커밋의 패치 전체를 제외한다. 이미 다른 커밋에서 같은 변경이 반영됐는지 확인하지 않고 쓰면 필요한 코드가 사라질 수 있다.
이미 원격에 올린 브랜치라면 더 조심한다
rebase 뒤에는 커밋 ID가 달라지므로 이미 push한 브랜치는 일반 push가 거절될 수 있다. 혼자 쓰는 작업 브랜치이고 저장소 정책이 허용할 때만 원격 최신 상태를 확인한 뒤 다음을 고려한다.
git fetch origin
git push --force-with-lease origin feature/login
--force-with-lease는 예상한 원격 참조와 현재 원격 참조가 일치하는지 확인한다. 그래도 다른 사람의 작업을 덮어쓸 위험이 완전히 사라지는 것은 아니다. 공유 브랜치에서는 먼저 팀과 조율하고, 보호 브랜치 정책을 우회하지 않는다. 확인 없이 --force를 쓰는 것은 피한다.
한눈에 보는 복구 흐름
rebase 시작
├─ 충돌 없음 → 완료
└─ 충돌 발생
├─ 해결 가능 → status → 수정 → 테스트 → add → continue
├─ 작업 취소 → rebase --abort
└─ 현재 커밋을 버림 → rebase --skip (의도가 분명할 때만)
충돌 자체보다 중요한 것은 각 커밋이 원래 해결하려던 문제를 보존하는 일이다. rebase가 끝난 뒤에는 git log --graph와 전체 테스트로 최종 이력을 다시 확인한다.
참고 자료
'배움과 성장 > DevOps·클라우드' 카테고리의 다른 글
| Docker란 무엇인가: 이미지·컨테이너·VM 차이와 격리 구조 (0) | 2023.03.25 |
|---|---|
| Docker 컨테이너 생명주기: run·start·stop·rm·commit 차이 (0) | 2023.03.25 |
| 신입 DevOps 엔지니어 학습 순서: Linux·네트워크부터 CI/CD·Cloud까지 (0) | 2023.03.15 |
| Interactive Shell과 Non-Interactive Shell: Bash 실행 모드·Startup File 구분 (0) | 2023.01.11 |
| 로그 레벨 기준: ERROR·WARN·INFO·DEBUG·TRACE에 무엇을 남길까 (0) | 2023.01.11 |
댓글