Close

Git 병합 충돌

버전 제어 시스템은 여러 배포된 작성자(일반적으로 개발자) 간의 기여를 관리하는 것입니다. 여러 개발자가 동일한 콘텐츠를 편집하려고 하는 경우가 있습니다. 개발자 B가 편집 중인 코드를 개발자 A도 편집하려고 하면 충돌이 발생할 수 있습니다. 충돌 발생을 완화하기 위해 개발자는 별도의 격리된 브랜치에서 작업합니다. git merge 명령의 주된 역할은 별도의 브랜치를 결합하고 충돌하는 편집을 해결하는 것입니다.


병합 충돌 이해


충돌은 일반적으로 두 개발자가 한 파일에서 같은 줄을 변경하거나 한 개발자가 파일을 수정하는 동안 다른 개발자가 파일을 삭제할 때 발생합니다. 이 경우 Git은 무엇이 올바른 동작인지 자동으로 판별할 수 없습니다. 충돌은 병합을 수행하는 개발자에게만 영향을 미치며 나머지 팀원은 충돌을 인식하지 못합니다. Git은 파일을 충돌한다고 표시하고 병합 프로세스를 중단합니다. 그런 다음 충돌을 해결하는 것은 개발자의 역할입니다.

병합 충돌 유형


병합은 두 개의 별도의 지점에서 충돌하는 상태가 될 수 있습니다. 병합 프로세스를 시작할 때 및 병합 프로세스 도중입니다. 다음은 각 충돌 시나리오를 해결하는 방법을 설명합니다.

Git에서 병합을 시작하지 못함

Git이 현재 프로젝트의 작업 디렉터리 또는 스테이징 영역에 변경 사항이 있는 것을 발견하면 병합은 시작되지 않습니다. 병합 중인 커밋이 보류 중인 변경 사항을 덮어쓸 수 있기 때문에 Git은 병합을 시작하지 못합니다. 이 경우는 다른 개발자와의 충돌이 아니라 보류 중인 로컬 변경 사항과의 충돌 때문에 발생합니다. git stash, git checkout, git commit 또는 git reset을 사용하여 로컬 상태를 안정화해야 합니다. 시작 시 병합이 실패하면 다음과 같은 오류 메시지가 출력됩니다.

error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)

병합 중 Git 실패

병합 중 실패는 현재 로컬 브랜치와 병합되는 브랜치 간의 충돌을 나타냅니다. 이것은 다른 개발자 코드와 충돌을 나타냅니다. Git은 파일을 병합하려고 최선을 다하지만 사용자가 충돌하는 파일에서 수동으로 해결할 수 있도록 여지를 남겨둡니다. 병합 중에 실패하면 다음과 같은 오류 메시지가 출력됩니다.

콘솔 창
관련 자료

고급 Git 로그

Bitbucket 로고
솔루션 보기

Bitbucket Cloud에서 Git에 대해 알아보기

error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes in staging area)

병합 충돌 만들기


병합 충돌에 익숙해지기 위해 다음 섹션에서는 충돌을 시뮬레이션하여 나중에 검사하고 해결할 것입니다. 이 예제에서는 UNIX와 유사한 명령줄 Git 인터페이스를 사용하여 예제 시뮬레이션을 실행합니다.

$ mkdir git-merge-test
$ cd git-merge-test
$ git init .
$ echo "this is some content to mess with" > merge.txt
$ git add merge.txt
$ git commit -am"we are commiting the inital content"
[main (root-commit) d48e74c] we are commiting the inital content
1 file changed, 1 insertion(+)
create mode 100644 merge.txt

이 코드 예제에서는 다음을 수행하는 일련의 명령을 실행합니다.

  • git-merge-test라는 새 디렉터리를 만들고 해당 디렉터리로 변경하여 새 Git 리포지토리로 초기화합니다.
  • 일부 콘텐츠가 포함된 새 텍스트 파일 merge.txt를 만듭니다.
  • 리포지토리에 merge.txt를 추가하고 커밋합니다.

이제 하나의 브랜치 main 및 콘텐츠가 포함된 merge.txt 파일이 있는 새 리포지토리가 있습니다. 다음으로 충돌하는 병합으로 사용할 새 브랜치를 만듭니다.

$ git checkout -b new_branch_to_merge_later
$ echo "totally different content to merge later" > merge.txt
$ git commit -am"edited the content of merge.txt to cause a conflict"
[new_branch_to_merge_later 6282319] edited the content of merge.txt to cause a conflict
1 file changed, 1 insertion(+), 1 deletion(-)

계속 진행되는 명령 시퀀스는 다음을 수행합니다.

  • new_branch_to_merge_later라는 이름의 새 브랜치를 만들고 체크아웃
  • merge.txt의 콘텐츠 덮어쓰기
  • 새 콘텐츠 커밋

이 새 브랜치 new_branch_to_merge_later를 사용하여 merge.txt 콘텐츠를 재정의하는 커밋을 만들었습니다.

git checkout main
Switched to branch 'main'
echo "content to append" >> merge.txt
git commit -am"appended content to merge.txt"
[main 24fbe3c] appended content to merge.tx
1 file changed, 1 insertion(+)

이 명령 체인은 main 브랜치를 체크아웃하고 merge.txt 파일에 콘텐츠를 추가한 다음 커밋합니다. 이제 예제 리포지토리는 두 개의 새 커밋이 있는 상태가 됩니다. 하나는 main 브랜치에, 다른 하나는 new_branch_to_merge_later 브랜치에 있습니다. 이때 git merge new_branch_to_merge_later에 어떤 일이 일어나는지 살펴보겠습니다.

