본문 바로가기
컴퓨터 & IT (Computer & IT)/Github

[GitHub] Working directory, stage, commit 내용 정리

by Physics 2021. 2. 3.
728x90

아래의 내용들은 『Git 교과서』 내용을 개인적으로 정리한 내용들입니다.


1. Working Directory, Stage, and Repository 

깃은 VCS의 특성 상 저장 공간을 논리적으로 분할한다. 깃에서는 저장 공간을 크게 3가지로 나눈다; 
   • 작업 공간 (Working Directory) 
   • 임시 저장 공간 (Stage) 
   • 실제로 저장하는 공간 (Repository) 

 1) Repository

 Git은 작성한 소스코드 파일의 모든 변경 사항을 관리하며, 파일들의 변경 내역을 저장소 (Repository)에 저장을 한다. 이러한 저장소는 크게 로컬 저장소와 원격 저장소로 나누어진다. 

  (1) 폴더와 깃 저장소
    •깃 저장소는 폴더와 외형적으로 비슷하다.
    •깃 저장소의 내부 구조
      - 깃 저장소에는 숨겨진 폴더(.git)이 존재하며, 해당 폴더에서 버전 관리 시스템 (VCS)에 필요한 파일 변경 이력을 기록한다. 
      - 프로젝트의 모든 변경 이력과 history를 가진 일종의 데이터 베이스와 동일 
      - $ git init 명령어로 생성되는 .git 폴더가 로컬 저장소이다. 
      - .git 디렉토리가 로컬 저장소에 해당한다. 

  (2) 초기화 
    • Git 초기화란? 
        - Git 초기화란, Git 저장소를 생성을 한다는 의미이다.
        - 즉, 이미 존재하는 폴더에 초기화 명령을 사용하여 VCS 관리를 위한 숨겨진 영역 (.git)을 생성하는 작업을 의미한다. 
    • 초기화 명령어: $git init <directory_path> 
       - <directory_path> : 저장소로 사용할 디렉토리의 경로 
       - $git init 명령어는 기본적으로 로컬 저장소를 생성하는 명령어이다. 
       - 디렉토리 경로를 입력하지 않을 시, 현재 작업 중인 디렉토리를 저장소로 초기화한다. 
    ※ 정상적으로 초기화가 되었을 경우 
       - 다음 메시지 출력:  Initialized empty Git repository in <directory_path>
       - 저장소 내에 ".git"이란 숨겨진 디렉토리 생성 
    • .git 디렉토리 
       - 숨겨진 디렉토리이며 저장소에 필요한 모든 정보들이 들어있다.
       - ex) 버전 관리를 한 데이터, 원격 저장소의 주소, etc... 
       - 만약 깃 저장소를 복사하는 경우에는 반드시 .git 디렉토리까지 모두 복사를 해야한다. 

 2) Working Directory 

   • 사용자의 작업 공간으로써, 로컬 저장소에 접근할 수 있으며 실제 파일을 수정하거나 생성하는 공간이다.  
   • 현재 작업 중인 소스코드들을 담고 있으며, 운영체제도 워킹 디렉토리 내부의 파일들만 접근하거나 수정할 수 있다. 
   • 작업 폴더에서 .git 디렉토리를 제외한 나머지 부분
   • 워킹 트리, 워킹 디렉토리, 작업 디렉토리 등으로 불림 
   • 워킹 디렉토리에서는 파일들을 추적(tracked)/비추적(untracted) 상태로 구분한다.  

   ※ tracked/untracked 상태 
   (1) untracked 상태 
      - 저장소 내에서 새로 만들어진 모든 파일들은 untracked 상태로 시작한다. 
      - untracked 상태인 저장소 내의 파일들은 git이 코드 변경 이력을 추적하지 않는다. 
   (2) tracked 상태 
      - tracked 상태의 파일들은 git에 의해서 파일의 변경 이력이 추적된다.  
      - 모든 파일들의 변경 이력을 추적할 경우에는 시스템의 부하가 커지게 된다. 따라서 git에서는 요청받은 파일들만 변경 이력을 추적한다. 
      - 명령어: $git add <file_name> 
        위의 명령어를 이용하면 이름이 <file_name>인 파일을 tracked 상태로 등록*한다. (즉, 파일을 stage 영역으로 등록시킨다.) 

  * 등록이란?
 워킹 디렉토리에 있는 "untracked 상태"의 파일을 추적 가능한 상태(tracked)로 변경하는 것이다. 이때, add 명령어를 사용함으로써, 워킹 디렉토리에 있는 파일을 스테이지 영역으로 복사를 한다. 커밋을 하기 위해선, "등록"이 필수적이며, 스테이지에 등록하지 않은 unstage 파일들은 커밋을 할 수 없다. 주의할 점은 파일을 등록했다고 하여 커밋이 된 것이 아니며, 등록은 커밋을 하기 위한 선행 작업이다. 

   (3) tracked 상태와 untracked 상태는 다음과 같이 총 4가지 상태로 추가적으로 더 세부적으로 상태를 나눌 수 있다. 
     - untracked --> untracked 
     - tracked --> unmodified, modified, staged 

