git을 사용하는 경우는 크게 두 가지입니다.
먼저 첫 번째 경우 어떻게 하는지 확인해봅시다.
지금부터는 리눅스 명령어들을 사용하게 됩니다. 모르는 명령어가 있을 경우 "man <명령어이름>"을 검색하면 여러 내용들을 찾을 수 있습니다.
우선 start-git이라는 디렉토리를 새로 생성했습니다. 디렉토리의 경로는 자유롭게 정하면 됩니다.
$ mkdir start-git
$ cd start-git
$ pwd
/start-git
디렉토리는 윈도우에서의 폴더와 비슷한 개념입니다.
$ touch hello.txt && ls
hello.txt
그리고 touch
명령어를 사용해 hello.txt
라는 파일을 생성했습니다.
git init
명령어를 사용해 현재 디렉토리를 git을 이용해 버전 관리를 할 수 있도록 만들어줍니다.
$ git init
Initialized empty Git repository in /start-git/.git/
비어있는 git repository가 생성됐다고 알려줍니다.
git status
명령어를 사용하면 git repository의 상태를 알려줍니다.
$ git status
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.txt
nothing added to commit but untracked files present (use "git add" to track)
현재 main
브랜치에 있고 커밋이 하나도 없다는 걸 알 수 있습니다. 당장 브랜치가 뭔지 몰라도 괜찮습니다.
우선 우리는 첫 커밋을 만들겠습니다. 여기서 커밋이란 ep01에서 언급했던 숙제_최종.hwp
나 숙제_진짜최종.hwp
와 같은 버전이라고 생각하면 됩니다. 내가 커밋 하나를 생성하면 한 가지의 버전이 추가되는 겁니다.
위의 메시지를 보면 Untrakced files, 즉 깃이 추적하지 않는 파일에 hello.txt
가 들어있는 걸 확인할 수 있습니다. 우리는 이 파일을 추적해 버전 관리를 하고 싶으니까 git이 알려주는 대로 git add
를 사용해 git이 추적할 수 있도록 해주겠습니다.
$ git add hello.txt && git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.txt
메시지를 살펴보면 현재 브랜치는 main
이고 커밋도 하나도 없다는 걸 알 수 있습니다. 대신 hello.txt
파일이 커밋할 변경사항으로 추가됐습니다.
현재 hello.txt
파일은 비어있는 파일입니다. cat
명령어로 파일을 확인할 수 있습니다.
$ cat hello.txt
그럼 이제 git commit
을 이용해 새로운 커밋을 생성하겠습니다.
$ git commit -m "첫 번째 커밋"
[main (root-commit) a0c9147] 첫 번째 커밋
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 hello.txt
-m
옵션은 커밋 메시지를 간편하게 작성할 수 있도록 해줍니다. 이 옵션을 넣으면 뒤에 쌍 따옴표 안에 있는 문자열이 커밋 메시지가 됩니다.
git 명령어가 적당히 궁금하면 git <명령어> -h를, 심각하게 궁금하면 git <명령어> --help 를 터미널에 쳐보세요.
$ git status
On branch main
nothing to commit, working tree clean
커밋 후에 git status
를 통해 현재 커밋할 게 없다는 걸 확인할 수 있습니다.
이제 main
브랜치가 어떤 커밋들을 가지고 있는지 확인해보겠습니다. git log
명령어는 브랜치의 기록을 확인하는 명령어입니다. 뒤에 브랜치 이름을 넣을 수도 있고, 넣지 않는다면 현재 브랜치의 기록을 보여줍니다.
$ git log
commit a0c9147ee12442437943043e6c2c048df48e96a6
Author: Junepil Lee <hanu9257@gmail.com>
Date: Thu Dec 21 08:45:32 2023 +0000
첫 번째 커밋
우리가 커밋한 내용을 순차적으로 볼 수 있습니다. 앞서 우리가 설정했던 작성자의 이름, 이메일과 커밋 시에 입력했던 첫 번째 커밋이라는 메시지 또한 잘 입력됐습니다. 이렇게 우리는 프로젝트의 첫 커밋을 생성했습니다. 앞으로 나오는 모든 커밋은 프로젝트의 버전이라고 이해하면 됩니다.
이번에는 echo
를 사용해서 hello.txt
파일에 내용을 추가해보겠습니다.
$ echo wolrd > hello.txt
$ cat hello.txt
wolrd
추가된 내용은 전과 같이cat
을 통해 확인할 수 있습니다. 이제 다시 git이 현재 프로젝트의 상태를 어떻게 인지하고 있는지 확인해보겠습니다.
$ git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.txt
no changes added to commit (use "git add" and/or "git commit -a")
staged 상태가 아닌 변경사항에 hello.txt
가 있는 걸 확인할 수 있습니다. 그리고 아래를 보니 hello.txt
는 변경됐다고 알려주고 있고, 커밋하기 위해 추가된 변경사항이 없다고 합니다.
우리는 이 상태를 살펴보겠습니다. 평소에 문서나 다른 파일들을 작업하다가 ctrl + s
를 눌러서 저장해본 적이 있나요? 있다면 그때 혹시 내가 원하는 단락이나 부분만을 특정해서 저장할 수 있었나요? 그렇지 않았습니다.
하지만 어떤 프로젝트에 파일이 10개가 있을 때, 파일 1개에 변경 사항이 생겼다고 파일 10개를 전부 새로 저장한다면 이는 저장 공간의 낭비로 이어집니다. 그래서 git은 똑똑하게 변경된 부분만 저장할 수 있게 해줍니다. 심지어 한 파일 안에서도 마찬가지입니다.
바로 여기서 staging area가 등장합니다. working directory 즉 현재 변경한 내용들 중에 다음에 만들 커밋에 넣고 싶은 내용들을 staging area에 보관했다가, 이 내용들을 가지고 커밋을 생성하는 겁니다.
$ git add *
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hello.txt
이번에는 git add *
를 사용해서 변경 사항을 staging area에 추가했습니다. git add
는 기본적으로 파일 이름을 뒤에 붙여서 staging area에 추가하지만 이렇게 *
를 붙이면 git status
를 사용했을 때 나오는 모든 변경 사항들을 staging area에 추가합니다. 또한 git add ./foo/*
같이 경로 내의 모든 변경된 파일도 추가할 수 있습니다.
똑같은 방식으로 goodbye.txt
를 만들고 staging area에 추가했습니다. 커밋될 변경 사항들에 hello.txt가 변경됐고 hell.txt가 새로 생겼다는 내용을 볼 수 있어요.
$ echo bye > goodbye.txt
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: hello.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
goodbye.txt
$ git add * && git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: goodbye.txt
modified: hello.txt
그리고 이전에 했던 것과 같이 커밋을 만들었습니다.
$ git commit -m "hello.txt 내용 추가, goodbye.txt 생성"
[main 10aa7d4] hello.txt내용 추가, goodbye.txt 생성
2 files changed, 2 insertions(+)
create mode 100644 goodbye.txt
이제 다시 main
을 git log
를 사용해 확인해보면
$ git log
commit 10aa7d430fc0e9b860ea325e8ebbf92bd8f9bcbf
Author: Junepil Lee <hanu9257@gmail.com>
Date: Thu Dec 21 09:02:06 2023 +0000
hello.txt내용 추가, goodbye.txt 생성
commit a0c9147ee12442437943043e6c2c048df48e96a6
Author: Junepil Lee <hanu9257@gmail.com>
Date: Thu Dec 21 08:45:32 2023 +0000
첫 번째 커밋
main
에 두 개의 커밋이 있는 걸 볼 수 있습니다.
브랜치를 설명하기에 앞서 커밋마다 존재하는 의미를 알 수 없는 영어와 숫자로 이루어진 문자열은 체크섬이라고 불립니다. 커밋을 만들 때 메시지를 작성하긴 했지만 git은 다른 방법으로 각각의 커밋을 구분하는데 이때 사용되는 게 바로 각 커밋을 지칭하는 영어와 숫자 조합입니다.
예를 들어 우리의 첫 번째 커밋은 앞의 6자리를 이용해 a0c914
이라고 부를 수 있고, 같은 방법으로 두 번째 커밋은 10aa7d
라고 부를 수 있습니다. 일반적으로 이렇게 앞의 6자리를 이용해서 커밋을 지칭합니다.
git은 똑똑하게 앞자리도 커밋끼리 겹치지 않게 체크섬을 만들어주기 때문에 커밋을 표현할 때 6자리로도 충분합니다. 어떤 방식으로 이 체크섬을 만드는지 궁금하다면 SHA에 대해 찾아보길 추천합니다. 체크섬은 커밋의 내용이 같더라도 다를 수 있습니다.
브랜치는 커밋들의 관심사를 구분하기 위해 사용됩니다.
앞서 커밋은 하나의 버전이라고 했었습니다. 브랜치는 이 커밋들이 연결되어 구성됩니다. 만약 연결 리스트를 배웠다면 이해하기 쉽습니다. 왜나하면 커밋은 생성될 때 부모 커밋을 가지고 있기 때문입니다. 지금 우리의 main
브랜치에는 커밋이 두 개가 연결되어 있는 상태이고, 10aa7d
는 a0c914
를 부모 커밋으로 가지고 있습니다. 이 때문에 생성 순서와는 반대되는 포인터로 연결되어 있는 게 바로 브랜치입니다.
브랜치는 연결 리스트를 사용해 공통된 관심사에 속해 있는 커밋들을 모아놓은 것입니다. 덕분에 나중에 한 관심사에 대한 변경 사항들을 볼 때 이 관심사에 해당하는 브랜치만 보면 됩니다. 자동차를 프로그램으로 만들 때 바퀴를 만드는 영역, 창문을 만드는 영역을 따로 나눠서 창문과 바퀴 브랜치를 분리하면 작업도 각각 할 수 있고 관리도 더 쉬울 겁니다.
지금은 main
이라는 의미가 모호한 브랜치 하나만을 사용하고 있어 와 닿지 않겠지만 나중에 여러 개의 브랜치를 만들다 보면 왜 브랜치가 필요한지 감이 잡힐 겁니다.