Posts git 기초 명령어 사용법에 대해 알아보자(git init, git add, git commit)
Post
Cancel

git 기초 명령어 사용법에 대해 알아보자(git init, git add, git commit)

생활코딩 - 지옥에서 온 Git을 공부하며 정리한 내용입니다.

git을 이용해서 버전관리를 시작해보자. git에서 주로 사용되는 명령어들 중에서 이번 포스팅에서는 다음의 내용들을 다루어보고자 한다.

또한 git add, git commit, git status의 작동원리에 대해서 함께 소개하고자 한다. 작동원리는 다소 초심자가 이해하기에는 다소 어려운 내용일 수 있으므로, 해당 내용은 건너뛰고 나중에 필요할 때 다시 읽어보는 것을 추천한다.

1. git init : 저장소 만들기

Git을 로컬 저장소에서 생성하기 위해서 Git Bash 프롬프트에서 git init을 입력하면 .git이라는 파일이 생성된다. 이 파일은 버전에 대한 정보를 담고 있는 파일이며, 평소에는 숨김 파일로 설정되어 눈에 보이지 않는다. 그리고 파일이 추가/삭제 되거나, 파일의 내용이 변경되는 것을 자동으로 감지할 수 있다. 해당 파일을 삭제하면 이전 버전에 대한 정보가 날아가므로 주의해야 한다.

git initinitialize(초기화)를 의미한다. 이 명령어를 실행하기 전까지 폴더는 내 컴퓨터에만 존재하는 세상 평범한 폴더였지만, 이제는 버전 관리가 가능한 특별한 폴더가 된다.

참고로 Github의 저장소 구조를 나타내면 아래의 사진과 같다.

크게는 로컬 저장소원격 저장소 2가지로 나뉘는데, 쉽게 말해서 로컬 저장소은 내 컴퓨터에 저장된 폴더를 의미하고, 원격 저장소Github 서버에 올라간 폴더를 의미한다.

주의할 점은 실시간으로 폴더 내의 변화를 감지해서 원격 저장소와 연동 하는 것이 아니다. 지속적으로 변화하는 파일의 상태를 실시간으로 서버와 지속적으로 연결해서 비교하는 것은 네트워크 자원을 소모하는 낭비일 뿐이며, 파일 버전 관리의 의미가 없어지게 된다.

누가 이렇게 생각을 하겠냐마는, 부끄럽게도 처음에 내가 이렇게 생각했었다.

앞으로 자세히 설명하겠지만, git add - git commit - git push 순으로 명령어를 입력하면 Github에 내 파일들이 올라가는 것을 볼 수 있다.

2. git add : git이 관리할 대상으로 파일 등록

git add는 작업 디렉토리 상의 변경 내용을 스테이징 영역에 추가하기 위해 사용하는 명령어이다.

예를 들어, hello.txt를 해당 폴더에 처음 생성하고 prompt에서 git status를 입력하면 파일의 상태를 다음과 같이 확인할 수 있다.

git_status

빨간색으로 표시된 파일이 현재 Untracked 상태라는 것인데, git이 해당 파일에 대한 어떠한 정보도 가지고 있지 못하다는 것을 의미한다.

git_add

명령어가 실행되면 스테이징 영역으로 넘어가서 Tracked로 상태가 바뀌고, 초록색으로 표시되는 파일은 현재 커밋을 기다리는 단계임을 알려준다.

사용법

  1. git add . : 현재 디렉토리의 모든 변경 내용을 스테이징 영역으로 넘길 때 .을 인자로 넘긴다. 개인적으로 1번을 제일 많이 사용한다.
  2. git add -A : 작업 디렉토리 내의 모든 변경 내용을 모두 스테이징 영역으로 넘긴다. git add .와는 달리 현재 디렉토리를 기준으로 상위 폴더의 변경 내용까지 포함한다.

    \---one
      | one.txt
      |
      +---two
      |   two.txt
      |
    
    

    만약, 위와 같이 one폴더 아래 two 폴더가 있다고 했을때, one폴더에서 three.txt를 생성하고 two 폴더에서 git add -A를 실행하면 상위 폴더에서 생성된 three.txt 파일도 스테이징 영역으로 넘긴다.

  3. git add 파일/디렉토리 경로 : 작업 디렉토리의 변경 내용의 일부만 스테이징 영역에 넘기고 싶을 때는 수정한 파일이나 디렉토리의 경로를 인자로 넘긴다.

작동원리

git add는 현재 디렉토리에서 생성된 파일을 스테이지 영역(커밋 대기상태)에 추가하는 역할을 한다.

[t1.txt]
a

t1.txt에 위와 같은 내용으로 저장을 하고, .git 폴더 내부를 살펴보자.

git add(1)

