Fork = 남의 GitHub Repository를 자신 계정의 GitHub Repository로 Copy해오는 것.
기본적으로 GitHub Repository에 Commit을 직접 Push할 수 있는 사람은 GitHub Repository를 만든 소유자 뿐이다.
다른 사람이 이곳에 Push를 하면 Error가 발생하므로 GitHub Repository의 소유자가 다른 사람을 협력자로 등록해야 한다.
GitHub Repository의 소유자가 협력자를 등록하려면 GitHub의 Repository Menu에서 Settings -> Collaborators Page -> Add people
그런데 GitHub 원본 Repository 소유자 입장에서는 협력자가 많아질수록 Push도 많아지기 때문에 원본 Repository를 관리하기가 어려워진다.
하지만 동시에 많은 개발자에게 의견을 받고 Open Source를 개선하고 싶은 욕구가 있다면 개발자는 Open Source에 참여하고 기여하고 싶지만 원본 Repository에 직접 Push하는 것에 대한 부담이 있다.
이럴 때 대안책이 바로 Pull Request이다.
개발자는 원본 Repository를 Fork해서 GitHub Repository를 생성하고 이곳에 Commit을 올린 후 원본 Repository의 소유자에게 Merge 요청을 한다.
원본 Repository 소유자는 개발자의 Merge 요청을 검토해서 원본 Repository에 반영하는 것이다.
결국 Branch가 원본 Repository 내에서 평행세계를 만드는 것이라면
Fork는 평행우주를 만드는 것이다.
Fork는 Branch를 포함한 원본 Repository의 모든 Commit Log들을 새로운 GitHub Repository에 통째로 Copy한다.
Branch에 올린 Commit Log는 원본 Repository에서 바로 볼 수 있지만, Copy한 GitHub Repository는 새로운 주소로 독립되었기 때문에 이곳의 Log를 보려면 추가적으로 이곳의 주소를 등록해야 한다.
너구리가 고양이와 문어의 원본 Repository를 Fork하면서 새로운 원격 Repository를 만들었다.
그렇기 때문에 Fork한 시점까지의 모든 History는 너구리가 알 수 있지만, 그 다음에 원본 Repository에 무슨 일이 일어났는지는 모른다.
원본 Repository와 Fork한 원격 Repository는 이미 주소까지 바뀌어서 서로 다른 원격 Repository가 되었기 때문.
그럼 본인의 원격 Repository에서 다른 원본 Repository의 History도 함께 보고 싶다면 어떻게 할까?
방법은 Git이 원본 Repository와 원격 Repository룰 동시에 추적하도록 만들면 된다.
- 착각하면 안되는 점은 Local과 GitHub가 한 쌍으로 연결되었는데, 이제는 하나의 Local Repository에서 두 개 이상의 GitHub Repository를 바라보는 방법을 학습.
Pull Request를 보냈을 때 Conflict가 난다면 두 가지 선택지가 있다.
- 현재 Commit과 Merge하고 싶은 Commit을 미리 내 Branch에서 Merge해서 Merge Commit을 만들고 이를 Pull Request로 보내는 방법.
너구리 개발자가 commit3에서 Conflict를 고친 후에 만들어진 Merged Commit을 원격 Repository에 올렸다.
아쉬운 점은 먼저 Merge하고 Pull Request를 보내면 Conflict는 나지 않겠지만, 본인의 Pull Request에 불필요한 Merge Commit의 이력이 남는 아쉬움이 있다.
그렇다면, 더 좋은 방법을 알아보자.
너구리는 Commit0을 Base로 Commit1,2를 만들었다.
Commit0이 최신 Commit3와 Merge한다면 Conflict 발생.
하지만 Rebase라는 것을 통해 Commit1,2가 Commit3를 Base로 만들어진 상태로 조작한다면 Commit3는 Commit2와 Fast-Foward Merge가 가능해진다.
앞서 말한 Merge Commit이 생기는 방법과는 달리 깔끔하게 Pull Request를 보낼 수 있게 된다.
또한 본인의 Branch에 본인의 변경 사항만 남길 수 있다는 장점도 존재.
정리하자면 Rebase는 옛날 Commit(Commit0)을 가준으로 만든 Commit(Commit2)을 최신 Commit(Commit3)을 Base로 만든 것처럼 이력을 조작하는 것이다.
만약 Conflict가 발생한다면 Rebase 도중에 해결하면 된다.
Rebase 후에 조작된 이력을 GitHub Repository에 Push해야 한다.
하지만 Rebase는 이력을 조작하는 행위이기 때문에 일반적인 Push는 수행할 수 없다.
Rebase를 하려면 다른 개발자가 이 변경 사항을 사용하고 있지 않아야 한다.
History를 강제로 조작하는 것이기 때문에 만약 다른 사람이 History를 보고 있다면 완전히 꼬이게 된다.
따라서 Rebase는 다른 개발자에게 피해를 줄 수 있기 때문에 본인의 Branch에서만 사용해야 한다.
Rebase 후, 반영하기 위해 강제 Push가 필요하다.