Git 기초 사용법(이정도는 익혀두자)

요즘 대중적으로 널리 쓰이고 있는 Git은 대부분의 개발자라면 능숙하게 사용할 수 있을 뿐만 아니라 많은 기업에서도 Git을 선택해서 사용하고 있습니다. Git은 소스코드의 버전(히스토리)을 편리하게 관리할 수 있도록 도와줍니다. 기본적인 Git 사용법에 대해서 배워보고 향후 Github에 대해서 학습하신다면 개발 협업에 많은 도움을 받으실 수 있습니다. 이 글에서는 터미널에서 Git을 활용하는 내용 위주로 설명합니다.

빅어드민 Git 기초 사용법(이정도는 익혀두자)

1. git 이란 무엇인가요?

git은 소프트웨어 개발에서 소스 코드 관리를 위해 사용되는 분산 버전 관리 시스템(Distributed Version Control System, DVCS)을 말합니다.

여기서 말하는 분산(Distributed)은 버전관리 메인 서버 뿐만 아니라 개발자의 컴퓨터에도 소스코드의 모든 히스토리 정보가 저장되어 있어 온/오프라인 상관없이 어디서든 독립적으로 작업을 진행하고 병합(merge)을 통해 통합할 수 있다는 것을 뜻합니다.

이는 여러 사람이 동시에 개발에 참여하여 각자의 작업 내용이 충돌하지 않도록 관리해 주는 역할도 합니다. git의 핵심 주요 기능은 다음과 같습니다.

git의 주요 기능

  • 버전관리: 파일 변화를 시간에 따라 기록해서, 특정 시점의 버전을 다시 불러오거나 변경 내용을 비교할 수 있습니다.
  • 분산 개발: 로컬 컴퓨터에서 전체 코드베이스의 복사본(리포지토리)을 가지고 작업하므로 인터넷 연결 없이도 개발을 계속할 수 있습니다.
  • 협업: 다수의 개발자가 동일한 프로젝트에 기여할 수 있으며, 각자의 변경 사항을 쉽게 통합할 수 있습니다.

2. git 설치

윈도우의 경우 cmder을 설치 합니다. cmder에는 git이 내정되어 있어 별도 설치가 필요 없습니다. 그리고 git 공식사이트의 download 메뉴에서 OS게 설치 파일을 다운받거나 명령을 실행해서 설치 할 수 있습니다. 설치가 되었다면 아래 명령으로 git의 버전을 확인 해 보세요.

$ git --version
git version 2.34.1

3. Git 초기 설정

git을 설치하고 나면 git 관련 모든 설정은 사용자 계정의 홈디렉토리의 .gitconfig 파일에 저장됩니다. 아래 명령으로 현재 설정된 내용을 확인할 수 있습니다.

$ git config --list

# editor를 사용해서 global 설정을 편집할 수 있다.
$ git config --global -e 

# 텍스트 에디터(vscode)를 사용해서 편집하고 싶을때는 아래와 같이 설정한다.
$ git config --global core.editor "code --wait"
$ git config --global -e

계속해서 사용자와 관련된 설정을 진행해 봅시다.

$ git config --global user.name "username"
$ git config --global user.email "username@useremail.com"
$ git config user.name
username
$ git config user.email
username@useremail.com

$ git config --global core.autocrlf true # 윈도우즈 사용자의 경우
$ git config --global core.autocrlf input # Mac 사용자의 경우

OS마다 줄바꿈의 문자열이 다릅니다. 어떤 OS에서도 오류가 없도록 해기 위해서 core.autocrlf 설정을 합니다.

  • 윈도우의 경우 \r\n (carriage-return + line feed)
  • 맥의 경우 \n (line feed)

윈도우의 경우 core.autocrlf를 true로 설정하면 git에 저장할때 carriage-return(\r)을 제거해서 저장하고, 다시 git에서 가져올 때는 carriage-return(\r)을 붙여서 가져옵니다.

맥에서 core.autocrlf를 input으로 설정하면 git에 저장할때는 carriage-return(\r)을 제거하지만 받아 올때는 별다를 작업을 하지 않습니다.

4. Git 초기화/삭제

git init 명령어를 사용해서 git 초기화할 수 있습니다. git에 대한 모든 정보는 .git 디렉토리 안에 저장됩니다. 이 .git 디렉토리를 삭제하면 이 디렉토리는 git 프로젝트가 아니게 됩니다.

$ mkdir -p workspace/git-test && cd workspace/git-test
$ git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
Initialized empty Git repository in /home/dk/workspace/git-test/.git/
$ ls -al
total 12
drwxr-xr-x 3 dk dk 4096 May 13 15:57 ./
drwxr-xr-x 3 dk dk 4096 May 13 15:57 ../
drwxr-xr-x 7 dk dk 4096 May 13 15:57 .git/

$ rm -rf .git

5. Git 명령어 단축키

git status 명령으로 git의 상태를 확인할 수 있습니다. 이런 명령은 alias 를 설정해서 짧게 단축해서 사용할 수 있습니다. 그리고 git 명령에서 사용가능한 옵션을 확인하려면 -h 옵션을 사용합니다.