3) Stage

 •스테이지(stage)는 워킹 디렉토리에서 제출된 tracked 상태의 파일들을 관리 및 임시로 저장하는 공간이다. 
 •임시로 저장을 하는 공간의 의미란? 
       - 워킹 디렉토리와 "실제로 저장하고 기록하는 공간" 사이의 임시 공간이다. 
       - 실제로 저장하고 기록하는 공간에서는 스테이지 영역에서의 파일 내용을 기반으로 변경된 차이점 만을 기록한다. 
 •스테이지 영역에서는 파일의 콘텐츠 내용을 직접 가지고 있는 것이 아닌, 커밋하려는 파일의 추적 상태 정보들만 기록한다. 
 •스테이지가 만들어진 이유는 커밋을 빠르게 처리하기 위해서이다. 
 •스테이지 내의 파일들은 stage/unstage 상태로 구분된다. 
 •스테이지 상태 확인 명령어: $git status or  $ git ls-files --stage 

   ※ stage/unstage 상태 
  (1) stage 상태 
      - stage 영역에 들어온 파일들은 모두 tracked 상태의 파일들이다. 
      - stage 영역에서 나간 파일들은 untracked 상태의 파일이다. 
      - 중요: 깃이 변화이력을 기록하기 위해선, 파일의 최종 상태가 반드시 stage 상태가 되어야 한다. 
  
  (2) unstage 상태 
     - 파일 내에 변화가 있을 경우 해당 파일은 unstage 상태가 된다, 
     - 즉, 워킹 디렉토리에서의 파일과 스테이지 영역에서의 파일 간 내용 차이가 존재한다면, 해당 파일은 unstage 상태이다. 
     - 스테이지 영역으로 등록하지 않은 워킹 디렉토리 내의 파일들도 unstage 상태로 생각할 수 있다. (untracked & unstage)

  ※ modified/unmodified 상태 
  Git이 코드의 변화를 기록하기 위해선, 파일의 최종 상태가 stage 상태가 되어야 한다. 하지만, 워킹 디렉토리 내의 파일을 수정하게 되는 경우, 스테이지와 워킹 디렉토리의 파일 내용이 일치하지 않는다. 따라서, 스테이지에서는 modified와 unmodified 상태로 파일의 원본과 수정본을 구분한다. 변경 발생 기준은 '파일이 Stage에 등록되거나 또는 Commit된 시점 이후에 변경 되었는가'이다. 

 (1) modified 상태 
     - 워킹 디렉토리 내의 tracked 상태의 파일을 수정하게 되는 경우, Git의 스테이지는 파일의 상태를 modified 상태로 변경한다. 
     - modified 상태의 파일은 스테이지 영역에서 제외되며 스테이지 영역으로 재등록하기 위해선, $git add 명령어를 다시 사용해야한다. 
 (2) unmodified 상태 
     - 원본 파일
     - tracked 상태이면서 스테이지에서 한번도 수정을 하지 않은 원본을 의미한다. 
     - unmodified 상태에서는 스테이지 영역으로 재등록할 필요가 없다.  
 ※ 스테이지 영역에서는 tracked 상태와 unmodified 상태의 파일들만 존재한다. 
 ※ 워킹 디렉토리에서는 untracked 상태와 modified/unmodified 상태의 파일들이 존재

아래 그림은 working directory와 stage에 대해서 이해한 부분을 그림으로 나타내었다. 

