기타

[git]책 - 팀개발을 위한 git, github 시작하기(3일차)

변기원 2023. 1. 20. 16:22

chapter4 개념 fork, clone, pull request, merge, rebase

 

같은 base를 기준으로 분기하는 브랜치 말고

어떤 원격저장소를 그대로 복사해서 쓰는 것이 fork이다. 오픈소스 프로젝트를 하기 위해 필요한 개념인데

하나의 프로젝트에 콜라보레이터가 많아지면 수많은 사람이 직접 원본저장소에 푸시할 수 있기 때문에

버전관리가 어려워질 수 있다. 그래서 원본저장소를 fork 해서 나의 원격저장소에 복사하고

마음껏 코드를 추가, 수정 후 나의 원격저장소를 원본저장소에 병합요청하면 원본저장소의 소유자(A)는 풀리퀘스트를 올린

사람(B)의 코드를 검토 후 원본저장소에 반영할 수 있다.

아래는 원본저장소 소유자를 A, 이를 포크 해서 자신의 원격저장소로 가져온 사람을 B 라고 한다

kiwonbyun/iTshirt 레포지토리를 포크해서 kiwonFlow/iTshirt 레포지토리가 생겼다.

B의 원격저장소를 clone 받으면 A의 원본저장소의 커밋내역까지 전부 복사돼서 가져온다.

 

B가 어떤 코드를 수정해서 본인의 원격저장소에 푸시했다.

이것을 A의 원격저장소에 병합요청 하기 위해 Pull Request를 보낸다.

내가 이런 것들을 바꿨으니 검토 후에 반영해 주세요!라는 뜻이다.

A가 Pull request탭에서 이 내역을 확인하고 Merge pull request를 클릭하면 병합이 된다.

브랜치를 통해 작업하는 것과 개념이 동일하다.

 

근데 문제가 있다.

브랜치를 통해 작업을 할 때도 base에서 분기하여 한참 작업을 하고 다시 base로 병합하려고 했을 때

다른 사람이 나보다 먼저 base의 코드를 변경해 놓은 상태라면 "Can't automatically merge"라는 메시지가 뜨면서 병합할 수 없다.

브랜치를 통해 작업하던 것을 복습해 보자

깔끔한 상황을 위해 현재 상태를 로컬/메인 전부 main, comment, cart 브랜치 모두 가장 최신 코드를 가진 상태로 만들었다.

이곳을 base로 각 브랜치가 분기한다.

나 말고 다른 사람이 comment브랜치에서 "이런저런 기능 추가"커밋을 만들고 원격에 올린 후 main에 병합했다.

이 상황에서 내가 cart브랜치를 수정하고 "변기원 추가"커밋을 만들고 pull request를 보내면

Can't automatically merge 메시지가 나온다.

cart브랜치가 분기한 main과 현재 main의 상태가 달라져서 충돌이 생겼다.

충돌을 수정하면 다시 pr을 올리게 되고 병합도 할 수 있다.

충돌이 없으면 base가 달라져도 병합이 된다

 

이번에는 브랜치가 아니라 레포지토리끼리 코드가 충돌한 상황이다.

2일 차에서 배웠듯 작업브랜치로 main을 병합해서 충돌을 해결하듯이

원본레포지토리를 가져와서 병합하고 충돌을 해결하면 pull request를 올릴 수 있을 것이다.

근데 이렇게 하면 실제로 코드를 변경한 커밋 외에도 충돌을 해결하느라 생긴 병합커밋이 생길 것이다.

 

이것을 피하고 깔끔하게 변경한 부분만 pr을 보내는 방법이 바로 rebase이다.

re-base 즉. base를 다시 잡는다는 뜻으로 아주 직관적이다. 개념은 이렇다

위가 A의 원본저장소, 아래가 B의 원격저장소 상태이다. B가 작업을 하는 동안 base에서 커밋이 두 번이나 더 생겼다.

아예 원격저장소의 주소가 다르기 때문에 B는 A의 커밋상태를 알 수 없었다.

B에게 A의 원본저장소 커밋상태를 알게 하려면 원격을 추가해야 한다.

기존에는 원본저장소 origin만 보고 있었는데, add remote를 해주면 원본저장소도 보게 된다.

이름은 관용적으로 upstream이라고 짓는다. 자세한 방법은 책에..

그러면 아래와 같은 상태가 된다.

B의 로컬에서 추적할 수 있는 원격이 두 개가 됐다. origin, upstream

이제 로컬의 수정사항을 똑 떼어서 upstream의 최신커밋을 base로 재배치를 해주자 이것이 rebase이다.

당연히 충돌이 생기므로 로컬에서 해결을 해주고 커밋을 남긴다.

그러면 upstream의 최신커밋을 다시 base로 하여 그 위에 B의 커밋이 새로 생긴다.

rebase가 된 것이다. 하지만 B의 origin/main은 여전히 옛날 커밋기록을 가지고 있다.

다시 푸시를 해줘야 하는데, 이때는 이력을 조작하는 행위이기 때문에 강제푸시를 해줘야 한다.

 

여기까지 되면 이제 B의 원격저장소에서 A의 원본저장소로 pr을 보낼 수 있게 된다.

 

 

 

chapter5 개념 amend, cherry-pick, reset, revert, stash

 

amend: 마지막 커밋을 수정한다. 원격에 이미 반영된 경우, 강제푸시를 하면 수정할 수 있다.

 

cherry-pick: 다른 브랜치의 수많은 커밋 중, 원하는 커밋 하나만 가져올 수 있다. 탐나는 체리 하나만 따온다.

 

reset: 원하는 커밋으로 현재 브랜치를 초기화한다. soft-모든 로컬변경사항 유지 mixed - 작업상태는 그대로 두고 인덱스 리셋

hard - 모든 작업상태 변경사항을 버림

mixed로 reset 하면 시점을 해당 커밋버전으로 옮기지만 그 이후의 변경사항들이 스테이지 아래에 살아있게 된다.

hard로 reset하면 변경사항들이 모두 사라지고 해당 커밋으로 시점이 옮겨지게 된다. 원격에 반영할 땐 강제푸시를 해야 한다.

 

revert: reset은 아예 과거의 커밋으로 되돌아가는 것이고 revert는 되돌리는 새로운 커밋내역을 남기면서 되돌리는 방법이다.

 

stash: 작업 중인 코드들을 아직 커밋하긴 좀 그렇고, 다른 브랜치로 이동하고 싶을 때, 변경내역들을 잠시 서랍에 넣어두는 것