[TIL] Git & GitHub ( 1탄 )
오늘은 그동안 나를 무던히도 괴롭혀온 git에 대해서 포스팅해보고자 한다. git은 정말 어렵고 또 어렵다. 처음 git에 대해 배운 날에는 혼이 빠지는 느낌을 받았다. 도대체 이 어려운 git을 왜 써야 하는 것이며, 이 어려운 git을 어떻게해야 좀 더 쉽게 이해할 수 있는지에 대해서 자세히 포스팅하려 한다.
1. Git 이 뭔가요 ? Git 은 왜 필요한가요 ?
Git이란 소스코드를 효과적으로 관리하기 위해 개발된 '분산형 버전 관리 시스템'이다.
( 💁🏻♀️ 버전은 프로그램의 변경사항을 의미한다. )
🙋🏻♀️ 그렇다면 버전은 왜 굳이 관리해야하는 걸까? 최종 코드만 계속 갱신하면 되는게 아닐까?
매번 코드 수정 때마다 변경 사항을 업로드하는게 더 귀찮지 않을까?
( 💁🏻♀️ Git에서는 소스 코드가 변경된 이력을 쉽게 확인할 수 있다. 또한, 특정 시점에 저장된 버전과 비교할 수 있고
특정 시점으로 되돌아갈 수도 있다. 게다가, 내가 올리려는 파일이 다른 팀원과 편집한 내용과 conflict(충돌)한다면
서버에 업로드 할 때 경고 메시지가 발생한다. 그렇기에 실수로 누군가의 작성 문서를 덮어버리는 일은 생기기 힘들다. )
개발을 하다보면, 협업이 필수과정이다. Git은 문제점들(코드를 공유받지 못해 다음 단계로 진행할 수가 없는 경우, 팀원들 간의 코드 충돌 경우, 여러 번의 수정 과정을 거치면서 내가 짠 코드가 무엇인지 헷갈리게 되는 경우 등)을 방지하기 위해 버전 관리를 통해 작업 일지 기록이나 협업, 백업 등을 가능하게 한다.
위 모든 이유들로 인해 Git은 필수적으로 모든 개발자들에게 필요한 필수템이라고 할 수 있다.
2. Git 에 관한 자세한 개념 소개
1) Repository (저장소)
Repository( 레포지토리 )는 말 그대로 파일 등이 저장되는 저장소로, 프로젝트 폴더를 의미한다. 저장소의 종류는 다음과 같다.
- Remote Repository (원격 저장소): 원격 서버에 저장된 저장소로, 여러 사람이 함께 공유한다.
- Local Repository (개인 저장소): 우리가 직접 관리하는 저장소로, 내 PC에 저장되어 있다.
보통 레포지토리는 로컬에서 만들어서 원격에 업로드하거나, 원격에서 생성된 레포지토리를 로컬로 다운받는 방법으로 생성한다.
2) Commit
Commit( 커밋 )은 프로젝트의 변경 이력을 말한다. 복잡하게 생각될 수 있는데, 간단하게 로컬에서 작업 시 다음과 같이 나타낼 수 있다.
3) Branch
이전까진 모두 개인이 로컬에서 개발하는 상황에서 사용하는 git의 명령어다. Branch( 브랜치 )는 여러 명이 같은 코드를 공유하며 협업하는 상황에서 사용하는 git의 명령어다. 앞서 설명했듯, 개발자들은 여러 번 commit을 하여 코드를 업로드한다. 이때 누가 어떤 commit을 추가했는지 구분이 가능해야 한다. 바로 이런 상황에서 사용되는 것이 branch다. branch는 각 개발자들이 개발을 진행하고 있는 환경 또는 흐름을 말한다. 그래서 새로운 브랜치가 생성되더라도 기존의 메인 브랜치는 그대로 남아있다. 이게 무슨 의미인지 그림을 통해 설명하려 한다.
물론 다음과 같이 한 사용자가 자신의 기능의 세부 브랜치를 또 다시 나눌 수도 있다. ( 브랜치 생성 가능 갯수에는 제한이 없다. )
▶ 주로 쓰이는 브랜치 종류 (" Git flow - 저장소 고수준 관리위한 브랜칭 기법 ")
☑️ Master 브랜치 - (메인 배포판) 실제로 클라이언트에서 이용하는 최종 형태의 메인 브랜치이다.
☑️ Develop 브랜치 - (메인 개발) 현재 개발이 진행 중인 메인 브랜치이다. Master 브랜치와 마찬가지로
추가적으로 생성 또는 삭제되지 않는 브랜치이다.
☑️ Feature 브랜치 - (추가 기능 개발) 새로운 기능을 추가하기 위해 사용되는 브랜치로, 특정 기능의 개발이 필요할 때
Develop 브랜치에서 파생되며, 기능 개발이 완료되면 Develop 브랜치로 병합된다. (가장 많이 생성되었다 삭제되는 브랜치 )
4) Checkout
현재 위치한 commit ( 커밋 )에서 다른 commit ( 커밋 )으로 이동하는 것을 Checkout ( 체크 아웃 )이라 한다. 체크 아웃을 통해 현재 커밋에서 같은 브랜치 내 다른 커밋으로 이동하거나, 다른 브랜치 내 커밋으로 이동할 수 있다. 결론적으로 체크아웃으로 인해 이전 시점의 버전으로 되돌아갈 수도 있고, 다른 사람의 브랜치로 전환해 다른 개발자들의 코드 진행 상황을 확인해 볼 수도 있다.
5) Merge
Merge는 나뉘어진 브랜치를 다시 하나의 브랜치로 합치는 것을 말한다. 가장 오류가 많이 발생하는 과정이니 주의해야 한다.
Merge 진행 시 현재 브랜치를 브랜치가 합쳐지는 기존 메인 브랜치로 전환한 후 수정된 브랜치를 Merge해야 오류가 발생하지 않는다.
여러 개의 브랜치들을 한꺼번에 Merge할 때도 마찬가지로, 차례대로 기존 브랜치 상태에서 Merge를 진행해야한다.
Merge에는 종류가 2가지가 있다. 하나는 fast-forward이고, 나머지 하나는 non fast-forward이다.
먼저 fast-forward는 기본 merge 방식으로, 서로 다른 두 브랜치를 충돌 없이 자동 merge 시키는 병합이다.
하지만 그 과정에서 때때로 일부 문법으로 인해 충돌 (Conflict)이 발생하면 병합에 실패하는 경우가 발생한다.
이때 해당 충돌 기록을 살피며 일일히 해당 코드를 수정한 뒤 Merge를 이어서 진행하면 성공적으로 브랜치가 병합된다.
이 Merge 방식이 non fast-forward이다. 또한 이 과정에서 코드의 수정이 이루어졌으니 마찬가지로 새로운 커밋이 생성된다.
6) Clone
Clone ( 클론 )은 원격 저장소로부터 특정 프로젝트를 통째로 내 로컬 저장소에 다운받는 것을 말한다.
7) Push
Push ( 푸쉬 )는 현재 내 로컬에서 작업한 변경 사항들을 원격 저장소에 반영하는 것을 말한다.
작업이 완료될 때마다 원격 저장소에 푸쉬해야 다른 사람들이 내 코드를 확인할 수 있다.
8) Pull
Pull ( 풀 )은 원격 저장소에서 변경된 사항들을 내 로컬 저장소에 반영하는 것을 말한다. Push의 정반대 개념으로, 다른 사람이 Push를 해서 원격 저장소에 코드를 업데이트하면 우리는 해당 코드를 Pull하여 로컬의 코드를 업데이트한다. ( 이때 기존의 코드와 내 코드가 다른 경우 Merge를 진행해 코드를 합치게 된다. )
※ Clone과 개념이 헷갈릴 수도 있는데, Clone은 프로젝트를 처음 불러올 때 프로젝트 전체를 다운받는 것이지만, Pull은 해당 프로젝트에서 변경된 사항들만 다운받는 것을 말한다.