Git(깃)이란?

Git은 2005년 리누스 토르발즈가 개발한 분산 버전 관리 시스템이다.

만들게 된 이유

리누스 토르발즈는 리눅스 커널을 만들 당시에 BitKeeper라는 분산 버전 관리 시스템을 사용했는데, BitKeeper라는 서비스는 원래 유로였지만 리눅스 커뮤니티에는 무료로 제공해주고 있었다. 커뮤니티의 개발자 한명이 BitKeeper의 통신 프로토콜을 리버스 엔지니어링해서 해킹하는 사건이 발생했고, BitKeeper는 무료로 리눅스 커뮤니티에 서비스를 제공하던 것을 철회했다. 이때 리누스 토르발즈가 분산 버전 관리 시스템을 2주 만에 만들었다.

  • 버전 관리 시스템 (VCS, Version Control System)참고 : https://heekangpark.github.io/git/vcs
  • 버전 관리(Version Control), 혹은 소프트웨어 형상관리(SCM, Software Configuration Management)란 소프트웨어 개발 및 유지 보수 과정에서 발생하는 소스 코드, 문서 등의 생성, 변경 이력, 삭제 이력 등을 관리하는 것을 말한다.
  • SVN vs GITSVN GIT
    사용법 간편하고 어렵지 않다. 다소 복잡하고 초보자가 이해하기 어렵다.
    기능 버전관리에 최적화된 간현한 기능 다양한 기능이 존재한다. 버전 관리에 필요한 모든 기능이 존재한다.
    프로세스 중앙 집중식 분산 관리식
    소스 충돌 위험 매우 높음 권환 설정을 통해 충돌 위험 감소
    저장소 백업 여부 저장소 백업이 용이 하지 못함. git 저장소만 있으면 리모트 복구는 언제든지 가능하다.
    다수 작업 관리 관리에 한계가 존재한다. 수백~수천의 프로그래머의 분산 작업에 매우 용이하다.
    작업 내용 복구 다소 불편하다. 예전 리비전으로 복구가 매우 편리하다.
    브렌치 생성 다소 불편하다. 로컬에서 브렌치 생성 및 태그 생성이 매우 편리하다.

 

개념

Git은 분산 버전 관리 시스템이기 때문에 리모트 서버에 있는 소스를 수정하려면 로컬 환경으로 소스를 클론(Clone)하는 과정이 필요하다. 말 그대로 모든 소스를 복사하여 사용자의 컴퓨터로 받아오는 것이다.

이후 Git은 로컬 환경의 파일을 추적하고 있다가 사용자가 소스를 수정하면 그 변경 사항을 감지한다. 그 후 사용자는 자신이 리모트 서버에 변경 사항을 반영하고 싶은 파일이나 소스 코드의 라인을 고른 뒤 리모트 서버에 업로드한다.

맨 위의 origin/master는 리모트 서버의 버전, 맨 밑의 master는 해당 컴퓨터의 버전을 의미한다.

즉, 리모트 서버에 있는 파일을 내 컴퓨터로 복붙한 다음 수정해서 다시 리모트 서버로 업데이트하는 것.

이때, 사용자가 자신이 변경한 로컬의 소스를 서버의 소스에 업로드한다. 즉, 서버로 밀어올리는 행위를 Push라고 부르고 사용자가 서버의 소스를 자신의 클라이언트로 가져오는 행위를 Pull 또는 Fetch라고 한다.

 

Remote(리모트) / Origin(오리진)

말 그대로 서버 자체를 의미한다.

우리가 자주 사용하는 구글 드라이브나 N드라이브와 같은 클라우드 스토리지를 사용하는 것을 떠올리면 이해하기 쉽다. 전 세계 어딘가에 있는 서버에 우리의 소스를 저장하는 것이다.

Git을 사용할 때는 내가 어떤 Remote 서버에 변경 사항을 업로드 할 것인지 정해야하는데, 반드시 하나의 Remote 서버만 사용할 수 있는 것이 아니기 때문에 내가 사용하는 Remote 서버의 이름을 정해줘야한다. 이때 주로 사용하는 관례적인 이름이 바로 Origin이다.

보통 한 개의 Remote 서버만 운용하는 경우가 대다수이기 때문에 많은 사람들이 Remote와 Origin을 혼용해서 부르곤 한다.

 

Repository(레파지토리)

Repository(레파지토리, Repo)는 저장소라는 뜻이다.

리모트 서버 내에서 구분되는 프로젝트 단위라고 생각하면 된다. 우리가 구글 드라이브를 사용할 때도 하나의 디렉토리에 모든 파일을 다 때려넣지않고 몇 개의 디렉토리를 만들고 용도에 따라 파일을 나눠서 구분하는 것과 동일하다.

일반적으로 한 개의 레파지토리는 하나의 프로젝트를 의미하지만 경우에 따라서 레파지토리 하나에 여러 개의 프로젝트를 구성하기도 한다.

<https://github.com/user/repository.git>
<https://user@bitbucket.org/group-name/repository.git>

