치춘짱베리굿나이스
Github, Git 기본 <Pull Request, pull, 충돌 해결> 본문
Github, Git 기본 <Pull Request, pull, 충돌 해결>
7. 내 코드 팀 레포지토리에 합치기, Pull Request
커밋이 아주 잘 올라왔다
이것을 이제 팀 레포지토리에 합쳐보자
우상단의 New pull request
를 누른다
브랜치를 원본 레포지토리의 main에 PR
만약 협업을 할 때 한 레포지토리에서 분기 (branch) 를 나누어 작업했다면,
base
에는 내 브랜치를 합치려는 팀 레포지토리 브랜치를 선택한다 (예시:main
)compare
에는 내 브랜치를 선택한다 (예시:feat/test
)
포크 레포지토리를 원본 레포지토리에 PR
만약 브랜치로 나눈 것이 아니라, Fork를 했다면 상단의 compare across forks
를 누른다
그러면 출력되는 브랜치의 종류가 살짝 달라지게 된다
base repository
에는 내 커밋을 합치려는 목적지 레포지토리를 선택한다 (예시: 내가 Fork한 원본 레포)head repository
에는 내 Fork 레포지토리를 선택한다 (깃허브 계정명으로 찾으면 된다)base
에는 목적지 레포지토리의 브랜치를 선택한다compare
에는 내 레포지토리의 브랜치를 선택한다
풀 리퀘스트 생성
브랜치를 선택하면 내 브랜치의 커밋들과, 최하단에는 변경점이 표시된다
Create pull request
를 누르자
상단에 앞서 지정한 브랜치들과, 자동 Merge 여부가 출력된다
자동으로 Merge할 수 있다면 초록색으로, 자동으로 Merge할 수 없으면 (충돌 발생) 빨간색으로 출력된다
위 이미지는 지금 충돌이 발생한 상태라 해결해주어야 한다
하단은 두 섹션으로 분리되어 있다
- 왼쪽 섹션에서는 풀 리퀘스트의 제목과 간략한 설명을 적을 수 있다
- 보통은 어떤 작업을 했고, 어느 부분이 개선되었는지 이미지와 함께 작성하는 편이다
- 꼼꼼하게 적으면 다른 사람들이 리뷰하기 쉽다
- 오른쪽 섹션은 이 풀 리퀘스트의 속성을 지정할 수 있다
Reviewers
에서는 이 풀 리퀘스트를 리뷰해줬으면 하는 사람을 지정할 수 있다 (레포지토리에 소속된 사람만 가능)Assignees
는 이 작업을 한 사람을 지정할 수 있다Labels
는 태그같은 개념으로, PR의 특성을 지정할 수 있다Projects
는 사전에 설정해놓은 칸반보드 등에 연동할 수 있는 기능이다Milestone
은 사전에 해당 레포지토리에 설정한 투두리스트 같은 것을 연동할 수 있다Development
는 이슈와 풀리퀘스트를 연결하여 풀리퀘스트가 해결되면 자동으로 닫히게 등 설정할 수 있다
다 작성했다면 Create pull request
를 누른다
풀 리퀘스트가 잘 생성이 되었다
이제 다른 사람들이 내 PR을 보고 코드의 개선안을 제시하거나 오류를 지적하는 리뷰를 올릴 수 있다
draft pull request
아직 코드가 다 완성되진 않았지만 풀 리퀘스트를 미리 올리고 싶을 때 사용한다
draft PR은 merge할 수 없다
8. 원격 레포지토리 내용 내려받기, git pull (fetch & merge)
$> git pull origin main
원격 레포지토리 (origin) 의 main으로부터 내용을 내려받아 현재 로컬 브랜치에 합친다
만약 git clone
을 통해 깃허브에서 복제한 레포지토리라면 인자를 넣지 않고 git pull
만으로도 잘 동작할 것이다 (원래는 인자를 넣어주는 것이 맞다)
하지만 git init
을 통해 로컬에서 레포지토리를 만들고 원격으로 올렸다면 이러한 설정이 잘 안 되어 있을 것이다
$> git push -u origin main
git push
할 때 -u
옵션을 통해 기본 경로를 지정해주면 앞으로 git pull
만으로도 잘 받아질 것이다
git fetch
$> git fetch origin main
원격 저장소에서 변경점을 가져오기만 하고, 합치지는 않는 명령어
원격 저장소의 변경점을 새로운 브랜치로 가져오기만 하며, 이 브랜치는 FETCH_HEAD
라는 이름으로 접근할 수 있다
원격 저장소의 변경점을 내 브랜치에 합치고 싶다면 FETCH_HEAD
를 내 브랜치에 merge
하면 된다
git merge
$> git merge [브랜치명]
현재 checkout된 브랜치 (현재 브랜치) 에 인자로 받은 브랜치를 merge한다
두 브랜치의 커밋 이력을 한 브랜치로 통합한다고 생각하면 된다
git merge
를 진행하다 보면 Fast-forward라는 문구를 볼 수 있는데, 이는 현재 브랜치 (인자로 받은 브랜치를 merge하려는 브랜치) 가 분기 이후 변경점이 없어 단순히 맨 뒤에 다른 브랜치의 커밋을 붙이기만 해도 merge
가 되는 상황을 의미한다
Fast-forward가 아닌 다른 merge를 관찰하기 위해 main
, test/testbranch
두 브랜치가 서로 다른 커밋 이력을 갖고 있도록 서로 다른 파일을 추가해 보았다
(충돌은 나지 않도록 했다)
Fast-forward 대신 ‘recursive’ 전략을 사용해서 머지했다고 나온다
두 브랜치가 분기 이후로 독자 노선을 걷고 있기 때문에 브랜치의 맨 끝에 최신 커밋을 붙이기만 한다고 해결되지 않기 때문이다
recursive strategy는 git
은 main
과 test/testbranch
의 분기 지점 (공통 조상) 을 찾아내고, 3-way merge
방식을 사용하여 두 브랜치를 합친다
3-way merge는
- merge 받으려는 브랜치 (
main
) 의 가장 최신 커밋 - merge하려는 브랜치 (
test/testbranch
)의 가장 최신 커밋 - 분기 지점 커밋
의 3개 커밋을 이용한다
분기 지점 커밋을 이용하여 main
과 test/testbranch
의 커밋 중 어느 쪽에서 파일에 변경점이 발생했는지 알아내고, 이를 이용하여 새로운 커밋 (Merge commit) 을 만들어 merge를 진행한다
8. 충돌 해결하기
충돌이 발생하면 Merge pull request 버튼이 비활성화된다
충돌을 해결하는 방법은 크게 두 가지가 있다
Github 페이지에서 바로 해결하기
conflict가 났다고 알려주는 박스의 우상단 Resolve conflicts 버튼이 활성화되어야지만 사용할 수 있다
파일의 수가 너무 많거나 변경점이 복잡하면 비활성화되기 때문에 이 방법으로 고칠 수 없다
충돌 표식을 보여준다
<<<<<
로 되어있는 칸 안의 내용이 머지하려는 브랜치의 내용이고,, >>>>>
로 표시된 칸 안에 있는 내용이 머지하고자 하는 기준 브랜치의 내용이다
유지하고자 하는 코드를 남겨두고, 지우려는 코드를 지워주자
Mark as resolved
를 누르면 해당 충돌이 해결되었음을 표시할 수 있다
모든 파일이 Mark as resolved 되면 Commit merge
버튼이 활성화된다
로컬에서 해결하고 올리기 - Fork한 레포지토리
$> git remote add upstream [원본 레포지토리 링크]
만약에 레포지토리가 fork한 레포라면 upstream
리모트를 설정해주어야 한다
$> git pull upstream [upstream으로부터 가져올 브랜치]
upstream의 내용을 현재 브랜치에 pull 받아보자
git pull
은 git fetch
와 git merge
를 한꺼번에 사용하는 명령어이다
git fetch
는 변경사항을 가져오기만 하지만, git merge
는 가져온 변경사항을 현재 브랜치에 Merge하려고 시도하기 때문에 충돌이 발생할 수 있다
위의 사진을 보면 벌써 충돌이 났다
git status
를 실행해 보면 어느 커밋, 어느 파일에서 충돌이 발생했는지 보여준다
both modified
인 것으로 보아 양 브랜치에서 동시에 같은 파일을 작업해서 발생한 충돌이다
충돌이 발생한 파일을 열어보자
내가 작성한 적 없는 <<<
, >>>
표식이 생겨있다
이는 충돌 병합 표식으로, 어느 부분을 너의 브랜치는 이렇게 수정했고 머지하려는 브랜치는 이렇게 수정했으니 너가 합쳐봐라 라는 뜻이다
<<<<
표식은 가져와서 머지하려는 브랜치====
표식은 수정점을 구분하는 구분자>>>>
표식은 머지받으려는 브랜치의 내용이다
양 브랜치에서 가져올 내용은 가져오고, 삭제할 내용은 삭제한 뒤 표식을 전부 지워주면 된다
수정사항을 add 후 commit하자
$> git rebase --continue
충돌을 해결할 때는 자동으로 rebase 상태가 되므로, git push
를 할 수 없다!
git push 대신 git rebase -—continue
를 통해 다음 merge 단계로 넘어가자
간단하게 설명하자면 git rebase 도중 다음 단계 (다음 커밋) 으로 넘어가기 위한 명령어라고 생각하면 된다
rebase에 대해서는 다른 포스팅에서 더 자세히 정리하려고 한다
충돌이 완전히 해결될 때까지 위의 과정을 반복하고, git rebase —-continue
를 통해 다음 커밋으로 넘어가자
모든 충돌 merge 작업이 끝나면 위와 같은 문구가 표시된다
rebase
과정은 기존의 커밋을 이용해서 아예 새로운 커밋을 만드는 것이기도 하고, 충돌을 합치는 과정에서 각 커밋에 다른 변화가 생겼기 때문에 원격 브랜치와 로컬 브랜치의 커밋 기록이 달라진다
당연하게 git push
를 시도하면 빨간 글씨로 경고가 뜨기 때문에 당황스러울 수 있는데, 침착하게 -f
옵션을 붙여서 다시 시도한다
원격 브랜치에 어떤 내용이 있던 상관하지 않고 강제로 push해서 덮어씌워버리라는 의미이다
충돌이 잘 해결되면 위처럼 Merge pull request
버튼이 활성화되고 초록색으로 변한다
회색 침침한 배경에서 초록색으로 바뀌니 안도감이 느껴진다
Merge를 진행하자
옆의 화살표를 누르면 merge 옵션이 나온다
Create a merge commit
은 merge 커밋 (merged ~ into ~) 을 하나 생성해 merge되었음을 표시한다squash and merge
는 여러 커밋을 하나의 커밋으로 뭉쳐 merge한다rebase and merge
는 여러 커밋을 전부 rebase하고 merge하는데, rebase 특성상 커밋들이 조금씩 수정되므로 해당 레포지토리에서 작업하는 다른 사람들한테서 충돌이 발생할 수 있다
보통은 기본적인 Create a merge commit
으로 진행한다
새로운 merge commit을 생성하므로 커밋 메시지와 코멘트를 남긴다
아래의 코멘트는 커밋 시 커밋 제목이 아니라 개행 후 적히는 내용으로 들어간다
설정이 완료되면 Confirm merge
를 누르자
잘 merge되면 풀 리퀘스트가 보라색으로 변하고, 아래에 Merge되었음을 알리는 문구가 추가된다
merge된 브랜치나 포크는 삭제해도 상관없다
만약 해당 PR에 연결되어 있는 이슈가 있다면, 그 이슈도 자동으로 닫히게 할 수있다
merge commit을 보자
아까 적은 커밋 메시지와 코멘트가 보인다
내 수정사항이 잘 반영되었음을 볼 수 있다
여담
깃은 항상 쓰는 기능만 썼었는데 파면 팔 수록 기능이 정말 많다는 것을.. 느낀다
사실 rebase도 최근에야 알았고 pull이 fetch & merge인 것도 비교적 최근에 알았다
많이 쓰는 기술인 만큼 조금 더 공부가 필요할 듯 하다
참고 자료
'이론적인 부분들 > Git Github' 카테고리의 다른 글
Git 폴더 뜯어보기 (0) | 2022.07.25 |
---|---|
Github PR 리뷰하기 (0) | 2022.07.23 |
Github, Git 기본 <status, add, commit, push> (0) | 2022.07.23 |
Github, Git 기본 <레포지토리 생성 및 클론> (0) | 2022.07.23 |
Gist 사용하기 + 삽질의 기록 (0) | 2022.07.19 |