Git 병합 충돌 해결 튜토리얼

Git 병합 충돌이 무엇인가?

Git 버전 관리 시스템은 팀 협업과 프로젝트에 기여하는 것입니다. 개발자들은 일반적으로 격리된 브랜치에서 작업하며, 작업을 완료하면 메인 브랜치로 변경 사항을 병합합니다. 이러한 형태의 팀워크는 버그를 발견하는 데 매우 생산적이고 효율적입니다. 때때로 여러 개발자가 같은 코드 줄을 작업하며, 변경 사항을 병합하려고 할 때 충돌이 발생합니다. 


Git 충돌의 간단한 예

上图이 일반적인 Git 합치기 충돌의 완전한 예제를 보여줍니다. 주 대 branches에는 “HELLO, WORLD!” 텍스트를 포함하는 파일이 있습니다. 사용자 이름 abid이 주 대 branch를 분叉하고 “HELLO, CAT!”로 텍스트를 변경합니다. abid이 변경을 마치는 동안, 원래의 주 대 branch도 “HELLO, DOG!”로 변경되고 있습니다. 이 branches를 합치는 것은 합치기 충돌 문제를 일으키고 프로세스를 일시 중지하게 됩니다.

git merge 명령어의 주요 일은 두 branches를 combine하고 자동으로 충돌을 resolve하는 것입니다. 그러나 때때로 두 사람이 同一 line of code를 변경하거나 또는 다른 開発자가 작업하는 중인 중요한 파일을 제거하는 충돌이 발생합니다. Git이 이러한 변경을 표시하고 merging process를 중지합니다. 이 경우 충돌은 자동으로 해결되지 않고; 대신 개발자가 수동으로 변경하거나 도구를 사용하여 충돌을 해결해야 합니다.

Merge Types

Git merge와 rebase가 두 가지 방법으로 대상 branch의 커밋을 소스 branch로 통합할 수 있습니다. 그리고 Git merge는 fast-forward 또는 no-fast-forward merge를 수행합니다. Target branch의 head가 Source branch에 존재하면, 기본적으로 merge type가 fast-forward merge가 되고, 없다면 no-fast-forward merge가 됩니다. Git rebase는 다른 종류의 merge로 target branch의 commit history를 다시 sequence하는 것입니다.

Fast-forward Merge

Git 병합은 기본적으로 fast-forward를 사용하여 목표 분기에 누락된 커밋을 통합합니다. 예를 들어, pull 명령을 사용하여 원격 서버에서 로컬 분기를 업데이트하는 데 사용됩니다. Fast-forward는Git이 소스 분기에 목표 분기의 헤드가 없을 때는 적용하지 않기 때문에 병합 충돌 문제를 발생시키지 않습니다. 

노-패스트-포워드 병합

노-패스트-포워드 병합은 세 가지 방식이나 진정한 병합이라고도 합니다. 이는 소스 분기와 목표 분기의 변경 사항을 통합하여 목표 분기에 새 커밋을 생성합니다. 변경 사항은 두 분기의 마지막 공통 커밋 이후에 섞입니다. 우리의 경우에는 C 다음입니다. 이러한 종류의 병합은 소스 분기와 목표 분기가 충돌할 때 Git 병합 충돌을 발생시킵니다. 위의 도표에서 병합 커밋(X)은 소스와 목표 분기를 통합하여 생성되는데, K와 E는 병합 커밋의 부모입니다. 

리베이스 

Git 리베이스는 다른 유형과는 조금 다릅니다. 이는 목표 분기 커밋 히스토리의 순서를 변경합니다. 리베이스는 소스 분기를 목표 분기가 마지막 공통 커밋 이후의 모든 변경 사항을 포함하도록 통합합니다. 우리의 경우, 마지막 공통 커밋은 C이며, D와 E는 소스 분기의 것입니다. K* 커밋은 K와 다른 커밋 ID를 가진 K와 같습니다. C를 링크하는 대신 E를 링크합니다. 노-패스트-포워드 병합과 마찬가지로, 소스와 목표 분기에 호환性问题가 있으면 Git은 리베이스를 완료하기 전에 충돌을 해결하라는 문제를 발생시킵니다. 

