이제 막 개발을 시작하는 사람들이거나 개발을 해본적이 있는 사람이라면 한번은 Git에 대해서 들어봤을 것입니다.
이 글을 통해 깃을 통해 커밋, 풀, 푸시, 패치 등등 각각의 명령어들이 로컬저장소와 원격저장소 사이에서 어떤 역할들을 하고있는지 설명하려고 합니다.


버전관리 시스템

깃(Git)에 대해 설명하는 여러 글들을 찾아보면 버전 관리 시스템(Version Control System)이야기하고 있습니다.
Git은 등장 이전 가장 많이 사용되던 SVN과는 다르게 분산형 버전관리 시스템이라는 특징이 있습니다. SVN은 중앙형 버전관리 구조이기 때문에 중앙 서버에 의존적이고 각 개발자들이 동시에 작업할 때 병합에 불편함이 있다는 단점이 있었으나 Git의 등장으로 서버와 연결되어 있지 않은 상태로오프라인 환경에서 작업할 수 있다는 점 등 독립적으로 작업을 할 수 있게 되었습니다.
물론 Git이든 SVN이든 각각의 장점이 있기 때문에 장단을 알고 상황에 맞게 형상관리도구를 선택하는게 가장 좋습니다.

Git

그럼에도 불구하고 많은 기업들과 개발자들은 Git을 사용하고 있기 때문에 Git은 어떤식으로 소스를 관리하는지 알아보도록 하겠습니다.
저는 깃에서 얘기하는 여러가지 개념들 중 가장 중요하게 생각하는건 저장소라고 생각합니다.
작업 영역(Working Directory)에서 작업한 결과물(소스가 작성된 파일)을 실제 물리적인 경로에 존재하는 저장소에 변경된 소스파일과 함께 변경이력을 같이 저장하는 기능, 저장된 이력들을 통해 이전 버전으로 다시 돌아가는 기능, 어떤 내용들이 변경되었는지 확인하는 기능 등 여러가지의 다양한 기능들을 사용하기 위해 소스파일이 필수적으로 저장소에 올라간 상태여야 하기 때문입니다.
작업한 소스들을 실제로 저장소에 등록하고 관리하는 프로세스는 아래 그림과 같습니다.

깃은 버전관리를 위해 작업 공간을 논리적으로 분리하는데 그림에서 보이는 Local 영역의 세가지(Working Directory, Staging Area, Repository)로 구분할 수 있습니다.

Working Directory

이름 뜻 그대로 현재 개발자가 작업하고 있는 작업영역을 의미합니다. Staging Area와 연결되어 작업한 결과물들을 git add 명령어를 통해 Staging Area로 보낼 수 있습니다.
깃은 파일의 tracked 상태를 이용해 파일을 추적하고 관리하는데 git add 명령어를 통해서 수정된 파일을 staging area로 보내는 것 외에도 untracked 상태에 있던 파일을 git이 관리할 수 있게 tracked 상태로 변경해주는 작업을 합니다.

Staging Area (Index)

git add 명령어를 통해 staging 상태로 변경된 파일들이 존재하는 영역입니다. git commit 명령어를 통해 해당 영역에 있는 파일들을 Local Repository에 전달할 수 있습니다.
스테이징 영역에 있는 모든 파일들은 git add 명령어를 통해 전달받기 때문에 모두 tracked 상태이고, 그 말의 의미는 git을 통해 추적/관리할 수 있다는 의미입니다.
커밋 전 커밋 대상이 되는 파일이 어떤 파일들인지 git status 명령어를 통해 확인할 수 있습니다.
git status 명령어를 입력하면 스테이징 상태(staged)인 파일들은 Changes to be committed 영역에 나타나게 됩니다.

Local Repository

Repository는 실제로 변경된 파일들과 이력이 저장되는 영역입니다.
이 영역에서는 개발자의 로컬환경에서의 파일 변경이력과 파일들이 실제로 저장되어있고 원격 저장소가 있다면 로컬 저장소에서 관리하고 있는 변경내용을 원격 저장소로 보내거나, 반대로 원격 저장소의 변경 내역을 로컬 저장소로 불러올 수 있습니다.

Remote Repository

원격 저장소라고도 부르는 Remote Repository는 사용자의 로컬환경을 벗어나 원격에 있는 서버에서 Local Repository의 역할을 하는 저장소 입니다.
Local repository는 개발자 한명이 개발을 하며 버전에 대한 관리를 할 수 있지만, 원격 저장소를 사용해 작업한다면 개발자의 로컬환경에서 벗어나 여러 개발자가 함께 협업할 수 있습니다.

Branch

Branch는 Repository 안에서 독립적으로 작업하고 작업에 대한 관리를 할 수 있게 분리한 공간입니다. Repository를 관리하면서 브랜치 라는 용어가 등장했습니다.
주로 새로운 기능을 개발하거나 긴급하게 버그를 수정해야할 경우 새로운 브랜치를 만들어 작업을 하며 그 외에도 여러가지 전략에 따라 브랜치를 나누어 사용합니다.
대표적인 브랜치 전략으로는 Git Flow, GitHub Flow, GitLab Flow 등이 있습니다.
브랜치는 로컬/원격 모두 만들 수 있고, 원격 브랜치를 로컬 브랜치에 대응해서 사용할 수도 있습니다.

마무리

Git의 작업영역이라는 중요한 개념을 제대로 이해하고 사용할 때, 작업내용을 관리하고 특히 협업하는 과정에서 더 효과적으로 프로젝트를 관리할 수 있을거라고 생각합니다.