Community코딩 & 개발github.com

roselletabuena/git-conflict-resolution

Git 병합, 리베이스, 체리픽, 리버트 또는 스태시 팝 충돌을 올바르게 해결합니다. 각 측의 의도를 파악하고, 하나를 선택하기보다 결합한 후 빌드를 확인하고 작업을 계속합니다.

git-conflict-resolution란 무엇인가요?

이 스킬은 Git 충돌을 안전하고 정확하게 해결하기 위한 전문 가이드입니다. 충돌 마커(`<<<<<<<`)가 나타나거나 "CONFLICT (content)", "both modified", "deleted by us/them" 메시지를 볼 때, 또는 사용자가 "fix the conflicts", "finish the rebase", "resolve and continue"라고 요청할 때 자동으로 활성화됩니다. `--ours`, `--theirs`, `-X ours`, `-X theirs` 플래그를 사용하기 전에도 실행해야 하는데, 리베이스 중에는 이 플래그들의 의미가 병합과 반대이기 때문입니다. 이 스킬은 충돌을 단순히 한쪽을 선택하여 해결하는 것이 아니라, 양쪽의 의도를 이해하고 결합하여 올바른 결과를 만드는 데 중점을 둡니다. 작업 중인 Git 작업(병합, 리베이스, 체리픽 등)을 정확히 식별하고, 충돌의 전체 맥락을 파악하며, 양쪽 변경 사항을 결합한 후 빌드 및 테스트를 통해 검증합니다. Claude Code, Cursor, Codex와 같은 AI 에이전트 플랫폼에서 실행 가능하며, 사용자 대신 충돌 해결 프로세스를 안내하거나 자동화할 수 있습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/roselletabuena/skills/tree/HEAD/plugins/git-workflows/skills/git-conflict-resolution

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

충돌 해결하기

충돌은 Git이 같은 위치에 두 가지 변경 사항을 발견했고 어느 것을 선택해야 할지 판단을 거부한다는 의미입니다. 해결은 의도에 대한 결정이며, 안전한 기본값은 양쪽의 의도를 모두 유지하는 것입니다. 한쪽을 삭제하여 해결하면 마커는 사라지지만 문제는 더 악화됩니다. 빌드는 여전히 통과하지만 동료의 변경 사항은 사라집니다.

1. 현재 작업 중인 작업 파악하기 - ours와 theirs는 이에 따라 달라집니다

git status                  # "rebase in progress" / "You have unmerged paths" / "cherry-pick in progress"
작업--ours / HEAD 측--theirs 측
merge현재 브랜치병합되는 브랜치
rebase리베이스 대상 브랜치(업스트림)재생 중인 자신의 커밋
cherry-pick, revert, stash pop현재 브랜치적용되는 커밋

리베이스 행이 함정입니다. git rebase main 중에 "ours"는 main이고 "theirs"는 사용자 자신의 작업입니다. 이는 병합과 반대입니다. 리베이스 중 git checkout --theirs file은 자신의 변경 사항을 유지하고 업스트림의 변경 사항을 폐기합니다. 이 플래그를 사용하기 전에 위 표를 다시 읽으십시오.

2. 마커뿐만 아니라 전체 충돌 보기

git diff --name-only --diff-filter=U        # 병합되지 않은 파일
git status                                   # 유형: both modified / deleted by us / both added
git config merge.conflictStyle zdiff3        # 공통 조상도 표시 (git 2.35+; 이전 버전에서는 diff3 사용)
git checkout --conflict=zdiff3 -- <file>     # 기본 조상이 표시된 하나의 파일 다시 렌더링 (이미 파일에 적용된 편집은 폐기)

기본 조상이 표시되면 마커에는 세 부분이 있습니다. 내 쪽, 원본, 상대방 쪽. 대부분의 명백한 충돌은 각 측이 무엇에서 변경되었는지를 볼 수 있을 때 명확해집니다.

각 측이 변경된 이유를 이해하려면:

git log --merge -p -- <file>                 # 파일을 변경한 양쪽의 커밋 (병합 또는 리베이스 진행 중)
git show REBASE_HEAD                          # 리베이스 중: 재생 중인 커밋
git show :1:<file>  :2:<file>  :3:<file>     # base, "ours", "theirs" 전체 파일

커밋 메시지를 읽으십시오. 측별로 한 문장으로 설명할 수 없는 해결은 추측입니다.