Git 병합 충돌 유형

두 种의 Git 합并 충돌이 存在한다: 합并 시작과 합并 과정 동안이다 – Atlassian이며, 이 부분에서는 모두의 유형을 배울 것이며, 각 상황을 해결하는 방법을 배울 것입니다.

합并 시작에 대해서

Git 합并이 작업 디렉터리 또는 스테이지 영역에 변경이 있으면 시작할 때에 실패할 수 있다. 이러한 변경은 entrant merge commit로부터 덮어 씌워지는 것을 방지하기 위해 시작时에 실패한다. 이는 로컬 변경과의 충돌, 다른 분기나 開発자와의 충돌이 아니라고 나타낸다. 로컬 상태를 안정화하기 위해 git stash, git commit, git checkout, 또는 git reset와 같은 명령어를 사용할 수 있다.

합并 과정 동안에 대해서

합并 과정 동안 실패는 ällor 브랜치와 대상 브랜치가 같은 파일을 다른 開発자들이 수정했을 때 충돌이 있음을 의미한다. 자동 합并没有할 때 실패하면 Git은 수동으로 문제를 해결하라고 요구할 수 있으며, teritary-party tools를 사용하여 변경을 시각화하고 통합할 수 있다.

Git 합并 충돌 해결 명령어

이 부분에서는 Git 합并 충돌을 시각화하고 해결하기 위한 다양한 ネイティブ 명령어를 배울 것입니다.

일반 명령어

Git status는 가장 자주 사용되는 명령어로 수정된 파일, 스테이지 영역, 및 커밋의 상태를 보여준다. 합并 과정 동안, 충돌 발생한 파일을 식별하기 위해 사용된다.

git status

Git 로그에서 –merge 인자로 생성되는 커밋 목록은 소스 분기와 충돌하는 커밋들을 나타냅니다.

git log --merge

기본적으로 git diff 옵션은 미커밋 변경과 이전 커밋 사이의 차이를 보여줍니다. Git diff는 분기, 커밋, 파일을 比较하는 것에 사용되며, 미래의 합성 충돌을 예방하는 것에 유용합니다.

git diff

시작시 합성 실패의 명령어

Checkout은 변경을 취소하거나 새로운 oder 老旧한 분기로 전환하는 것을 사용합니다.

git checkout

Git reset은 작업 디렉터리와 스테이지 영역의 변경을 되돌릴 때 사용합니다.

git reset --mixed

합성 동안 충돌에 대한 명령어

–abort 인자는 합성 프로세스를 중지하고 합성이 시작되기 전의 상태로 변경을 되돌립니다.

git merge --abort

Git reset은 일반적으로 합성 과정에서 충돌 발생한 파일을 원래 상태로 되돌릴 때 사용합니다.

git reset

삭제된-수정한 파일 충돌 해결

Git 충돌이 생성되는 조건은 현재 분기에서 파일을 지웠고, 다른 분기에서 누군가가 그 파일을 수정했을 때입니다. 이 경우, 파일을 추가하고 커밋하거나,

git add <filename>

또는 파일을 제거하고 커밋할 수 있습니다.

git rm <filename>

비주얼 합성 도구

병합 도구는 모든 종류의 병합 충돌을 식별하고 해결하기 위한 사용자 친화적인 시각 도구입니다. 일부 도구는 변경 사항 비교, Git 연산, 프로젝트 및 저장소 관리와 같은 추가 기능을 지원합니다. Git 병합 도구는 두 가지 유형이 있습니다: 터미널 전용과 GUI 기반입니다. 터미널 기반 도구는 PowerShell이나 Bash 내에서 실행되고, GUI 기반 도구는 창환경에서 실행됩니다.

설치되어 있는 유효한 도구 목록을 확인하려면 다음을 사용하세요:

git mergetool --tool-help

목록에는 git 명령과 함께 설치하고 통합할 수 있는 모든 유효한 도구가 포함되어 있습니다.