$ git merge new_branch_to_merge_later
Auto-merging merge.txt
CONFLICT (content): Merge conflict in merge.txt
Automatic merge failed; fix conflicts and then commit the result.

쿵 💥. 충돌이 발생합니다. Git 덕분에 이 상황을 알 수 있었습니다.

병합 충돌을 식별하는 방법


앞의 예시에서 봤듯이 Git은 충돌이 발생했음을 알려주는 몇 가지 설명적인 출력을 생성합니다. git status 명령을 실행하여 더 많은 인사이트를 얻을 수 있습니다

$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)

Unmerged paths:
(use "git add <file>..." to mark resolution)

both modified:   merge.txt

git status 출력은 충돌로 인해 병합되지 않은 경로가 있음을 나타냅니다. 이제 merge.text 파일이 수정된 상태로 나타납니다. 파일을 확인하며 수정된 내용을 살펴보겠습니다.

$ cat merge.txt
<<<<<<< HEAD
this is some content to mess with
content to append
=======
totally different content to merge later
>>>>>>> new_branch_to_merge_later

여기서 cat 명령을 사용하여 merge.txt 파일의 콘텐츠를 출력했습니다. 새로운 추가 사항 몇 가지를 볼 수 있습니다

  • <<<<<<< HEAD
  • =======
  • >>>>>>> new_branch_to_merge_later

이 새로운 라인을 "충돌 구분선"이라고 하겠습니다. ======= 선은 충돌의 "중심"입니다. 센터 및 <<<<<<< HEAD 선 사이의 모든 콘텐츠는 HEAD ref가 가리키는 현재 브랜치 메인에 존재하는 콘텐츠입니다. 또는 센터 및 >>>>>>> new_branch_to_merge_later 사이의 모든 콘텐츠는 병합 브랜치에 존재하는 콘텐츠입니다.

명령줄을 사용하여 병합 충돌을 해결하는 방법


병합 충돌을 해결하는 가장 직접적인 방법은 충돌한 파일을 편집하는 것입니다. 즐겨 사용하는 편집기에서 merge.txt 파일을 엽니다. 이 예제에서는 모든 충돌 구분선을 간단히 제거하겠습니다. 수정한 merge.txt 콘텐츠는 다음과 같이 표시됩니다.

this is some content to mess with
content to append
totally different content to merge later

파일을 편집했으면 git add merge.txt를 사용하여 병합된 새 콘텐츠를 스테이지합니다. 병합을 완료하려면 다음을 실행하여 새 커밋을 만듭니다.

git commit -m "merged and resolved the conflict in merge.txt"

Git은 충돌이 해결되었음을 표시하고 병합을 마무리할 수 있도록 새 병합 커밋을 만듭니다.

병합 충돌을 해결할 수 있는 Git 명령


일반 도구

git status

status 명령은 Git으로 작업할 때 자주 사용되며, 병합하는 동안 충돌하는 파일을 식별할 수 있습니다.

git log --merge

--merge 인수를 git log 명령에 전달하면 병합 브랜치 간에 충돌하는 커밋 목록이 포함된 로그가 생성됩니다.

git diff

diff를 통해 리포지토리/파일의 상태 간 차이점을 찾을 수 있습니다. 이렇게 하면 병합 충돌을 예측하고 방지하는 데 유용합니다.

Git이 병합을 시작하지 못하는 경우를 위한 도구

git checkout

checkout은 파일 변경 사항을 실행 취소하거나 브랜치를 변경하는 데 사용할 수 있습니다

git reset --mixed

reset은 작업 디렉터리 및 스테이징 영역에 대한 변경 사항을 실행 취소하는 데 사용할 수 있습니다.

병합하는 동안 Git 충돌이 발생하는 경우를 위한 도구

git merge --abort

--abort 옵션을 사용하여 git merge를 실행하면 병합 프로세스가 종료되고 브랜치가 병합이 시작되기 전의 상태로 돌아갑니다.

git reset

병합이 충돌하는 동안 Git reset을 사용하여 충돌하는 파일을 정상 상태로 다시 설정할 수 있습니다

요약


병합 충돌은 힘든 경험이 될 수 있지만, 다행히 Git은 충돌을 탐색하고 해결하도록 지원하는 강력한 도구를 제공합니다. Git은 자동 병합 기능을 통해 대부분의 병합을 자체적으로 처리할 수 있습니다. 두 개의 개별 브랜치가 한 파일에서 같은 줄을 편집했거나 한 브랜치에서는 파일이 삭제되었지만 다른 브랜치에서는 편집된 경우 충돌이 발생합니다. 팀 환경에서 작업하는 경우 충돌이 발생할 가능성이 큽니다.

병합 충돌을 해결하는 데 도움이 되는 도구는 많습니다. Git에는 여기서 논의한 많은 명령줄 도구가 있습니다. 이 도구에 대한 자세한 내용은 git log, git reset, git status, git checkout 및 git reset에 관한 별도의 페이지를 참조하세요. Git 외에도 많은 타사 도구가 간소화된 병합 충돌 지원 기능을 제공합니다.


이 문서 공유
다음 토픽

여러분께 도움을 드릴 자료를 추천합니다.

이러한 리소스에 책갈피를 지정하여 DevOps 팀의 유형에 대해 알아보거나 Atlassian에서 DevOps에 대한 지속적인 업데이트를 확인하세요.

도구로 가득한 벽을 사용하여 협업하는 사람들

Bitbucket 블로그

DevOps 일러스트레이션

DevOps 학습 경로

Atlassian 전문가와 함께 하는 Demo Den 기능 데모

Bitbucket Cloud가 Atlassian Open DevOps와 작동하는 방법

DevOps 뉴스레터 신청

Thank you for signing up