3. 결합하여 해결하기

  • 양쪽이 서로 다른 이유로 같은 라인을 편집한 경우 - 두 작업을 모두 수행하는 버전을 작성하십시오. 예를 들어, 한쪽은 tax_rate 매개변수를 추가하고 다른 쪽은 discount 매개변수를 추가한 경우: 해결된 함수는 둘 다 받아서 둘 다 적용합니다.
  • 한쪽이 이동하거나 이름을 바꾸고 다른 쪽이 편집한 경우 - 새 위치에 편집 내용을 적용하십시오. 이전 파일과 새 파일을 모두 유지하지 마십시오.
  • 한쪽이 삭제하고 다른 쪽이 수정한 경우 - 이는 기계적인 결정이 아니라 실제 결정입니다. 삭제된 이유를 찾으십시오. 수정 사항이 여전히 중요하다면 이를 이월해야 하고, 그렇지 않으면 삭제가 승리합니다. 불분명하면 사용자에게 물어보십시오.
  • 생성된 파일 및 잠금 파일(package-lock.json, poetry.lock, go.sum, 스냅샷, 컴파일된 출력) - 수동 병합하지 마십시오. 한쪽을 선택한 다음 도구를 사용하여 다시 생성하십시오(npm install, poetry lock, go mod tidy, 스냅샷 명령).
  • 바이너리 파일 - 병합이 불가능합니다. 의도적으로 한쪽을 선택하고(위 표를 염두에 두고) 그렇게 말하십시오.

텍스트는 깔끔하게 병합될 수 있지만 여전히 잘못될 수 있습니다. 한쪽이 함수 이름을 바꾸고 다른 쪽이 이전 이름에 대한 호출을 추가한 경우, Git은 충돌을 감지하지 못합니다. 이것이 4단계에 빌드가 포함된 이유입니다.

일괄 플래그는 결정을 숨깁니다. git checkout --ours ., -X ours / -X theirs(충돌하는 각 청크를 한쪽으로 해결) 및 -s ours(다른 브랜치를 완전히 폐기)는 각각 살펴보지 않고 작업을 버립니다. 사용자가 정확히 그렇게 요청했고 무엇이 삭제되는지 알고 있는 경우에만 사용하십시오.

4. 확인한 다음 계속 진행하기

git diff --check                              # 남은 충돌 마커 및 공백 오류 확인
grep -rnE '^(<<<<<<<|=======|>>>>>>>)' .      # 안전장치, git diff-check가 확인하지 않는 파일에서
# 가장 빠른 관련 테스트 빌드 및 실행
git add <해결된-파일들>

일치하는 명령으로 계속 진행하십시오. 편집기가 열릴 수 있는 곳에 GIT_EDITOR=true를 추가하십시오. 편집기는 비대화형 셸에서 중단되기 때문입니다:

git merge --continue            # 또는: git commit --no-edit
GIT_EDITOR=true git rebase --continue
GIT_EDITOR=true git cherry-pick --continue

리베이스는 커밋을 하나씩 재생하므로 다음 커밋에서 다시 중지될 수 있습니다. 루프를 반복하십시오. 충돌이 나타나는 가장 이른 커밋에서 해결하십시오. 이후 커밋은 동일한 충돌이 재생되는 것일 수 있습니다.

해결 후 테스트가 실패하면 실패는 해결에 대한 정보입니다. 실패를 무시하고 넘어가지 말고, 테스트가 보호하는 동작이 어느 쪽인지 알 때까지 테스트를 편집하여 "수정"하지 마십시오.

5. 중단하고 물어봐야 할 때

다음과 같은 경우 추측하지 말고 중단하십시오:

  • 양쪽이 비즈니스 로직을 호환되지 않는 방식으로 변경한 경우(서로 다른 두 가지 세금 규칙, 서로 다른 두 가지 재시도 정책);
  • 각 측이 변경한 이유를 한 문장으로 말할 수 없는 경우;
  • 해결로 인해 테스트가 실패하고 원인이 명확하지 않은 경우.

두 의도를 진술하고, 무엇을 선택할지와 그 이유를 말한 다음 사용자가 결정하도록 하십시오. --continue 이전의 모든 것은 되돌릴 수 있습니다: git merge --abort, git rebase --abort, git cherry-pick --abort는 트리를 시작 상태로 되돌립니다.

반복되는 충돌

동일한 충돌이 반복되는 긴 리베이스 또는 반복적으로 병합되고 포기된 브랜치의 경우:

git config rerere.enabled true      # 각 해결을 기록하고 다음 번에 재생합니다
git rerere diff                      # 기록된 내용 표시
git rerere forget-path <file>        # 잘못된 기록된 해결을 폐기합니다

rerere는 묻지 않고 해결을 재적용하므로 잘못된 해결이 전파됩니다. rerere가 해결한 충돌 후에도 여전히 결과를 확인하십시오.

브랜치가 오래되었고 많이 뒤쳐진 경우, 트렁크를 한 번 병합하면 일반적으로 한 번의 충돌 라운드로 끝나고; 리베이스는 커밋별로 충돌을 재생합니다. 그 선택은 사용자의 몫입니다.

안전장치

  • 충돌을 없애기 위해 한쪽을 통째로 선택하여 해결하지 마십시오. 다른 쪽은 누군가의 작업입니다.
  • 지루하다는 이유로 사용자가 완료하도록 요청한 리베이스를 중단하지 마십시오. 잘못된 경우에만 중단하고 그렇게 말하십시오.
  • 요청하지 않으면 해결 후 푸시하지 마십시오. 리베이스는 강제 푸시가 필요합니다. git-safe-history-rewrite를 따르십시오.
  • 각 충돌 파일을 보고하십시오: 양쪽이 무엇을 했는지, 무엇을 유지했는지, 확인할 수 없는 모든 것.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

관련 스킬