예를 들어, vim과 nvim이 기본적으로 설치되어 있으며, 어떤 未提交된 파일과 이전 커밋의 차이를 보고 싶다면 다음을 입력하세요:

git difftool --tool=vimdiff3

vimdiff3 도구는 변경 사항을 강조하고 터미널 내에서 커밋을 비교할 수 있습니다.

vimdiff3에서 같은 파일의 두 버전의 차이

Meld

Meld는 병합 충돌 해결을 새로운 수준으로 이동시키는 무료 및 오픈 소스 도구입니다. Git와 통합하려면 먼저 공식 사이트에서 다운로드하고 설치를 해야 합니다. 그 다음, 전역 구성에 추가하여 Git이 충돌 해결을 위해 기본적으로 Meld를 실행하게 합니다.

아래의 구성 명령은 Windows 사용자에게만 적용됩니다. 변경해야 하는 것은 Mac이나 Linux에 설치된 Meld 파일 경로를 변경하는 것뿐입니다.

git config --global merge.tool meld git config --global mergetool.meld.path "C:/Program Files (x86)/Meld/Meld.exe" git config --global diff.tool meld git config --global difftool.meld.path "C:/Program Files (x86)/Meld/Meld.exe"

앞 설정을 마친 후, Git 로컬 디렉토리 내에서 git difftool를 입력하여 Windows 버전의 Meld를 실행할 수 있으며, 아래처럼 git mergetool를 사용하여 병합 충돌을 해결할 수 있습니다.

Meld로 병합 충돌 해결

VSCode

VSCode는 병합 충돌을 해결하는 가장 좋고 인기 있는 방법을 제공합니다. Git이 파일을 자동으로 병합하지 못할 때, VSCode는 충돌된 코드를 강조하고 다음 네 가지 옵션을 제공합니다: 현재 변경 사항을 받아들이기, 들어오는 변경 사항을 받아들이기, 둘 다의 변경 사항을 받아들이기, 변경 사항 비교. 이러한 옵션을 사용하여 파일을 정리하고 모든 보류 중인 문제를 해결할 수 있습니다. 

VSCode로 병합 충돌 해결

Git 작업에 대한 완전한 솔루션을 찾고 있다면, GitKraken을 시도해 보세요. 무료 클라이언트, VSCode 확장 기능과 병합 충돌 해결을 위한 내장 도구를 제공합니다.  

Git 병합 충돌 해결 방법

이 섹션에서는 Git 병합 충돌을 생성하고 해결하는 방법을 배울 것입니다. 이 튜토리얼은 두 부분으로 나뉩니다. 첫 번째 부분에서는 로컬에서 Git 충돌을 해결하는 방법을 배우고, 두 번째 부분에서는 원격 서버(GitHub)와의 충돌을 해결하는 방법에 대해 다룹니다.

로컬 병합 충돌

병합 충돌을 생성하는 것은 이러한 문제가 처음에 어떻게 발생하는지 배우는 데 도움이 됩니다. 그런 다음 창의적인 방법으로 이러한 문제를 해결하거나 향후 발생을 방지할 수 있습니다.

이제 Git 저장소를 생성하고 단일 파일과 첫 번째 커밋을 만들어 시작해 보겠습니다.

  1. datacamp이라는 폴더를 만듭니다.
  2. 디렉토리를 datacamp으로 변경합니다.
  3. Git을 초기화합니다.
  4. 주어진 제목으로 README.md 파일을 만듭니다.
  5. 파일의 변경 사항을 스테이징하고 커밋합니다.
mkdir datacamp cd datacamp git init echo "# How to Resolve Git Merge Conflict" > README.md git add README.md git commit -m "first commit" >>> [main (root-commit) 8199ea2] first commit >>> 1 file changed, 1 insertion(+) >>> create mode 100644 README.md

다음으로, readme라는 새로운 브랜치를 만들고 제목을 “..Git Merge..”에서 “..Git..”으로 변경합니다. 파일을 추가하고 -am 인수를 사용하여 커밋을 만듭니다.

