Git Basics (1)

4 minute read

What is Git?

Git은 무료 오픈소스 distributed version control system으로써 소스 코드의 변경을 추적하기 위해 사용된다. 매우 활발하게 관리되고 있는 프로젝트이고, 소프트웨어 개발 프로세스에서 없어서는 안되는 편리한 must-have 툴이다.

다음과 같은 특징을 가지고 있다.

  • 오픈소스/무료 소프트웨어
  • 사용하기 쉽고 매우 빠름
  • Branching 기능: 새로운 아이디어를 시도해보기 위해 branch를 생성하고, 변경 사항을 잃지 않고 이전 상태의 코드로 돌아 올 수 있다. 즉, 실험하기 위해 브랜치를 만들고, 잘 안될거 같으면 그냥 삭제하고 돌아 올 수 있다 - 아무도 모르게
  • 나의 프로젝트의 모든 부분의 암호화 관련의 무결성을 보장해줌 - 강한 보안
  • 탈중앙화(decentralized)되어 있고 분배(distributed)되어 있음 - 많은 개발자들과 협업하는 것이 매우 원활함

이는 Git의 몇 가지 장점을 나열한 것이고, 이보다 더 많은 기능과 편리함을 가져다 준다.

Git을 사용하면서 다음과 같은 용어들을 많이 접한다.

  • Commit: 코드 히스토리에서의 하나의 시점. 커밋은 직관적으로(formal하지 않지만) 보면 코드 베이스의 특정 변경 사항(들)로 구성된 스냅샷으로써 언제든지 다시 가져올 수 있는 것이라고 이해할 수 있다.
  • Branch: 활동 중인 개발 라인(line)
  • Repository: 커밋들(+그것의 메타데이터)의 컬렉션

Installation

Mac OS나 리눅스 시스템에서는 Git이 디폴트로 설치되어 있다. 터미널에 git을 치면 확인할 수 있다.

윈도우에서는 WSL (Windows Subsystem for Linux)와 같은 command-line Linux in Windows를 사용하는 것이 좋다. 혹은 Windows CLI를 잘 안다면 윈도우용 Git을 사용해도 된다.

Creating a Git Repository

다음과 같이 새로운 디렉토리를 만들어보자.

mkdir projects

그 후, 해당 디렉토리로 들어간다.

cd projects

그 다음에 또 새로운 디렉토리를 만들어서 그 안으로 들어간다. 이 디렉토리가 root working directory가 될 것이다.

mkdir tutorial1
cd tutorial1

그리고 새로운 텍스트 파일을 만들어 준다.

echo Hello World > hello.txt

그 다음에 다음 커맨드를 통해 새로운 깃 레포지토리를 만들어준다.

git init

이 커맨드는 빈 로컬 깃 레포지토리를 tutorial1 디렉토리 안에 생선한다. 이 커맨드를 실행하고 ls -a를 해보면 숨겨진 .git파일이 보일 것이다. .git 레포지토리는 서브디렉토리에 모든 데타데이터 및 실제 프로젝트 데이터를 저장한다. 모든 깃 레포지토리들은 동일한 디렉토리 구조를 갖을 것이다.

ls .git

을 실행해보면, .git 디렉토리의 서브디렉토리들을 볼 수 있다. HEAD, objects, refs, 등과 같은 디렉토리들을 가지고 있을 것이다.

Staging and Making a commit

커밋을 만들기 전에, staging을 알고 가야 한다.

어떠한 커밋을 레포지토리에 만들기 전에, 변경 사항을 포함하고 있는 파일들은 staging area라는 곳에 먼저 올라가야 한다. 간단히 말해, staging area는 다음 커밋에 무엇이 갈지에 대한 정보를 저장하고 있는 우리의 디렉토리에 포함된 파일이다. 파일을 stage하면 레포지토리는 이 stage에 대해 메모를 남겨, 유저가 git commit 커맨드를 실행하여 커밋을 만들때 마다 변경 사항을 가지고 있는 stage된 파일이 새로운 커밋의 일부분이어야 한다는 것을 알게된다. Staging area에 파일들을 추가하기 위해서는 git add 커맨드를 사용한다.

다음 커맨드를 실행하면 hello.txt를 staging area에 추가한다.

git add hello.txt
find .git/objects -type f

다음과 같은 것을 볼 수 있을 것이다.

.git/objects/de/c4cb0dba536b6baaaa0d487c0d34655d46da84