레파지토리를 클론받을 때는 해당 레파지토리를 가리키는 URL이 필요한데, 레파지토리의 이름은 URL의 맨 마지막에 .git 확장자를 가지는 방식으로 표현된다.

 

Branch(브랜치)

일종의 독립된 작업을 진행하기 위한 작업 공간의 개념이다.

맨 처음 Git을 초기화했을 때 기본적으로 master라는 이름의 브랜치가 하나 생성된다. 그 후 개발하는 기능 또는 버그 픽스에 따라서 브랜치를 새로 생성하고 거기서 작업한 후에 나중에 다시 master로 합치는 것이다.

master 브랜치에서 다른 브랜치를 분리한 모습

Git을 초기화하면 기본적으로 master 브랜치가 생긴다. 메인 브랜치 역할을 한다.

브랜치는 어떤 브랜치에서 분리시키는 것이고, 분리된 브랜치는 분리될 당시의 부모 브랜치 상태를 그대로 가지고 있다.

개발자는 각 각의 브랜치에서 개발을 진행한 뒤 나중에 다시 master 브랜치로 변경 사항을 합친다.

참고 : https://velog.io/@soyi47/GitGithub-staging-commit

👀참고

 

필수 명령어

만약 혼자서 프로젝트의 버전 관리를 한다면 단순히 리모트 서버의 레파지토리에서 소스를 받아와서 변경한 후 다시 리모트 서버로 업로드하는 과정만으로도 프로젝트를 진행하는데 사실 아무 문제가 없다.

하지만 Git은 혼자서 개발하는 상황보다는 여럿이서 함께 소스를 수정하며 개발하는 협업 상황을 상정하고 만들었기 때문에 협업에서 발생할 수 있는 여러가지 곤란한 상황들을 타파하기 위한 많은 기능을 가지고 있다.

Git은 기본적으로 CLI(Command Line Tools)을 통해 사용하고 commit, fetch, branch와 같은 여러가지 명령어를 사용하여 이 기능들을 사용할 수 있게 해준다.

 

클론(Clone)

리모트 서버의 레파지토리에서 클라이언트로 파일을 복붙하는 행위를 말한다.

이때 클론을 수행하기 위해서는 어떤 레파지토리에서 파일을 가져올 것인지에 대한 정보가 필요한데, 이 정보는 URL로 표현된다. HTTPS 프로토콜이나 SSH 프로토콜을 사용하여 소스를 클론할 수 있는데, 보통 HTTPS를 많이 사용한다.

보통 Github와 같은 리모트 서버 제공업체들은 레파지스토리를 쉽게 클론할 수 있도록 눈에 잘 띄는 버튼을 만들어 놓고 해당 레파지토리의 URL을 제공하는 경우가 많다. 사용자는 단지 저 URL을 복사한 다음 Git의 clone 명령어를 사용해서 레파지토리를 클론하기만 하면 된다.

$ cd ~/dev/evan #원하는 작업 디렉토리로 이동
$ git clone <https://github.com/KDONG1224/test.git>

원하는 작업 디렉토리로 이동한 뒤 clone 명령어를 사용하여 레파지토리를 클론하게되면 현재 위치에 레파지토리 이름과 동일한 디렉토리가 생성되고 그 내부에 리모트 서버의 소스가 전부 복사된다.

~dev/evan 디렉토리 내부에 test 디렉토리가 생성되고 해당 레파지토리의 소스가 복사될 것이다.

 

풀(Pull)

리모트 서버의 최신 소스를 가져와서 로컬 소스에 병합해주는 명령어이다.

pull은 단순히 리모트 서버에서 로컬로 소스를 가져온다는 개념보다는 가져와서 합친다의 개념이기 때문에 브랜치끼리도 pull을 통해 소스를 합칠 수 있다.

$ git pull // 현재 내 로컬 브랜치와 같은 이름을 가진 리모트 서버 브랜치가 타겟
$ git pull origin master // origin 리모트 서버의 master 브랜치가 타겟

Pull Request 라는 단어가 있다. 이것은 “내가 작업한 브랜치를 가져와서 합쳐줘”라는 의미이다.

왜 Merge Request가 아니라 Pull Request 인 이유는 최종적으로 두 브랜치의 소스를 합치는 행위를 하는 주체가 요청을 한 사람이 아니고 요청을 받은 사람이기 때문에 요청을 받은 사람이 브랜치를 가져가서 합친다는 관점으로 생각하면 된다.

 

펫치(Fetch)

리모트 서버의 최신 이력을 내 클라이언트로 가져오되 병합은 하지 않는 명령어 이다.

$ git fetch

fetch 명령어를 사용하면 다른 사람들이 리모트 서버에 업데이트한 모든 내역을 받아올 수 있다. 내역을 보고 내 로컬에 있는 버전이 리모트 서버에 있는 버전보다 이전 버전이라면 pull 명령어를 사용하여 내 컴퓨터의 소스 코드를 갱신하면 된다.

