Git의 기본

Polynomeer·2020년 5월 4일
0
post-thumbnail

Git

안하던 일을 시작한다던가, 안 쓰던 도구를 처음 사용하는 것은 매우 힘든 일이다. 하지만 안 써서 오는 불편함이 매우 커졌을 때, 그 진입의 문턱은 크게 문제가 되지 않는다. git도 마찬가지로, 소스 코드와 프로젝트의 관리가 매우 불편해지고, 지난 프로젝트를 찾는 것이 아주 어려워져서 비로소 그 필요성을 매우 절실하게 느끼게 되었다.

git은 버전 관리 시스템인데, 마치 타임머신과도 같다. git을 통해서 과거로의 이동이 가능하고, 심지어 과거를 변경함으로써 또 다른 현재(마치, 평행세계?)를 만들 수도 있다.

190520            200301            report_final1.txt report_fixed2.txt
190712            200401            report_final2.txt report_fixed3.txt
190817            report.txt        report_fixed.txt
191118            report_final.txt  report_fixed1.txt

  • local은 우리가 사용하고 있는 컴퓨터에 해당한다.
  • remote는 원격 저장소이다.
  • repo는 repository의 준말로서 저장소를 의미한다.

working directory

사용자가 지금 사용하고 있는 컴퓨터에 있는 작업 디렉토리를 말한다.

각자의 컴퓨터에서 어떤 파일들을 만들거나, 파일의 내용을 수정하였거나 등등 각자 어떠한 작업을 한 그 디렉토리이다.

아직 버전으로 만들어지기 전 단계에 해당한다.

staging area

git은 파일이 추가되고, 삭제되고, 수정되는 등 변경사항을 모두 추적하므로 전부 파악할 수 있다.

그리고 사용자는 변경사항이 있는 파일들 중 최종적으로 다음 단계인 local repo에 저장할 파일들을 설정할 수 있고, 사용자가 설정한 파일들이 staging area에 임시적으로 저장된다.

예를 들어, 내가 파일1과 파일2를 수정했다. 그런데 파일2는 그대로 두고, 파일1만 다음 local repo에 저장하고 싶다. 그럴 때 파일1만을 이 과정에서 staging area에 등록하면 깃은 파일1에 대해서는 추적을 시작하게 되고, 파일2는 추적을 하지 않게 된다.

버전을 만들려고 하는 파일들이 이에 해당한다.

local repo (repository)

local repo는 전 단계인 staging area의 파일들을 최종적으로 우리 컴퓨터에 저장하는 저장소이다.
local repo는 다음 단계인 remote repo에 저장하기 전 단계이다.
remote repo는 원격 저장소라는 의미이고, github 저장소가 이에 해당한다.
즉, local repo는 원격 저장소에 저장하기 전에 마지막으로(최종적으로) 우리 컴퓨터에 저장되는 저장소이다.

만들어진 버전 파일들이 포함된다.

정리

지금까지 과정을 정리하여 보면, 우리는 working directory에서 파일들을 수정하였고, 그 파일들 중 우리가 원하는 파일들을 임시적으로 staging area에서 파일들을 저장하였다.

그리고 그 staging area에 있는 파일들을 대상으로 최종적으로 local repo에 저장하였다.

local repo에 있는 파일들을 remote repo에 올리면 끝난다.

원격 저장소에서 우리의 작업 공간으로 가져오는 과정은 위에 설명했던 순서의 역순으로 생각하면 된다.

다만, staging area는 개념 자체가 working directory의 임시 파일들을 모아놓은 것이므로 역순으로 가져올 때에는 보통은 거치지 않는다.

참고 자료 :
https://git-scm.com/book/ko/v2
https://opentutorials.org/module/3963/24425


1. Git 기본명령어

git init

• 참고 링크 : https://git-scm.com/docs/git-init

git init 은 빈 git repository를 생성하거나 이미 존재하는 것을 초기화 한다.

git init [options] [directory]

현재 디렉터리를 git을 사용할 수 있도록 초기화

~/git-test
❯ git init .
Initialized empty Git repository in /Users/user_name/git-test/.git/

이렇게 하면 현재 디렉터리를 git repository로 지정하게 된다. 그리고 결과적으로 .git 이라는 숨김폴더가 생성된다. 이 안에는 각종 git의 설정정보가 들어있다.

~/git-test master
❯ ls -al
total 0
drwxr-xr-x   3 ham  staff   96 May  4 11:41 .
drwxr-xr-x  10 ham  staff  320 May  4 11:40 ..
drwxr-xr-x  10 ham  staff  320 May  4 11:41 .git

git config

해당 repository나 global 옵션으로 (전역적으로) git에 대한 설정을 할 수 있다.