git add를 실행하면 .git폴더 내부에는 위와 같이 index파일과 objects폴더 아래에 파일이 하나 생긴다. 하나씩 살펴보자면 다음과 같다.

  • index : 현재 스테이징 영역에 존재하는 파일을 의미한다. 즉, 커밋을 대기하는 상태인 파일들의 목록이다.
  • objects : 스테이징 영역에 올라온 파일에 대한 내용이 생성되거나 커밋 내용이 생성되는 객체 폴더이고, 하위 폴더에는 각각의 고유한 문자열로 저장이 된다.

    • 길이가 2인 하위 디렉토리가 생성되며, 이 디렉토리 안에 파일의 내용을 SHA1 알고리즘으로 해석한 해시값이 파일명으로 생성된다. (SHA1으로 해시값을 만들어보고 싶다면 SHA1-Online에 접속하여 확인해보자.)

    git add(2)

    • 본문에 a라고 입력하고 저장하면, git 내부적으로 내용을 압축하고 해시값을 계산을 한다. 이 글을 보시는 분들도 똑같이 내용을 입력하고 git add를 수행하면 사진과 똑같은 해시값을 얻게 될 것이다.

    • git에서는 해당 파일에 대한 고유한 해시값을 폴더명(2글자) + 내용 해시값을 합쳐서 인식을 한다.

    git add(3)

    • 그래서 index파일에서 링크가 된 해시값을 클릭하면 f1.txt에 대한 내용이 담긴 objects폴더 내부의 파일을 볼 수 있다.

    • 즉, index는 스테이징 영역에 올라온 파일들을 해시코드를 통해 추적을 할 수 있다. C언어에서 사용하는 포인터와 비슷한 원리라고 생각할 수 있다.

다음으로 f2.txt를 아래와 같이 생성하고 git add를 실행해보자.

[f2.txt]
z

git add(4)

내용에 따라 해시값이 달라지므로 당연히 f1.txt와 해시값이 고유하게 구분이 된다.

그러면 똑같은 내용의 파일을 복사한다면 git은 어떻게 인식을 할까? f1.txt를 복사해서 f3.txt로 만들고, git add를 실행하면 다음과 같은 결과가 나온다.

git_add(5)

f1.txtf3.txt는 파일이름이 다르지만, 내용이 똑같아서 같은 해시값으로 오브젝트 파일이 생성된다.

즉, 이름이 다른 파일이 5억개가 있어도 내용이 동일하다면 같은 오브젝트 파일이라는 것이다. 그래서 index에서는 다른 파일명들은 인식하지만, 모두 같은 오브젝트 파일이기 때문에 파일 내용에 대한 중복을 제거할 수 있다.

git add(6)

git status : 파일의 상태를 조회

이 명령어는 git add와 주로 함께 사용된다. 실행 결과는 크게 Untracked, Tracked, Modified, Unmodified 4가지이고, 현재 파일의 상태를 나타낸다.

  1. 처음 생성하면 Untracked 상태인데, 파일을 git add로 스테이징 영역으로 옮기면 Tracked 상태가 된다.
  2. commit을 통해 현재 버전에 대한 이력을 저장했다면, 자동으로 Unmodified 상태로 변경이 된다.
  3. commit이 완료된 파일이 수정된다면 Modified로 변경된다.
  4. Modified 상태의 파일을 다시 git add로 스테이징 영역에 올린다. 즉, 한번 커밋된 파일이 수정되면 무조건 다시 git add부터 입력해주어야 한다는 것이다.
  5. 만약 commit이 완료된 파일을 삭제하게 되면 해당 파일은 Untracked 상태가 되어 git의 관리 대상에서 제외된다.

git status의 원리

index 파일에 담긴 파일 정보와 현재 Wokring Directory에 있는 파일을 비교하여 새로운 파일이 추가되었는지, 기존의 파일이 수정 또는 삭제되었는지 판단한다.

git status

이전 커밋의 tree에서는 f2.txt에 대한 해시값을 발견할 수 없으므로 git status는 새로운 파일이 생성되었음을 발견한다.

만약 f1.txt파일이 수정되었다면 해당 파일에 대한 해시값이 변경되므로, git status를 실행했을 때 해시값을 비교하여 수정되었다는 것을 감지할 수 있다.

Staging Area

스테이징 영역은 커밋을 대기하는 장소로써, 작업 디렉토리와 Git 저장소 변경 이력 사이의 징검다리 역할을 한다. 작업 디렉토리는 아직 commit할 준비가 안된 변경 내용을 자유롭게 수정할 수 있지만, 스테이징 영역은 commit할 준비가 된 변경 내용이 Git 저장소에 기록되기 전에 대기하는 장소이다. 그래서 git add 명령어를 사용하면 현재 작업 디렉토리에 있는 모든 파일 또는 일부 파일의 변경 내용을 스테이징 영역으로 옮길 수 있다.

3. git commit : 버전 만들기