git checkout -b readme echo "# How to Resolve Git Conflict" > README.md git commit -am "new branch conflict added" >>> [readme 155f694] new branch conflict added >>> 1 file changed, 1 insertion(+), 1 deletion(-)

메인 브랜치로 돌아가서 >>를 사용하여 README.md 파일에 새로운 줄을 추가합니다. 변경 사항을 저장하고 커밋을 생성함으로써 동일한 파일의 두 버전 간에 충돌을 성공적으로 형성했습니다.

git checkout main echo "New change in base branch" >> README.md git commit -am " a line added to base branch Readme file" >>> [main f1f1874] a line added to base branch Readme file >>> 1 file changed, 1 insertion(+)

보시다시피, readme 브랜치를 병합할 때 Git은 자동 병합이 실패했으며 수동으로 변경을 하고 결과를 커밋해야 한다는 메시지를 표시했습니다.

git merge readme >>> Auto-merging README.md >>> CONFLICT (content): Merge conflict in README.md >>> Automatic merge failed; fix conflicts and then commit the result.

문제를 수동으로 해결하려면 Notepad에서 파일을 열고 편집하면 됩니다. 아래 이미지에서 HEAD로 표시된 화살표와 분할선, readme로 표시된 다른 방향의 화살표를 볼 수 있습니다. HEAD 부분은 주 브랜치에 있는 기존 변경 사항을 보여주고, readme 부분은 병합하고자 하는 브랜치입니다. 이는 다른 제목을 가지고 있습니다.

수동으로 병합 충돌 해결

문제를 해결하려면, readme 브랜치 부분, 화살표, 분할선을 제거하면 됩니다. 파일의 최종 버전은 아래와 같이 깨끗해져야 합니다.

충돌 해결됨

파일을 추가하고 커밋을 생성하면 병합 충돌이 해결됩니다. 이는 문제를 해결하는 가장 일반적인 그리고 가장 간단한 방법입니다. 또한 통합 개발 환경(IDE)를 사용하여 더 빨리 문제를 해결할 수도 있습니다.

git commit -am "conflict resolved in file README.md" >>> [main 9994a29] conflict resolved in file README.md

원격 병합 충돌

원격 병합 충돌을 생성하고 해결하려면 GitHub에 저장소를 만들어야 합니다.

GitHub에 새 저장소 생성

다음으로, 원격 이름(원본)을 주소와 함께 저장소에 추가하고, 로컬 저장소의 모든 변경 사항을 업스트림을 사용하여 원격 메인 브랜치로 푸시합니다.

git remote add origin https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git git push --set-upstream origin main >>> Enumerating objects: 12, done. >>> Counting objects: 100% (12/12), done. >>> Delta compression using up to 4 threads >>> Compressing objects: 100% (6/6), done. >>> Writing objects: 100% (12/12), 998 bytes | 499.00 KiB/s, done. >>> Total 12 (delta 2), reused 0 (delta 0), pack-reused 0 >>> remote: Resolving deltas: 100% (2/2), done. >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> * [new branch] main -> main >>> branch 'main' set up to track 'origin/main'.

충돌을 만들려면, 원격 및 로컬 README.md 파일에 변경 사항을 추가해야 합니다. GitHub 파일 편집기를 사용하여 “..Git merge..”를 “..Sit-Merge..”로 변경한 후 변경 사항을 커밋할 수 있습니다. 

GitHub 편집기에서 변경 사항 만들기

그런 다음 로컬 저장소에서 README.md 파일을 간단한 제목만 추가하도록 변경하고 변경 사항을 커밋합니다. 

echo "# How to Resolve Merge Conflicts in Git Tutorial" > README.md git commit -am "local branch changes in README.md" >>> [main c677a13] local branch changes in README.md >>> 1 file changed, 1 insertion(+), 4 deletions(-)

마지막으로 변경 사항을 원격 서버에 푸시합니다. Git이 문제를 해결하는 방법에 대한 힌트를 제공하며 오류를 발생시킨 것을 확인하세요. 