4) 기타 사항 

  (1) 파일 등록 취소: $git rm --cached <file_name> 또는 $git reset <file_name> 
      - tracked 상태의 파일을 untracked 상태/unstage 상태로 변경한다. 따라서, 스테이지 영역에 있던 파일이 워킹 디렉토리로 이동한다. 
      - rm 명령어: 파일을 등록한 후 커밋을 하지 않고 등록을 취소하는 경우에는 rm 명령어를 사용한다.  
      - reset  명령어: 파일을 한번이라도 커밋을 한 경우에는 reset 명령어를 사용하여 등록을 취소한다.  

  (2) 등록한 파일의 이름이 변경되는 경우 
      - 등록한 파일의 이름이 변경되었을 경우, 해당 파일을 별도로 Git에 통보할 필요가 없다.
      - tracked 상태의 파일의 이름이 변경되는 경우 자동적으로 깃에서 추적을 한다. 


2. Commit 

  (1) 커밋이란? 
     • 깃이 코드의 변화를 기록하는 것 
     • 코드의 의미있는 변경 작업들을 저장소에 기록하는 동작 
     • 깃은 코드의 변경 이력과 변경 시점을 커밋으로 기록한다.  

  (2) 깃이 파일을 관리하는 방법 
     • 코드의 새로 변경된 부분만 추출하여 저장한다. 
     • 파일의 이름을 변경하지 않고도 동일한 이름으로 관리가 가능하다.  
     • 시간에 따라 변화되는 부분만을 관리하고 코드가 변화된 시간 순서에 따라 영구적으로 저장한다. 
     • 부모 커밋을 기반으로 변화된 부분만을 이용하여 새로운 커밋을 생성한다. 

1)  커밋과 관련된 사항: Head, Snapshot

  (1) Head
     • Head는 커밋을 가리키는 묵시적 포인터로써, 최종적인 커밋의 작업 위치를 의미한다. (마지막 커밋 위치) 
     • 최소한 한번 이상 커밋을 해야지만 Head가 생성이 된다. 

  (2) Snapshot 
     • Snapshot 방식이란 변경된 파일의 전체를 저장하지 않고, 파일에서 변경된 부분만을 찾아 수정된 내용만 저장하는 방식이다. 
     • Snapshot 방식의 장점: 빠르게 버전의 차이점을 처리하고 용량을 적게 사용한다.
     • Git에서 Snapshot은 Head가 가리키는 커밋을 기반으로 한다.
       즉, Head 커밋과 스테이지 영역으로 등록된 변경된 파일과 내용을 비교한다. 그리고 해당 차이점을 새로운 커밋으로 기록한다. 

2) 파일 상태와 커밋

※ 커밋을 하기 전 선행 작업  
  - $git add 명령어를 통해서 새로 생성한 파일이나 변경한 파일을 stage 영역으로 등록한다.  
  - 커밋을 하기 위해선, 반드시 스테이지 영역으로 등록한 파일에 새로운 변경 사항이 있어야 한다. 변경사항이 없을 경우 커밋이 안된다. 
  - 파일을 수정했어도, stage 영역으로 등록하지 않을 경우, 커밋을 할 수 없다. 

  (1) 커밋 명령어: $git commit 
     commit 도움말 명령어: $git commit -help 
    • 파일 등록과 커밋을 동시에 하는 방법: $git commit -a

  (2) 커밋 메시지
    • 새로운 커밋을 생성할 때, 이전 커밋과의 차이점을 알려주는 메시지를 작성해야한다. 이런 메시지를 커밋 메시지라 한다. 
    • 커밋 메시지의 작성 요령 
        - 요약 내용과 상세 내용을 분리하여 기록한다. 

        - 첫번째 줄에는 보통 제목을 작성하고 그 다음 줄부터 상세 내용을 작성 
        - 제목과 상세 내용 사이에는 빈줄로 구별하여 로그 출력시 간단하게 출력되도록 한다. 
    • 좋은 커밋 메시지의 여러 규칙
        (1) 제목과 본문은 빈 줄로 분리 
        (2) 제목은 50자 이내로 작성 
        (3) 제목을 영어로 쓰는 경우, 첫 글자는 대문자로 
        (4) 제목에는 마침표를 넣지 않음 
        (5) 본문을 72자 단위로 줄바꿈 함 
        (6) 어떻게보다 무엇과 왜를 설명함 
    • 만일 커밋 메시지를 작성하지 않을 경우에는 커밋을 할 수 없다. 
    • 커밋 메시지의 텍스트 에디터는 nano로 설정되어있지만, 아래의 명령어를 통해서 "VIM 에디터"로 변경이 가능하다. 