이 명령어가 **pull**의 하위 호환이 아닌가? 라는 생각이 들 수도 있는데, **pull**과 **fetch**는 조금 용도가 다르긴 하다. pull 같은 경우는 일단 묻지도 따지지도 않고 바로 리모트 서버의 최신 소스를 가져와서 내 로컬 소스에 합쳐버리기 때문에 조금 위험하긴 하다. 예를 들면 지금 리모트 서버의 최신 소스가 버그가 있는 상태일 수도 있지 않을까? 그래서 보통 로컬 소스와 리모트 소스의 변경 사항을 미리 비교해보고 싶을 때 **fetch**를 사용한다.

 

변경 사항을 리모트 서버에 업데이트 하기

로컬에서 변경한 소스를 리모트 서버로 업로드하는 명령어들이 있다. 택배를 빗대어 생각하면 쉽다.

 

Add

원하는 변경사항만 골라 담는 add 명령어

어떤 소스들을 포장할 것인지 고르는 과정을 담당한다.

$ git add . // 현재 디렉토리의 모든 변경사항을 스테이지에 올린다
$ git add ./src/components // components 디렉토리의 모든 변경사항을 스테이지에 올린다
$ git add ./src/components/Test.vue // 특정 파일의 변경사항만 스테이지에 올린다
$ git add -p // 변경된 사항을 하나하나 살펴보면서 스테이지에 올린다

이때 선택된 변경 사항들은 스테이지(Stage)라고 불리는 공간으로 이동하게 된다. 이때 git add <경로> 명령어는 해당 경로 안에 있는 변경 사항을 전부 스테이지에 올리게 되는데, -p 옵션을 활용하여 변경 사항 하나하나 확인하면서 스테이지에 올릴 수 도 있다.

스테이지에 담긴 변경 사항들은 git status 명령어를 사용하여 확인해볼 수 있고, status 명령어에 추자적으로 -v 옵션을 사용하면 어떤 파일의 어떤 부분이 변경되었는지도 함께 볼 수 있다.

 

Commit

변경 사항들을 포장하는 commit 명령어

Add를 사용하여 원하는 변경사항을 스테이지에 올렸다면 이제 스테이지에 있는 변경 사항들을 포장해야 한다. 이때 이 포장하는 행위를 commit 이라고 한다. 커밋은 Git에서 엄청나게 중요한 부분을 차지한다. Git이 하나의 커밋을 하나의 버전으로 정의하기 때문이다.

$ git log --graph

* commit 20f1ea9 (HEAD -> master, origin/master, origin/HEAD)
| Author: KDONG <gkfl8807@gmail.com>
|
|     회원가입 기능 개발 끝!
|
* commit ca693fd
| Author: KDONG <gkfl8807@gmail.com>
|
|     회원가입 비밀번호 입력 폼 추가
|
* commit f9b6e2d
| Author: KDONG <gkfl8807@gmail.com>
|
|     회원가입 이메일 입력 폼 추가
|

그래프 상에서 HEAD가 20f1ea9 회원가입 기능 개발 끝! 커밋에 위치해 있으므로 현재 회원가입 기능까지 개발이 완료된 상태라는 것을 알 수 있다.

자세히 그래프를 보면 각 각의 커밋들은 20f1ea9과 같은 고유한 해쉬 값을 가지고 있는데, 이 해쉬 값을 사용하여 어떠한 커밋으로든 자유자재로 이동할 수 있다. 예를들면 회원가입 비밀번호 입력 폼 추가 커밋의 해쉬 값을 사용하여 git checkout ca693fd 명령어로 회원가입 비밀번호 입력 폼이 추가된 시점으로 이동할 수 있다.

이러한 커밋의 기능을 제대로 활용하기 위해서 커밋은 반드시 실행 가능한 단위로 해야한다. 특정 커밋으로 버전을 변경했을 때 어플리케이션이 제대로 실행되지 않고 에러가 발생하면 안된다는 것이다.

그리고 커밋에는 메시지를 담을 수 있다. 이 메시지는 커밋으로 인한 변경 사항이 무엇인지 직접적으로 표현해주는 유일한 수단이므로 좋은 커밋 메시지를 작성하기 위한 고민은 필수 입니다.

또한, 커밋은 아직 리모트 서버에 파일을 전송하는 것이 아니라 사용자의 클라이언트 내에서 수행되는 과정이므로 인터넷에 연결이 되어 있지 않아도 변경 사항을 커밋하는 것은 아무런 지장이 없다.

Push

변경 사항들을 원격서버에 업로드 하는 명령어

 

notion : https://noyclah.notion.site/Git-a85bc51b664c405492eabb33d5f28222

'공부 > 네트워크 관련' 카테고리의 다른 글

터미널과 서버  (0) 2022.06.01
암호화 / 복호화  (0) 2022.06.01
Process 와 Thread  (0) 2022.06.01
OSI 7계층과 TCP/IP  (0) 2022.06.01
네트워크와 인터넷 (Network & Internet)  (0) 2022.06.01