git push >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> ! [rejected] main -> main (fetch first) >>> error: failed to push some refs to 'https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git' >>> hint: Updates were rejected because the remote contains work that you do >>> hint: not have locally. This is usually caused by another repository pushing >>> hint: to the same ref. You may want to first integrate the remote changes >>> hint: (e.g., 'git pull ...') before pushing again. >>> hint: See the 'Note about fast-forwards' in 'git push --help' for details.

가장 간단한 힌트를 따라, 푸시하기 전에 원격 서버에서 파일을 가져옵니다. 

README.md 파일의 병합 충돌로 인해 파일 가져오기가 실패했습니다. 메모장을 사용하여 수동으로 수정할 수 있지만, 이번에는 시각적 도구를 사용하여 이 과정을 도울 것입니다. 

git pull >>> remote: Enumerating objects: 5, done. >>> remote: Counting objects: 100% (5/5), done. >>> remote: Compressing objects: 100% (2/2), done. >>> remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 >>> Unpacking objects: 100% (3/3), 681 bytes | 75.00 KiB/s, done. >>> From https://github.com/kingabzpro/DataCamp-Git-Merge-Guide >>> aaf149d..49b7d14 main -> origin/main >>> Auto-merging README.md >>> CONFLICT (content): Merge conflict in README.md >>> Automatic merge failed; fix conflicts and then commit the result.

병합 도구 Meld는 충돌된 파일을 식별하고 Meld GUI 애플리케이션에 표시합니다.   

git mergetool >>> Merging: >>> README.md >>> Normal merge conflict for 'README.md': >>> {local}: modified file >>> {remote}: modified file

세 개의 열이 있습니다: README_LOCAL_473.md, README.md 및 README_LOCAL_473.md. 원격 변경 사항이 유효하다고 생각되면 원격 열의 검은색 화살표를 클릭하고, 로컬 변경 사항을 유지하고 싶다면 로컬 열의 검은색 화살표를 클릭하세요. 아주 간단합니다.

Meld 기반 merge tool을 사용하여 충돌 해결

변경 사항을 만들 다음, 파일을 저장하고 コミット합니다. 正如您所看到的, 이mote 서버로 파일을 푸시하는 것은 합성 충돌 오류를 발생시키지 않습니다.

git commit -am "remote main branch conflict resolved" git push >>> Enumerating objects: 16, done. >>> Counting objects: 100% (16/16), done. >>> Delta compression using up to 4 threads >>> Compressing objects: 100% (6/6), done. >>> Writing objects: 100% (10/10), 1.08 KiB | 550.00 KiB/s, done. >>> Total 10 (delta 2), reused 0 (delta 0), pack-reused 0 >>> remote: Resolving deltas: 100% (2/2), completed with 1 local object. >>> To https://github.com/kingabzpro/DataCamp-Git-Merge-Guide.git >>> 49b7d14..8f5c3aa main -> main

로컬과 이mote 합성 충돌을 성공적으로 해결했습니다. 이러한 충돌은 데이터 과학자와 機械 러닝 엔지니어들이 매일 처리합니다. Git 操作 기능을 改善하려면 Git introduction 과정을 들으십시오.

결론

Git 합성 충돌 해결은 错綜複雑하며, 잘못된 코드를 합성하여 ソフト웨어를 壊し得는 危険한 일입니다. Merge 도구는 합성 충돌을 감지하고 해결하는 안전한 방법을 제공하는 사용자 friedly 환경을 제공합니다. 이 튜토리얼에서는 Git 충돌이 어떻게 발생하는지 以及 어떻게 해결하는지를 배웠습니다. 또한 다양한 합성과 충돌 유형, 유용한 Git 명령어, 그리고 시각적 도구에 대해 다룹니다. 마지막 섹션에서는 로컬과 이mote 저장소에서 합성 충돌을 생성하고 해결하였습니다.

Git를 처음 보고 이 기능을 어떻게 작동하는지 배우고 싶다면 Git과 GitHub 튜토리얼 시작을 읽으십시오.

Source:
https://www.datacamp.com/tutorial/how-to-resolve-merge-conflicts-in-git-tutorial