$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)
$ git config --global alias.st status
$ git st
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)
$ git config -h
usage: git config [<options>]

Config file location
    --global              use global config file
    --system              use system config file
    --local               use repository config file
    --worktree            use per-worktree config file
    -f, --file <file>     use given config file
    --blob <blob-id>      read config from given blob object

Action
    --get                 get value: name [value-pattern]
    --get-all             get all values: key [value-pattern]
    --get-regexp          get values for regexp: name-regex [value-pattern]
    --get-urlmatch        get value specific for the URL: section[.var] URL
    --replace-all         replace all matching variables: name value [value-pattern]
    --add                 add a new variable: name value
    --unset               remove a variable: name [value-pattern]
    --unset-all           remove all matches: name [value-pattern]
    --rename-section      rename section: old-name new-name
    --remove-section      remove a section: name
    -l, --list            list all
    --fixed-value         use string equality when comparing values to 'value-pattern'
    -e, --edit            open an editor
    --get-color           find the color configured: slot [default]
    --get-colorbool       find the color setting: slot [stdout-is-tty]

Type
    -t, --type <>         value is given this type
    --bool                value is "true" or "false"
    --int                 value is decimal number
    --bool-or-int         value is --bool or --int
    --bool-or-str         value is --bool or string
    --path                value is a path (file or directory name)
    --expiry-date         value is an expiry date

Other
    -z, --null            terminate values with NUL byte
    --name-only           show variable names only
    --includes            respect include directives on lookup
    --show-origin         show origin of config (file, standard input, blob, command line)
    --show-scope          show scope of config (worktree, local, global, system, command)
    --default <value>     with --get, use default value when missing entry

6. Git workflow 이해하기

vi 에디터에 명령 모드(Command Mode), 입력 모드(Insert Mode) 그리고 명령행 모드(Command-line Mode) 이렇게 세 가지 모드가 있는 것 처럼 Git에도 세 가지 작업 환경이 있습니다.

  • Working directory: 프로젝트의 현재 버전의 파일들이 실제로 저장되어 있는 로컬 파일 시스템입니다. 개발자가 실제로 파일을 수정하는 곳입니다. 이곳에서의 변경 사항은 아직 git에 의해 추척되지 않습니다. (git add)
  • Staging area: 커밋(commit)할 파일들을 준비하는 영역입니다. Working directory에서 변경된 파일을 커밋하기 위해 먼저 Staging area에 추가해야 합니다. (git commit)
  • .git Repository: 프로젝트 변경 사항(버전)을 저장하는 데이터베이스입니다. 개발자가 Staging area에서 변경 사항을 커밋하면 이 정보가 리포지토리의 로컬 데이터베이스로 저장됩니다. 리포지토리는 프로젝트의 모든 버전의 이력을 포함하며, 여기서 이전 상태로 롤백하거나 변경 이력을 조회할 수 있습니다. (git checkout, git push, git pull)
$ echo "Hello World" > a.txt
$ echo "Hello World" > b.txt
$ echo "Hello World" > c.txt

# git 상태를 확인합니다.
$ git st # git status
git st
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        a.txt
        b.txt
        c.txt

nothing added to commit but untracked files present (use "git add" to track)

# untracked 파일이 3개 있습니다. 파일을 Staging area로 옯깁니다.
$ git add a.txt
$ git st
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   a.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        b.txt
        c.txt

$ git add *.txt # 혹은 git add .
$ git st
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   a.txt
        new file:   b.txt
        new file:   c.txt

# a.txt 파일을 다시 수정합니다.
$ echo "oops..." >> a.txt
$ git st
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   a.txt
        new file:   b.txt
        new file:   c.txt

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:   a.txt

$ git add a.txt
$ git st
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   a.txt
        new file:   b.txt
        new file:   c.txt

# Staging area에서 working directory(untracked)로 옯깁니다.
$ git rm --cached *
rm 'a.txt'
rm 'b.txt'
rm 'c.txt'
$ git st
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        a.txt
        b.txt
        c.txt

nothing added to commit but untracked files present (use "git add" to track)
$ 

7. gitignore 활용하기

특정 파일이나 디렉토리를 git에서 추적하지 않도록 하고 싶은경우 .gitignore 파일을 작성합니다. 이 파일을 활용하여 민감한 정보, 빌드시 생성되는 파일, 시스템 특정 파일 등이 git 리포지토리에 실수로 추가되는 것을 방지할 수 있습니다. 예를 들어 컴파일된 파일, 로그 파일, 설정 파일 등 개발 과정에서 자동으로 생성되거나 각 개발자마다 다를 수 있는 파일들을 .gitignore에 추가함으로써 개발환경을 깔끔하게 유지하고 필요하지 않은 파일이 버전 관리되는 것을 방지할 수 있습니다.