git config --global core.editor "vim"

 

    • 간단하게 커밋과 동시에 한 줄짜리 커밋 메시지를 작성하기 위해선, -m 옵션을 사용하면 된다.  

$git commit -m "commit message"

 

    • 메시지가 없는 빈 커밋을 작성하기 위해선, 아래의 옵션을 사용하면 된다.

$git commit --allow-empty-message -m ""

 

   • 마지막으로 작성한 커밋 메시지를 수정을 해야한다면, $git commit --amend 를 사용하면 된다.
   • 커밋 간의 차이(diff)를 커밋 메시지에 작성하고자 한다면, $git commit -v 옵션을 사용한다.  

  (3) 커밋의 로그 기록   
    • 로그 확인 명령어: $git log   
    • 로그 기록은 최신 커밋 기록부터 내림차순으로 정렬한다. 
    • 커밋 로그와 관련된 옵션 
       - $git log --pretty=short : 간략하게 로그 기록을 확인할 때 사용되며 커밋 메시지의 첫번째 줄만 출력된다. 
       - $git log --pretty=oneline : 각 커밋을 한 줄로 표현 
       - $git log --oneline : 위와 동일 (간단한 커밋 해시와 제목만 출력) 
       - $git log --oneline --graph --decorate : HEAD와 관련된 커밋들을 조금 더 자세히 보고 싶을 때 
          --graph : 커밋 옆에 브랜치의 흐름을 보여줌 
          --decorate: 브랜치와 태그 등의 참조를 간결하게 표시 
          --all: all이 없는 경우 HEAD와 관련 없는 커밋은 출력 x 
       - $git log --oneline --graph --all --decorate : 모든 브랜치등을 보고 싶을 때 사용 
       - $git log --oneline -nx : x개의 최신 커밋을 볼 때 사용
       - $git log file_name : 특정 파일(file_name)의 로그 기록을 확인할 때, 사용한다.  
       - $git show <commit_id> : <commit_id>의 상세 커밋 메시지를 확인한다. 
       - $git log -p : diff 기능을 같이 포함하여 출력 
       - $git log --stat : 히스토리를 출력 


  (4) 수정된 파일 되돌리기 
   마지막 커밋 이후에 수정한 파일을 마지막 커밋 때의 상태 (수정 전 상태)로 되돌리는 명령어는 아래와 같다. 
    • 명령어: $git checkout -- <modified file>

  (5) 커밋 간의 차이 보기: diff 명령어 
   diff 명령어를 이용하여 파일들의 수정 이력을 비교할 수 있다. 
    • $git diff : 워킹 디렉토리와 스테이지 영역 간의 변경사항을 비교한다.
    워킹 디렉토리에서 작업한 파일 (modified 상태)를 $git add로 스테이지 영역으로 등록할 경우, $git diff는 아무 내용을 출력하지 않는다. 
    $git diff head : 스테이지 영역에 있는 파일과 최신 커밋 (head)와의 변경 내용을 비교한다.  

3) 커밋이 성공적으로 된 이후

커밋이 성공적으로 완료되었다면, 스테이지 영역은 초기화된다. 즉, 커밋 이후 새로운 추가 파일 및 수정 파일이 없다는 의미이다. 이는 $git status 명령어로 working tree clean 메시지가 출력됨을 통해서 확인할 수 있다. 이후 파일을 수정하게 되면, 파일은 modified 상태로 변경이 되며, 워킹 디렉토리로 이동하게 된다. 이후, 수정된 파일을 커밋을 하는 과정은 위에서 수행한 과정과 동일하다. 즉, $git add 명령어로 stage 영역에 등록한 후, $git commit 명령어를 통해 다시 커밋을 해야한다. 

※ 개인적으로 git에서 어떻게 동작하는지를 이해한 부분을 아래의 그림으로 정리를 하였다.  

728x90

'컴퓨터 & IT (Computer & IT) > Github' 카테고리의 다른 글

[GitHub] 병합과 충돌  (0) 2021.04.24
[Github] GitHub과 관련된 국내 도서  (0) 2021.04.23
[Github] 브랜치  (0) 2021.04.06
[Github] 서버 저장소 관련 내용 정리  (0) 2021.03.07
[Github] Github 설치  (0) 2020.07.11

댓글