• 참고 링크 : https://git-scm.com/docs/git-config

git config --global user.name "본인 이름"
git config --global user.email "본인 이메일 주소"

--global 옵션을 붙이면 전역적으로 지정하며, 이 옵션을 제외하면 해당 repository에만 해당 설정이 적용된다.

git config --global core.editor "에디터 이름"

해당 에디터를 git의 기본 에디터로 설정할 수 있다.

git config --list

list옵션으로 config파일에 설정된 모든 변수와 그 세팅된 값을 볼 수 있다.

...
user.name="user's name"
user.email="user's e-mail address"

git add

• 참고 링크 : https://git-scm.com/docs/git-add

인덱스에 파일 콘텐츠를 추가한다. 버전으로 만들기 위해서 working diretory에서 staging area로 올리는 명령이다.

git add [options] [path]

git add .을 입력하면 현재 working directory에 있는 모든 파일의 변경사항을 한꺼번에 staging area에 올릴 수 있다.

~/git-test master
❯ vi test1.txt
~/git-test master*
❯ cat test1.txt
1
~/git-test master*
❯ git status
On branch master

No commits yet

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

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

아직 staging area에 올라가지 않았으므로, untracked file로 인식된다.

~/git-test master*
❯ git add test1.txt

git add 명령어로 test1.txt를 staging area에 올리면

~/git-test master*
❯ git status
On branch master

No commits yet

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

commit 할 수 있는 변경사항이 추적된다.

git status

git status [options] [path]

working tree의 상태를 보여준다. staging area에 어떤 파일이 있는지 commit되었는지에 관한 정보를 볼 수 있다. (index file과 현재 HEAD commit사이의 차이, working tree와 index file 사이의 경로차이를 출력)

~/git-test master*
❯ git status
On branch master

No commits yet

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

현재 git add로 staging area에 test1.txt를 올렸으므로, 해당 파일만 보인다. 아직 commit되지 않았다고 상태를 알려준다.

git commit

• 참고 링크 : https://git-scm.com/docs/git-commit

repository에 변경사항을 기록한다. staging area에서 repository로 버전을 제출한다는 의미로 생각하면 된다.

git commit [options] [path]

그냥 git commit를 하면 staging area에 올라온 모든 변경사항에 대하여 commit하면서 덧붙일 메시지를 입력하는 에디터가 나온다. 여기서 메시지를 입력하고 저장하면 해당 메시지로 commit하게 된다.

 1 COMMIT_EDITMSG                                                       Buffers
 1   Message 1
  1 # Please enter the commit message for your changes. Lines starting
  2 # with '#' will be ignored, and an empty message aborts the commit.
  3 #
  4 # On branch master
  5 #
  6 # Initial commit
  7 #
  8 # Changes to be committed:
  9 #       new file:   test1.txt
 10 #

-m <msg>

주어진 메시지를 commit메시지로 사용한다. 여러개의 -m 옵션이 주어지면, 그 값을(문자열을) 모두 구분된 단락으로 이어붙인다. 이 옵션을 통해 위의 과정을 생략하고 바로 간단한 메시지를 포함하여 commit할 수 있다.

~/git-test master*
❯ git commit -m "Message 1"

이렇게 해도 동일한 결과를 얻을 수 있다.

이제 git status로 commit의 결과를 확인해보면,

~/git-test master 40s
❯ git status
On branch master
nothing to commit, working tree clean

이미 commit되었기 때문에 working tree가 출력되지 않는다.

-a
a는 add를 의미한다. 이 옵션을 통해서 매번 add해줄 필요가 없이 한번에 commit할 수 있다. 단, 최초의 git add는 이 옵션이 적용되지 않기때문에, 반드시 개별적으로 해주어야 한다. 이는 -a옵션으로 불필요한 파일들까지 add되는 것을 방지하기 위함이다.

~/git-test master*
❯ git commit -am "Message 3"
[master 393aad9] Message 3
 1 file changed, 1 insertion(+)

git log

• 참고 링크 : https://git-scm.com/docs/git-log

commit 로그를 보여준다.

git log [options] [revision range] [path]

commit 로그를 보여준다. 보통은 -p 옵션만 붙여서 commit 로그를 perl형식으로 출력한다.

-p

출력 패턴을 perl-compatible reuglar expressions로 한정하여 보여준다.

~/git-test master
❯ git log -p

해당 repository에서 명령어를 입력하면,

commit b9d03cccb762cfb47987d6e0fced56bcf696ee2d (HEAD -> master)
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 12:23:17 2020 +0900

    Message 1

