Joonas' Note
All about git - 핵심 개념 정리 본문
소스코드를 저장할 개념으로 학생때부터 git과 github을 꾸준히 사용했는데, 어느덧 거의 10년차가 되었다.
그렇다보니 주변에 git 에 대한 내용을 설명하는 경우가 많았는데, 사람들이 항상 혼란스러워 하는 부분을 이번 포스트 (어쩌면 시리즈)로 정리하고자 한다.
Git vs. GitHub
가장 중요한 것은 git 과 github 의 차이부터 아는 것이다.
특히 수많은 IDE가 git의 기능을 지원하면서 github(또는 다른 서버)와의 연동 역시 당연하게 지원하다보니, 둘을 구분하지 못한 채 개발하는 경우가 많이 있었다.
git
먼저, git은 온전히 "버전 관리 시스템(VCS; Version Control System)"이고 하나의 프로그램이다.
파일들의 변경 히스토리들을 기록하고 관리하는 것이 가장 큰 역할이자 목표이다.
쉽게 말해서 "파일 수정 사항"을 "그래프"처럼 관리하는 것만 담당한다.
(버전 관리 시스템에는 git 외에도 svn 같은 프로그램도 있지만 git 이 평정해버렸다.)
GitHub
그럼 GitHub 은 무엇인가?
GitHub은 각자 git 으로 관리한 그래프를 인터넷에 올려서 공유하는 허브 사이트이다.
즉, 서로의 작업 상황을 공유하는 등의 협업 관련 기능이 핵심이다.
그렇다보니 GitHub 외에도 Bitbucket, GitLab, Gerrit 등 여러 협업 플랫폼이 있다.
우리가 익히 알고 있는 "Pull Request"라는 것은 GitHub에서 제공하는 하나의 기능이다. Gerrit의 경우에는 패러다임이 조금 다르지만 Change Review 라는 유사한 기능이 있다. (별도의 포스팅에서 자세히 다뤄볼 예정)
git 기본 컨셉 이해하기
보통의 git 기능을 제공하는 툴을 사용하다보면 위와 같은 이미지를 본 적이 있을 것이다.
이렇게 생긴 모양은 그래프(graph) 또는 네트워크(network)라고 부른다.
먼저 git 은 "히스토리 관리"가 목적이고, 자세하게는 "여러 파일들이 변경된 역사를 모두 기록한다"고 말할 수 있다.
Commit
위에서 본 이미지와 같이 파일들의 버전 상태가 그래프와 같이 된다. 그 그래프를 이루는 하나의 점(node)가 커밋(commit)이다.
다시 말해서 "commit = 파일(들)의 변경 사항 묶음"이다.
기본적으로는 commit은 하나의 변경 사항 묶음 정도로 설명되는 게 맞고, 자세하게 말하자면 꽤 많은 내용을 저장한다.
- 커밋 메시지 (직접 작성)
- 커밋한 시간
- 커밋을 작성한 사람
- 각 파일들의 변경 사항들 (몇 번째 줄에 무엇이 추가되었는지, 삭제되었는지 등)
- 이전 커밋의 hash (지금은 중요하지 않음)
- 기타 등등
Branch
그러한 commit이 쌓이다보면 하나의 역사를 만든다. 필자는 이것을 항상 "하나의 세계"라고 표현해왔다. (지금은 멀티버스 개념이 잘 알려져있어서 설명하기가 너무 편하다 ^^)
commit은 그 세계에서 미래가 달라질 수 있는 중요한 이벤트들과 같고, 브랜치는 특정 시점에 갈라져서 다른 브랜치와는 다른 상태를 갖는다.
다시 말해서, commit 이 쌓인 하나의 줄기를 branch 라고 한다.
Repository
git init 을 통해서 폴더 내의 파일들을 관리할 수 있는 상태로 만들었다면, 그 폴더는 repository 이다.
특별한 기능이 있다기보다는, 일반적인 디렉토리와 동일하지만 버전 관리가 가능하다는 의미를 가진다.
당장 github의 아무 repository에 가서 다운로드 버튼을 누르면, 파일 전체를 zip 파일로 저장할 수 있다.
Fork (GitHub)
fork 라는 개념은 GitHub 에서 제공하는 기능 중 하나이다. 다른 호스팅 서버(gerrit)에는 없는 개념이다.
GitHub의 fork는 repository를 통채로 복제해서 마치 branch가 갈라진 것과 같은 효과를 제공한다.
유용하게 쓰이는 상황은, 원본 repository의 코드를 수정하고 싶지만 원본을 건드리고 싶지는 않을 때 (또는 그럴 권한이 없는 경우에), fork 된 repository를 마음껏 수정하는 식이다.
물론 같은 그래프(파일 변경 상태)를 어느 정도 공유하므로, 원본에 그래프를 적용해달라고 할 수도 있다. (자세한 내용은 Pull Request를 참고)
명령어 구분
글의 처음에서 언급했듯이, 그래프를 다루는 git 의 기능들과, 협업을 위해 서버(github 등)와 통신하는 기능들이 있다.
간단하게 요약하자면 아래와 같다.
- 서버 통신 관련: push, pull, fetch 등
- 그래프 관리: commit, rebase, merge, cherry-pick 등
- 상태 변경: add, reset, rm, stash, checkout 등
"상태"에 대한 내용은 별도의 글로 다룰 예정이다.
checkout
checkout 은 "특정 시점(commit)"으로 시간 이동을 하는 것과 같다.
(2019년부터는 git switch 라는 명령어가 생겼는데, 그래도 checkout 이라는 이름은 꽤 오랫동안 지원될 듯 하다)
브랜치 단위로 이동한다면, 그 브랜치의 가장 끝 커밋으로 이동한다. 참고로 현재 위치한 브랜치의 가장 끝을 HEAD 라고 부른다.
remote? origin?
git은 로컬(local)에서의 버전 관리만 담당하는 프로그램이며, github과 같이 협업을 위한 여러 호스팅 서버들이 존재한다.
내 컴퓨터에서만 관리하는 걸 local 이라고 부르고, 이것을 github과 같은 서버에 올리고자 할 때 서버를 remote 라고 부른다.
repository는 하나일수도 있지만, 하나의 코드를 여러개의 호스팅 서버로 관리하는 경우도 있을 수 있다.
예를 들면, 개발 코드의 브랜치는 github 으로 보내지만, 실제 배포 코드 브랜치는 bitbucket을 사용하는 등의 경우이다.
이 때, 어느 remote와 통신할 지를 결정할 때 사용하는 "별명"의 기본값이 origin이다. 그래서 다들 origin 이라고 부르는 데, origin, upstream 등 모두 대표적인 이름으로 사용하는 것들이다.
기존에 clone을 받았거나 GitHub과 같은 호스팅 서버와 연결된 git repository가 있다면, git remote -v 명령어를 입력해서 별명을 확인할 수 있다.
직접 사용하는 명령어의 예시로는, "git push origin main" 은,
"내 git에서 'origin'이라는 이름으로 연결된 remote repository에, 'main' 브랜치를 업로드하겠다" 라는 뜻이다.
다음 글
'개발' 카테고리의 다른 글
All about git - 충돌(conflict)과 merge/rebase 쉽게 이해하기 (0) | 2023.08.14 |
---|---|
All about git - 상태(status) 관리하기 (0) | 2023.07.15 |
SOLID 원칙 - Dependency Inversion Principle (DIP; 의존관계 역전 원칙) (0) | 2023.05.16 |
SOLID 원칙 - Interface Segregation Principle (ISP; 인터페이스 분리 원칙) (0) | 2023.05.16 |
SOLID 원칙 - Liskov Substitution principle (LSP; 리스코프 치환 원칙) (0) | 2023.05.16 |