git commit은 파일 및 폴더의 추가/변경 사항을 저장소에 기록하는 것이다. 즉, 파일(폴더)의 버전이 의미 있는 변화가 발생했다는 것이고, 특정 작업이 완결된 상태로 바뀌었다는 것을 의미한다. 커밋을 할 때는 보통 변경 내역에 대한 상세한 설명을 함께 포함하는데, 이것이 우리가 Github의 레포지토리에서 발견하는 문구이다. 커밋한 내용을 통해 어떤 파일이 언제, 어떻게 변경되었는지 한 눈에 타임라인으로 파악할 수 있다.

git_commit_message

사용법

  1. git commit -m "메세지 내용" : 변경 내역에 대한 메모와 함께 커밋한다.
  2. git commit -am "메세지 내용" : git addgit commit을 동시에 수행한다. 단, 이 기능을 사용하기 위해서는 commit이 한 번은 수행되어 있어야 한다.
  3. git commit --amend : 방금 커밋한 메세지를 수정한다.

git commit의 원리

git commit을 수행하면 커밋 메세지에 대한 새로운 객체 파일을 생성하고, 해당 커밋 메세지에는 treeparent가 포함된다.

  • tree : 해당 커밋을 수행한 당시에 스테이지 영역에 있던 파일들의 목록이 담겨있다.
  • parent : 첫 커밋에는 존재하지 않지만, 두 번째 커밋부터는 이전에 실행된 커밋에 대한 정보가 존재한다.
  • blob : 파일의 내용을 담고 있다.

git commit(1)

첫 커밋에서는 parent가 존재하지 않고, tree만 존재한다.

git commit(2)

두 번째 커밋부터는 이전 커밋에 대한 내역이 담긴 parent가 생성된다.

git commit(3)

위의 그림과 같이 각각의 커밋들은 서로 연결이 되있고, 각 커밋들마다 파일 내용에 대한 정보를 담고 있기 때문에 Git을 통한 파일 백업이 가능해진다.

즉, tree라고 하는 정보 구조에 각각의 커밋에 대한 모습을 사진으로 남겨놓는 것이다.

git log : 커밋 내역 확인

git log를 입력하면 아래와 같이 커밋이 완료된 내역들에 대해 조회할 수 있다.

git_log

사용법

  1. git log -p : commit 내역을 한 줄씩 내리면서 확인할 수 있다.
  2. git log diff 커밋코드1..커밋코드2 : 다른 2개의 커밋에 대해서 어떤 파일이 변경되었고, 어떤 코드가 변경되었는지 차이점을 보여준다.

git_diff

위의 사진에서는 git log diff 가장 마지막 커밋..가장 최근 커밋을 입력을 했다. 빨간색이 과거 커밋 내용이고, 파란색이 최근 커밋 내용이다. 로그 메세지를 읽는 방법은 다음과 같다.

1
2
3
4
5
6
1. --- /dev/null : subfolder/test2.txt 라는 파일이 과거에는 없었다는 의미이다.
2. +++ b/subfolder/test2.txt : 해당 파일이 최근 커밋에 추가 되었다는 의미이다.
3. @@ -0,0 +1 @@ : -0,0은 과거 파일을 기준으로 아무 것도 변경된 것이 없다는 것이고, +1은 최근 파일 1개에 1줄이 추가되었다는 것을 의미한다.
   만약 2줄이 추가 되었으면 @@ -0,0 +1,2 @@로 표시될 것이다.
4. +hello this is second folder : "hello this is second folder"라는 내용이 파일에 추가되었다는 것이다.

그렇다면 git add와 git commit은 왜 같이 쓰는 걸까?

여기서 의문이 들 수 있는 점이 git commit만 하면 될 것이지, 왜 굳이 git add를 사용해야 하냐는 것이다.

결론부터 말하자면, 원하는 파일에 대해서만 커밋을 하기 위해서이다.

혼자서 작업을 한다면 큰 문제가 되지 않지만, 큰 프로젝트를 진행하다보면 코드를 많이 수정하는 경우가 생긴다. 커밋을 할 때는 1가지 기능만 수정하는 것이 이상적인데, 개발을 하다보면 어떤 파일은 아직 완료가 안 되어 있기도 하고, 어떤 파일은 올리면 안되는 경우가 생긴다. 또는 커밋 시기를 놓쳐서 각 파일마다 커밋 메세지를 못 남기는 경우가 있을 수 있다.

그래서 git add를 사용하면 원하는 파일만 스테이징 영역에 올려서 선택적인 커밋을 할 수 있게 된다. 그리고 각 파일마다 커밋 메세지를 다르게 남기고 싶은 경우에도 동일하게 적용할 수 있다. (물론 귀찮기 때문에 이렇게는 안하고, 연관된 파일들끼리 묶어서 커밋을 한다.)

This post is licensed under CC BY 4.0 by the author.