diff --git a/test1.txt b/test1.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/test1.txt
@@ -0,0 +1 @@
+1
(END)

이처럼 파일의 변경사항과 간략한 commit 메시지가 출력된다. q를 누르면 해당화면에서 빠져나올 수 있다.

~/git-test master
❯ vi test1.txt

간단히 2라는 내용을 덧붙여서 파일을 수정한 뒤, 다시 git status로 staging area의 상태를 확인해보면

~/git-test master
❯ git status
On branch master
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:   test1.txt

no changes added to commit (use "git add" and/or "git commit -a")

commit은 되지 않았지만 staging area에 남아있는 변경사항이 추적된다.(이미 git add로 test1.txt가 staging area에 추가되었으므로 추적된다.)

~/git-test master
❯ git add test1.txt

변경사항이 생긴 test1.txt을 다시 git add 해주면

~/git-test master
❯ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   test1.txt

이렇게 test1.txt는 staging area에 올라가고, commit할 수 있는 상태가 된다.

~/git-test master
❯ git commit -m "Message 2"
[master 5de5160] Message 2
 1 file changed, 1 insertion(+)

이제 staging area의 모든 변경사항을 commit 한 다음

~/git-test master
❯ git log -p

git log 명령어로 commit 기록을 보면 아래와 같이 commit할때 입력한 메시지와 간단한 변경사항이 포함된 로그가 출력된다.

commit 5de5160f3750474154a6598a26595c472ec37f44 (HEAD -> master)
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 14:21:41 2020 +0900

    Message 2

diff --git a/test1.txt b/test1.txt
index d00491f..1191247 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1 +1,2 @@
 1
+2

commit b9d03cccb762cfb47987d6e0fced56bcf696ee2d
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 12:23:17 2020 +0900

    Message 1

diff --git a/test1.txt b/test1.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null

2. Git 시점변경

여러 개의 파일을 버전 관리

~/git-test master
❯ vi test1.txt

먼저, test1.txt의 내용을 1 2 3 으로 수정하고, 같은 working directory에 test2.txt라는 새로운 파일을 생성한다.

~/git-test master
❯ vi test2.txt

그리고 git status로 staging area의 상태를 확인해보면

~/git-test master
❯ git status
On branch master
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:   test1.txt

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

no changes added to commit (use "git add" and/or "git commit -a")

test2.txt는 한 번도 git add하지 않았으므로 Untracked files 라고 표시된다. 즉, 변경사항을 추적하지 못하는 상태이다. 반면에, test1.txt는 이미 한번 git add 한 적이 있으므로 변경사항은 추적된다. 하지만 변경사항이 staging area에는 아직 올라가지 않은 상태이므로 Changes not staged for commit라는 문구가 표시된다. 즉, commit을 하기위해서 변경사항이 있을때 마다 git add를 해주어야 한다는 것이다.

최초로 staging area에 올리는 것이나 두 번째 이상에서 변경사항을 staging area에 올리는 방법은 같다.

~/git-test master
❯ git add test1.txt

~/git-test master
❯ git add test2.txt

~/git-test master
❯ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   test1.txt
	new file:   test2.txt

두 개의 파일을 각각 git add 해주고 git status로 확인하면, 새로운 파일의 생성과 기존 파일의 변경사항 모두가 staging area에 올라가고 commit할 준비가 완료되었다.

~/git-test master
❯ git commit -m "Message 3"
[master 0713e2a] Message 3
 2 files changed, 2 insertions(+)
 create mode 100644 test2.txt

~/git-test master
❯ git status
On branch master
nothing to commit, working tree clean

commit을 해주면 staging area에 더 이상 변경사항이 남아있지 않은 것을 확인할 수 있다.

git log --stat

--stat옵션은 파일 별 변경사항을 볼 수 있게 해준다.

~/git-test master
❯ git status
commit 0713e2ae1f233f01f5c541950461fe5fb0a53f7c (HEAD -> master)
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 14:38:05 2020 +0900

    Message 3

 test1.txt | 1 +
 test2.txt | 1 +
 2 files changed, 2 insertions(+)

commit 5de5160f3750474154a6598a26595c472ec37f44
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 14:21:41 2020 +0900

    Message 2

 test1.txt | 1 +
 1 file changed, 1 insertion(+)

commit b9d03cccb762cfb47987d6e0fced56bcf696ee2d
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 12:23:17 2020 +0900

    Message 1

로그에서 볼 수 있듯이 git은 하나의 작업 또는 버전에서 여러 개의 파일을 그룹핑 할 수 있다는 장점이 있다.

git diff

commit된 것들 사이에서 또는 commit과 working tree사이에서의 변경사항을 보여준다.

git diff [option] [path]