git add hello.txt 커맨드는 텍스트 파일을 레포지토리에 추가한다. .git/objects 디렉토리에 blob object를 생성한다. 파일 내용의 SHA1으로 해싱된 것이 파일의 이름이 된다. SHA1 해시의 첫 두 개의 문자는 디렉토리 이름을 나타내고 나머지는 object의 파일 이름이다. 따라서 위 예시의 SHA1 해시는 dec4cb0dba536b6baaaa0d487c0d34655d46da84이다. (de는 디렉토리 이름)

Object dec4cb0dba536b6baaaa0d487c0d34655d46da84의 내용을 보기 위해서 다음 커맨드를 .git/objects 디렉토리에서 실행해준다.

cd .git/objects
git cat-file -p dec4cb0dba536b6baaaa0d487c0d34655d46da84

Object의 내용 “Hello World”를 볼 수 있을 것이다. NOTE: 같은 내용을 가진 두 개의 파일이 있다면(복사 해서 생성), Git object 데이터베이스에는 한 개의 카피만 존재할 것이다. 왜냐하면 내용이 동일한 SHA1 값을 가지기 떄문이다. 예를 들어,

cp hello.txt hello2.txt
git add hello2.txt

를 실행하여 hello2.txt를 staging area에 추가해도, .git/objects 디렉토리에서 blob object를 find해보면 이전에 생성된 것 하나 밖에 보이지 않는다.

보통은 한 개의 파일 보다 더 많은 파일들, 혹은 디렉토리들을 staging area에 추가 하는 일이 많다. Refer to Git CheatSheet

자, 이제 깃에서 커밋이란 무엇인지 알아보자. 파일이나 여러 개의 파일들이 staging area에 추가되면, 변경 사항들이 기록된 것은 아니다. 우리는 단지 무엇이 기록되어야 하는지에 대한 메모를 저장한 것 뿐이고 아무것도 기록한 상태는 아니다. Stage된 파일들의 내용이 기록되기 위해서는 commit이란 것을 수행한다.

커밋을 하면 stage된 파일들의 스냅샷을 생성하고 그와 함께 메시지를 하나 연관시켜 blob object가 생성된다. 레포지토리에 만들어진 모든 커밋에 대해 SHA1 해시가 계산되어 무결성을 보장해준다. 쉽게 말해 깃 커밋레포지토리에서 만들어진 변경 사항들을 기록하는 것이다.

깃 커밋을 하기 전, 커밋터(commiter)의 이름과 이메일 주소를 셋업 해야한다. 그렇게 해야 커밋을 누가 했는지 알 수 있기 때문이다.

git config --local user.name "<Your name>"
git config --local user.email "<Your Email Address>"

위 커맨드를 실행해준다. 만약 유저 이름과 이메일을 만드는 모든 레포지토리에 대해 동일하게 쓰고 싶다면 --local대신 --global을 사용한다.

이제 첫번 째 커밋을 할 준비가 되었다. 다음 커맨드를 실행하여 staging area에 있는 모든 파일들에 대해 커밋을 만들어 보자.

git commit -m "My First Commit"
find .git/objects -type f

NOTE: -m flag 없이 그냥 git commit을 해도 무방하다. 그렇게 되면 vim 에디터로 들어가서 메시지를 남겨주면 된다.

위 커맨드를 실행해보면 3개의 object가 있을 것이다. 커밋으로 인해 두 개의 object 타입이 추가된다 - tree object & commit object. Tree object는 blob와 파일 이름간의 매핑을 기록한다. Commit object는 이 커밋의 내용과 그것의 부모 커밋에 대한 레퍼런스를 기록한다. Tree object를 살펴보기 위해 object 내용을 출력하는 다음 커맨드를 실행해본다.

git cat-file -p <object name>

다음과 같은 내용이 보일 것이다.

100644 blob dec4cb0dba536b6baaaa0d487c0d34655d46da84 hello.bak 
100644 blob dec4cb0dba536b6baaaa0d487c0d34655d46da84 hello.txt 

Tree object를 보니 2개의 행이 있고 각 행은 파일을 나타낸다. 각 행의 포맷은 파일 타입, object 타입, 해시, 그리고 파일 이름 순서로 출력되었다. 예를 들어 파일 타입 100644는 일반 파일을 나타낸다. Commit object를 확인해보면 다음과 같이 나올 것이다.

tree 0748b6dad6574ce9ccf7a2c56b87f9cf994f334d 
author Sui <sui.man@google.com> 1532580259 +1000 
committer Sui <sui.man@google.com> 1532580259 +1000 

My First Commit  

파일 구조, 메타데이터, 작성자, 커밋터, 그리고 커밋 메시지 정보를 포함하고 있다.

추가 조사할 부분

  • Staging의 필요성 및 중요성
  • Blob, tree, commit object들의 구조 및 git add와 git commit 실행으로 인한 내부 로직

Categories:

Updated:

Leave a comment