$ echo "*.log" > .gitignore
$ echo ".env" >> .gitignore
$ echo "build/" >> .gitignore
$ git add *.txt
$ git st -s
A  a.txt
A  b.txt
A  c.txt
?? .gitignore
$ echo "added" >> a.txt
❯ git st -s
AM a.txt
A  b.txt
A  c.txt
?? .gitignore

8. git diff 명령어 활용하기

$ git diff
diff --git a/a.txt b/a.txt
index 5598e93..89786d3 100644
--- a/a.txt
+++ b/a.txt
@@ -1,2 +1,3 @@
 Hello World
 oops...
+added

(1) diff –git a/a.txt b/a.txt

  • 이 라인은 diff 명령이 두 버전의 파일을 비교하고 있다는 것을 나타냅니다. 여기서 a/a.txt와 b/a.txt는 각각 변경 전과 변경 후의 파일 경로를 나타냅니다. 이는 Git이 내부적으로 사용하는 표기법입니다.

(2) index 5598e93..89786d3 100644

  • 이 라인은 파일의 변경 전과 후의 SHA-1 해시 값을 보여줍니다. 5598e93은 수정 전의 커밋 해시이고, 89786d3은 수정 후의 커밋 해시입니다. 100644는 파일의 퍼미션을 나타내는데, 일반 파일에 대한 표준 Unix 퍼미션을 의미합니다.

(3) — a/a.txt

  • 이 라인은 비교 대상인 원본 파일(a/a.txt)을 나타냅니다. —는 이후에 나오는 내용이 삭제되거나 변경된 부분의 원본을 보여줍니다.

(4) +++ b/a.txt

  • 이 라인은 변경된 파일(b/a.txt)을 나타냅니다. +++는 이후에 나오는 내용이 추가되거나 변경된 부분을 보여줍니다.

(5) @@ -1,2 +1,3 @@

  • @@는 hunk의 시작을 나타내는 기호입니다. -1,2 는 변경 전의 상태를 설명합니다. 원본 파일(’-’)에서 변경이 시작되는 첫 번째 줄(‘1’)의 번호를 의미합니다. 콤마 이후 숫자(‘2’)는 변경 전의 범위를 나타내며, 이 경우 원본에서 변경되거나 비교된 내용이 2줄임을 의미합니다. +1,3 은 변경 후를 설명합니다. 수정된 파일(’+’)에서 변경이 시작되는 첫 번째 줄(‘1’)의 번호를 의미합니다. 콤마 이후 숫자(‘3’)는 변경 후의 번위를 나태내며, 이 경우 수정후 3줄이 되었음을 의미합니다.

(6) +added

  • + 기호는 해당 줄이 추가된 것을 의미합니다.
$ git diff -h # git diff 옵션 확인
$ git config --global -e

# 아래 내용 추가
[diff]
    tool = vscode
[difftool "vscode"]
    cmd = code --wait --diff $LOCAL $REMOTE

$ git difftool # vscode를 실행해서 diff 확인

Viewing (1/1): 'a.txt'
Launch 'vscode' [Y/n]? y

9. git commit

이제 Staging area에 있는 내용을 리포지토리에 저장합니다.

$ git commit
Title: first commit
Description: description

[master (root-commit) e9f783a] Title: first commit Description: description
 3 files changed, 4 insertions(+)
 create mode 100644 a.txt
 create mode 100644 b.txt
 create mode 100644 c.txt

$ git log
commit e9f783a9d93b781a95c4e0535538e95930df619c (HEAD -> master)
Author: $$$$ <$$$$@bigadmin.org>
Date:   Tue May 14 14:23:07 2024 +0900

    Title: first commit
    Description: description

$ echo "aaa" >> b.txt
$ git st
$ git add b.txt
$ git commit -m "second commit"
$ git log
commit dc51f315d740150f905b4f34d268043305051c9b (HEAD -> master)
Author: $$$$ <$$$$@bigadmin.org>
Date:   Tue May 14 14:29:06 2024 +0900

    second commit

$ echo "bbb" >> c.txt
$ git commit -am "Third commit"
$ git log
commit 486c813116a740ed7f667f17f6a8e07c6481af7d (HEAD -> master)
Author: $$$$ <$$$$@bigadmin.org>
Date:   Tue May 14 14:31:24 2024 +0900

    Third commit

.git 리포지토리는 history 저장소입니다. 이 히스토리 저장소에 전체 프로젝트를 하나의 commit으로 저장하는 것은 의미가 없습니다. 각 기능을 세분화 해서 작은 조각 단위로 저장하는 것이 유용합니다. 그리고 의미 있는 이름을 지정해서 저장하는 것이 중요합니다. 하나의 commit에는 하나의 작업 내역만 포함되도록 하는 것이 정신건강에 좋습니다.

10. 마무리

CLI를 통해 Git을 활용하는 기본적인 방법들에 대해 살펴보았습니다. 실제로 사용하면서 점차 노하우를 쌓아가시길 바랍니다. Git은 개발 과정을 보다 효율적으로 만들어주는 강력한 도구이니, 이 기회에 많은 실험을 해보시고 좋은 적용 사례들을 익혀 가시기를 권해 드립니다.

Leave a Comment