~/git-test master
❯ cat test1.txt
1
2
3

이 파일의 내용을 일부 수정한다.

~/git-test master
❯ vi test1.txt

~/git-test master* 18s
❯ cat test1.txt
1
2
three

3을 three로 변경하였다.

~/git-test master* 13s
❯ git diff

그리고 git diff로 변경사항을 바로 확인할 수 있다.

diff --git a/test1.txt b/test1.txt
index 01e79c3..6b1f642 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1,3 +1,3 @@
 1
 2
-3
+three

-3은 3이 지워졌다는 의미이고, +three는 three라는 내용이 추가되었다는 뜻이다.

git checkout

git-checkout은 브랜치를 변경하거나 working tree 파일들을 복구할 때 사용된다. 이는 과거로 돌아가는 타임머신의 역할을 수행하는 것이다.

git checkout [options] [branch/commit]

commit c836acaa9ec45c674bb3d87558def3f26095dd14 (HEAD -> master)
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 15:06:00 2020 +0900

    Message 4

diff --git a/test1.txt b/test1.txt
index 01e79c3..6b1f642 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1,3 +1,3 @@
 1
 2
-3
+three

commit 0713e2ae1f233f01f5c541950461fe5fb0a53f7c
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 14:38:05 2020 +0900

    Message 3

diff --git a/test1.txt b/test1.txt
index 1191247..01e79c3 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1,2 +1,3 @@
 1
 2
+3
diff --git a/test2.txt b/test2.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/test2.txt
@@ -0,0 +1 @@
+1

commit 5de5160f3750474154a6598a26595c472ec37f44
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 14:21:41 2020 +0900

    Message 2

diff --git a/test1.txt b/test1.txt
index d00491f..1191247 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1 +1,2 @@
 1
+2

commit b9d03cccb762cfb47987d6e0fced56bcf696ee2d
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 12:23:17 2020 +0900

    Message 1

diff --git a/test1.txt b/test1.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/test1.txt
@@ -0,0 +1 @@
+1

로그에서 HEAD는 현재 시점을 가리키는 포인터로 생각할 수 있다. 그리고 master는 가장 최신의 시점의 commit을 나타낸다.

git-checkout을 통해 두 번째 commit으로 돌아가보았다. git checkout에 해당 commit의 해시값을 붙여넣게 하면 된다.

~/git-test master*
❯ ls
test1.txt test2.txt

checkout 하기 전에는 test2.txt까지 디렉터리에 있는 것을 확인할 수 있다.

~/git-test master
❯ git checkout 5de5160f3750474154a6598a26595c472ec37f44
Note: switching to '5de5160f3750474154a6598a26595c472ec37f44'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 5de5160 Message 2

checkout을 하면 2번째 commit으로 돌아간 것이므로 test2.txt파일은 없는 상태인 것을 확인할 수 있다.

~/git-test master~2
❯ ls
test1.txt

이때의 로그를 다시 확인해보면

~/git-test master~2
❯ git log -p

HEAD는 2번쨰 commit을 가리키고 있다. 하지만 master는 여전히 존재한다.

commit 5de5160f3750474154a6598a26595c472ec37f44 (HEAD)
Author: Ham <polynomeer@gmail.com>
Date:   Mon May 4 14:21:41 2020 +0900

    Message 2

diff --git a/test1.txt b/test1.txt
index d00491f..1191247 100644
--- a/test1.txt
+++ b/test1.txt
@@ -1 +1,2 @@
 1
+2

commit b9d03cccb762cfb47987d6e0fced56bcf696ee2d
Author: Ham <polynomeer@gmail.com>
Date:   Mon May 4 12:23:17 2020 +0900

    Message 1

diff --git a/test1.txt b/test1.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null

이 상태에서 다시 git checkout master을 입력하면 가장 최신의 상태로 돌아가게 된다.

~/git-test master~2
❯ git checkout master
Previous HEAD position was 5de5160 Message 2
Switched to branch 'master'

돌아간다음 로그를 보면

commit c836acaa9ec45c674bb3d87558def3f26095dd14 (HEAD -> master)
Author: polynomeer <polynomeer@gmail.com>
Date:   Mon May 4 15:06:00 2020 +0900

    Message 4
...

이처럼 HEAD가 다시 master를 가리키는 것을 확인할 수 있다.

git reset

git-reset은 현재의 HEAD를 특정 상태로(해당 버전으로) 리셋해주는 명령어이다.

git reset [option] [path]

--hard

git revert

git-revert는 되돌리기의 기능을 하는 명령어이다. 반드시 역순으로 차례대로 진행해야 한다.

profile
어려운 문제를 어렵지 않게.

0개의 댓글