git 개념 정리

■git 기본 커맨드 정리
  ▨초기화
    git init : 현재 디렉토리를 git 저장소로 만들기 (.git 생성)
    git init --bare --shared <git dir> : Working Directory를 만들지 않고, 여러사람이 작업할 떄 권한을 자동으로 주는 git 저장소 만들기

  ▨Staging Area로 보내기
    git add . : 현재 디렉토리의 모든 내용을 Staging Area(.git)에 추가
    git add -A : Working Directory의 모든 내용을 Staging Area에 추가
    git add -p : 변경점을 hunk 단위로 보여주면서 인터랙티브하게 Staging Area에 추가

  ▨commit
    git commit -m "Add: test.py 파일 추가"

  ▨원격 저장소에서 가져오기
    git fetch : 원격 저장소의 변경 내용을 확인하기
    git pull origin master : 원격 저장소의 변경 내용을 현재 디렉토리로 가져오기 (원격 서버→.git)
    git clone : 원격 저장소를 로컬 저장소로 복사하여 새로운 저장소 생성 (기존 commit 로그 없음)
    git fork : 원격 저장소를 원격 저장소에 복사본 생성 (기존 commit 로그 있음)

  ▨원격 저장소로 보내기
    git push : 변경 사항을 원격 서버에 업로드 (.git→원격 서버)

  ▨상태 확인
    git status : 현재 상태 확인
    git log : 로그 확인
    git reflog : 커밋 삭제 로그 확인
    git log --oneline : 커밋 히스토리 조회 (commit hash 확인)
    git remote -v : 리모트 확인

  ▨설정
    git config --global user.name "git user" : 사용자 설정
    git config --global user.email "gituser@git.com" : 이메일 설정
    git config --unset --global user.name : user.name 설정 삭제
    git remote add origin "https://git:git@10.10.10.111/sample_repo.git"
    git remote remove origin : origin 저장소 삭제
    git remote -v : 원격 저장소 확인
    git config --list : 전체 설정 확인

  ▨remote
    git remote show origin : origin remote 상세 정보 보기

  ▨초기화
    git init : 현재 디렉토리를 git 저장소로 만들기 (.git 생성)
    git init --bare --shared <git dir> : Working Directory를 만들지 않고, 여러사람이 작업할 떄 권한을 자동으로 주는 git 저장소 만들기

  ▨삭제
    git rm -f --cached <파일명>: 원격 저장소에 있는 파일 삭제 ('*' 가능)
    git rm -f <파일명>: 원격 저장소와 로컬 저장소에 있는 파일 삭제

  ▨commit
    git commit -m "message" : 커밋 생성
    git commit --amend -m "수정된 메시지" : 커밋 생성+커밋 메세지 수정
    git commit --amend --no-edit : 커밋 생성+설명은 수정하지 않음

  ▨branch
    git branch
    git branch -vv : 로컬 분기 브랜치 목록 보기
    git branch <branch> : 브랜치 생성
    git branch -b <branch> : 브랜치를 생성하고 해당 브랜치로 바로 이동
    git checkout <branch> : 브랜치 이동
    git branch : 원하는 브랜치로 이동했는지 확인
    git branch -a : 모든 브랜치 확인
    git branch -d <branch> : 브랜치 삭제
    git branch -D <branch> : 브랜치 강제 삭제
    git branch -rd <remote>/브랜치 이름> : 원격 추적 브랜치 삭제
    git push --delete <remote> <branch> : 원격지 브랜치 삭제
    git remote prune <remote> : unreachable 한 git object 들을 local 에서 clean
    git remote prune --dry-run --verbose : prune 테스트
    git diff <branch> <다른 브랜치 이름> : 변경 내용을 merge 하기 전에 바뀐 내용 비교
    git merge <다른 브랜치 이름> : 다른 브랜치와 병합
    ※브랜치 파일 위치: .git/refs/remotes/<branch name>

  ▨커밋 되돌리기 (push 전에 사용)
    git reset HEAD^ : commit 바로 이전 단계로 복구
    git reset HEAD~2 : commit 바로 전전 단계로 복구
    git reset --hard <commit hash> : <commit hash> 이후의 변경 이력은 파일까지 모두 삭제
    git reset --mixed <commit hash> : Working Directory는 변화없이 HEAD와 Staging Area만 <commit hash>로 되돌림
    git reset --soft <commit hash> : Staging Area, Working Directory는 변화없이 HEAD만 <commit hash>로 되돌림

  ▨커밋 되돌리기 (push 후에 사용)
    git revert <commit hash> : <commit hash>에 해당하는 커밋을 이전 상태로 되돌림

  ▨저수준 커맨드
    git cat-file -p HEAD : HEAD를 가리키는 스냅샷 확인
    git ls-files -s : 현재 Index 확인

  ▨압축
    git archive -l (압축 가능한 포맷 확인)
    git archive --format=tar.gz master -o /backup/20230504_backup.tar.gz

  ▨저장소 위치에 따른 정리
    commit: Staging Area > Local Repository
    push: Local Repository > Remote Repository
    pull: Remote Repository > Local Repository
    clone: Remote Repository > Local Repository (최초 가져오기에 사용)
    fork: Remote Repository > Remote Repository

■Local Repository→Remote Repository 레포지터리 최초 업로드
  cd <Working Directory>
  git init
  git remote add origin "https://git:git@10.10.10.111/sample_repo.git"
  git add -A
  git commit -m "initial commit"
  git push

■Remote Repository→Local Repository 최초 다운로드
  git clone "https://git:git@10.10.10.111/sample_repo.git" "D:\src\test"
  git add .
  git commit
  git push

■Remote Repository→Local Repository 변경사항 반영
  git fetch origin master
  git pull origin master

■git 개념
                 Working Directory (.git이 위치한 디렉토리)                             git Server
|-----------------------------------------------------------------------------||------------------------|

                                    commit -a
         +--------------------------------------------------------+
         |             add                        commit          |           push
         |    +-------------------+          +---------------+    |    +----------------+
         |    |                   |          |               |    |    |                |
         |    |                   v          |               v    v    |                v
+-------------------+          +-------------------+     +-------------------+      +-------------------+
|                   |          |                   |     |  Local            |      |  Remote           |
| Working Directory |<---------|  Staging Area     |     |  Repository       |      |  Repository       |
|                   | checkout |  (.git directory) |     |  (.git directory) |      |                   |
+-------------------+          +-------------------+     +-------------------+      +-------------------+
     ^    ^     ^                                             |    |     ^              |     |
     |    |     |                                             |    |     |              |     |
     |    |     +---------------------------------------------+    |     +--------------+     |
     |    |                      checkout HEAD                     |          fetch           |
     |    +--------------------------------------------------------+                          |
     |                               merge                                                    |
     +----------------------------------------------------------------------------------------+
                                         pull = fetch + merge

  ▨저장소 설명
    -Working Directory:
      내가 작업하고 있는 프로젝트의 디렉토리
    -Staging Area(.git):
      commit을 하기 위해 git add 명령어로 추가한 파일들이 모여있는 공간.
      스테이징 영역(Staging area)란 commit이 가능한 영역으로, commit하기 전 파일을 담아두는 상자라고 볼 수 있다. git add 명령어를 통해 수정된 파일을 스테이징 영역에 담을 수 있다.
      즉, 스테이징 영역은 commit하기 위한 파일들을 담는 박스이고, commit 하는 것은 박스에 담긴 파일들을 간단한 코멘트를 남겨 라벨링을 해주는 것이다.
      만약, git add 명령어를 통해 파일을 Staging area에 추가한 상태에서 또 파일을 수정한다면, 해당 파일은 스테이징 영역에 존재하면서, 수정(modified)된 상태가 된다.
      따라서, git status로 확인하면 스테이징 영역과 modified 영역에 둘 다 표시하게 된다.
      이 상태에서 git commit을 하게 된다면, 스테이징 영역에 있는 파일만 commit이 되고, 이후 수정된 내용은 commit이 되지 않는다. 따라서 git add 명령어를 실행한 후 다시 파일을 수정한다면 git add 명령어를 다시 실행하여 파일의 최신 상태가 스테이징 영역에 존재하도록 해야 한다.
      만약, git add 명령어를 실행한 후 다시 파일을 수정하였지만, 수정한 파일을 폐기하고 싶다면, git restore 명령어를 통해 폐기가 가능하다. git restore 명령어를 실행하였을 경우, git add 된 파일은 폐기되지 않고, git add 명령어 사용한 이후에 수정된 부분만 폐기된다.
    -Local Repository(.git):
      git commit 시 .git\objects\에 이력이 추가되며, 파일과 메타데이터도 저장된다.

  ▨git의 3가지 상태

◆Modified           ◆Staged             ◆Committed
+----------------+   +----------------+   +----------------+
|                |   |                |   |                |
| Working        |   | Staging Area   |   | Local          |
|      Directory |   |                |   |     Repository |
|                |   |                |   | (.git)         |
+----------------+   +----------------+   +----------------+
        |                    |                    |
        |<----------------------------------------|
        |           checkout the project          |
        |------------------->|                    |
        |     stage fixes    |------------------->|
        |                    |       commit       |

  -Modified : 수정한 파일을 로컬 데이터베이스에 commit하지 않은 상태
    *Working Directory 영역에 있는 파일들 중 수정을 한 파일들의 상태를 의미
  -Staged : 수정한 파일들 중 commit 할 것이라고 표시한 상태
    *Staging Area 영역에 있는 파일들의 상태
  -Commited : Staged 상태의 파일들이 로컬 데이터베이스에 안전하게 저장되었다는 의미
    *commit 된 대상 파일은 Working Directory 영역으로 돌아가게 되고 대상 파일의 버전을 관리하는 파일들은 .git에 저장된 상태
    *Commited 상태 대상 파일을 수정하게 되면 Modified 상태

  ▨git 파일의 LifeCycle 관점에서 본 4가지 상태
+----------------+   +----------------+  +----------------+   +----------------+
|   Untracked    |   |  Unmodified    |  |    Modified    |   |    Staged      |
+----------------+   +----------------+  +----------------+   +----------------+
        |                    |                  |                    |
        |------------------->|                  |                    |
        | Add the file       |                  |                    |
        |                    |----------------->|                    |
        |                    | Edit the file    |------------------->|
        |                    |                  | Stage the file     |
        |<-------------------|                  |                    |
        | Remove the file    |                  |                    |
        |                    |<------------------------------------- |
        |                    |                  |      Commit        |

  -Untracked : Working Directory에 존재는 하지만 git이 관리를 하지 않는 파일들의 상태
    *Working Directory에 새롭게 만들어진 파일들이 이에  해당
  -Unmodified : 신규로 파일이 추가되었을 때, new file 상태와 같다. (git add 상태)
  -Modified : 파일이 추가된 이후 해당 파일이 수정되었을 때의 상태
  -Staged : Staging Area에 반영된 상태

■git 용어
  origin: remote(원격 저장소)의 디폴트 이름 (저장소 이름을 origin으로 하면 저장소명 생략가능)
  master: 기본 branch.
  branch: Remote Repository의 현재 상태를 복사하여 master branch와 별개의 작업을 진행할 수 있는 공간
  head: 현재 작업중인 branch의 최근 commit된 위치
  index: Staging Area를 의미
  merge: 다른 branch의 내용을 현재 branch로 가져와 합치는 작업
  fetch: 원격저장소에 있는 변경사항들을 로컬저장소에 가져오기 전에 변경내용을 확인하고 싶은경우에 사용 (내용을 가져오지 않고 변경한 내역들만 확인)
  pull: 원격저장소에 있는 변경사항들을 로컬저장소로 가져와 합치는 명령
  push: 원격저장소에 코드 변경분을 업로드
  checkout: branch 간 전환 또는 현재 작업 중인 파일들을 복원
  HEAD: HEAD란 가장 최근에 checkout된 branch의 마지막 commit을 가리키는 포인터.
  blob 개체 : git 내부적으로 사용되는 파일 개념
  tree 개체 : git 내부적으로 사용되는 디렉토리 개념

■git 기본 환경 설정
  git config --global user.name "git_user"
  git config --global user.email "gituser@gituser.com"
  git config --global core.autocrlf false
  git config --global core.editor "'C:/PortableApps/Notepad++Portable/Notepad++Portable.exe' -multiInst -nosession"
  git config --global core.pager ""
  git config --global core.protectNTFS false
  git config --global http.sslVerify false
  git config --global i18n.commitencoding "UTF-8"
  git config --global i18n.logoutputencoding "UTF-8"
  git config --global push.default current
  git config --global --add diff.guitool kdiff3
  git config --global --add difftool.kdiff3.cmd  """"C:\PortableApps\GitExtensions_Portable\_3RD_PARTY_APPS\KDiff3\bin\diff3.exe""" """$LOCAL""" """$REMOTE""""
  git config --global --add difftool.kdiff3.path "C:\PortableApps\GitExtensions_Portable\_3RD_PARTY_APPS\KDiff3\bin\diff3.exe"
  git config --global --add difftool.kdiff3.trustExitCode false
  git config --global --add merge.tool kdiff3
  git config --global --add merge.tool.kdiff3.cmd """"C:\PortableApps\GitExtensions_Portable\_3RD_PARTY_APPS\KDiff3\bin\diff3.exe""" """$BASE""" """$LOCAL""" """$REMOTE""" -o """$MERGED""""
  git config --global --add merge.tool.kdiff3.path "C:\PortableApps\GitExtensions_Portable\_3RD_PARTY_APPS\KDiff3\bin\diff3.exe"
  git config --global --add mergetool.kdiff3.trustExitCode false

  git init
  git remote add origin "https://git:git@10.10.10.111/sample_repo.git"
  #git remote remove origin
  ※global config 파일 위치: ~/.gitconfig
  ※local config 파일 위치: .git/config

■branch 개념
  branch(branch)란 독립적으로 어떤 작업을 진행하기 위한 개념으로 필요에 의해 만들어지는 각각의 branch는 다른 branch의 영향을 받지 않고 영향을 주지도 않기 때문에 여러 작업을 동시에 실행할 수 있다.
  현재 작업중인 branch는 HEAD-> 가 가르키는 branch 이다.

  -master branch란?
    저장소 생성 시 자동으로 생성되는 디폴트 branch

             +-----------+
             | 버그 픽스 |
     +------>| branch    +------+
     |       +-----------+      |
+----+---+                      |
| Master |                      v
| branch +------------------>Merge------->Merge------->Merge-->
+----+---+                                  ^            ^
     |       +-----------+                  |            |
     +------>| 기능 추가 +------------------+            |
     |       | branch    |                               |
     |       +-----------+                               |
     |                                                   |
     |               +------------+                      |
     |               | 기능 변경  |                      |
     +-------------->| branch     +----------------------+
                     +------------+

  -branch 만들기: git branch <branch 이름>
  -작업하고 싶은 branch로 이동하기: git branch <branch 이름>
  -branch생성과 이동을 동시에 하기: git checkout -b <branch 이름>
  -branch 삭제하기: git branch -d <branch 이름>

  ※일반적으로 branch를 삭제를 하는 경우는 master branch와 test branch에서 작업한 것을 병합 한 후 삭제한다.
  ※test branch를 삭제하고 싶으면 현재 가리키고 있는 branch가 test이면 안된다.

■HEAD와 branch 개념 (출처: https://charles098.tistory.com/24)

  HEAD와 branch는 상태를 가리키는 포인터로 HEAD는 branch를 통해 commit을 가리키는 포인터.
  아래는 commit과 checkout 과정에서 branch와 HEAD의 이동을 보여준다.

                             +------+
                             | HEAD |
                             +---+--+
                                 |
                                 v
                             +------+
                             | test |
                             +---+--+
                                 |
                                 v
+-----+        +-----+        +-----+
|     +------->|     +------->|     |
+-----+        +-----+        +-----+
첫번째 commit  두번째 commit  세번째 commit

=> commit을 하면 HEAD가 가리키는 branch가 최신 commit으로 이동

                         +------+
                         | HEAD |
                         +---+--+
                             |
                             v
                         +------+ +------+
                         |master| | test |
                         +-----++ ++-----+
                               |   |
                               v   v
+-----+        +-----+        +-----+
|     +------->|     +------->|     |
+-----+        +-----+        +-----+
첫번째 commit  두번째 commit  세번째 commit

=> test branch를 만들면 위 그림처럼 HEAD가 가리키던 commit을 test branch가 가리키게 된다.

                                  +------+
                                  | HEAD |
                                  +---+--+
                                      |
                                      v
                         +------+ +------+
                         |master| | test |
                         +-----++ ++-----+
                               |   |
                               v   v
+-----+        +-----+        +-----+
|     +------->|     +------->|     |
+-----+        +-----+        +-----+
첫번째 commit  두번째 commit  세번째 commit

=> git chkeckout test로 branch를 변경하면 HEAD는 test를 가리킨다.

                                                           +------+
                                                           | HEAD |
                                                           +---+--+
                                                               |
                                                               v
                             +------+                      +------+
                             |master|                      | test |
                             +---+--+                      +---+--+
                                 |                             |
                                 v                             v
+-----+        +-----+        +-----+        +-----+        +-----+
|     +------->|     +------->|     +------->|     +------->|     +
+-----+        +-----+        +-----+        +-----+        +-----+
첫번째 commit  두번째 commit  세번째 commit  네번째 commit  다섯번째 commit

=> commit을 두번 더 진행했을 경우 HEAD는 현재 branch인 test를 따라 움직인다.

                             +------+
                             | HEAD |
                             +---+--+
                                 |
                                 v
                             +------+                      +------+
                             |master|                      | test |
                             +---+--+                      +---+--+
                                 |                             |
                                 v                             v
+-----+        +-----+        +-----+        +-----+        +-----+
|     +------->|     +------->|     +------->|     +------->|     +
+-----+        +-----+        +-----+        +-----+        +-----+
첫번째 commit  두번째 commit  세번째 commit  네번째 commit  다섯번째 commit

=> git chkeckout master로 branch를 변경하면 HEAD는 다시 master를 가리킨다.

                                                           +------+
                                                           | HEAD |
                                                           +---+--+
                                                               |
                                                               v
                                                           +------+
                                                           |master|
                                                           +---+--+
                                                               |
                                                               v
                              +-----+                      +------+
                              |  #1 +--------------------->|  #2  |
                              +--+--+                      +------+
                                 ^
                                 |                         +------+
                                 |                         | test |
                                 |                         +---+--+
                                 |                             |
                                 |                             v
+-----+        +-----+        +--+--+        +-----+        +-----+
|     +------->|     +------->|     +------->|     +------->|     +
+-----+        +-----+        +-----+        +-----+        +-----+
첫번째 commit  두번째 commit  세번째 commit  네번째 commit  다섯번째 commit

=> commit을 두번 더 했을 경우 코드의 흐름이 두 갈래로 나뉘어 지며, 이를 "분기한다"라고 한다.

                                                           +------+
                                                           | HEAD |
                                                           +---+--+
                                                               |
                                                               v
                                                           +------+
                                                           |master|
                                                           +---+--+
                                                               |
                                                               v
                              +-----+        +-----+       +------+
                              |  #1 +------->|  #2 |------>|merge |<--+
                              +--+--+        +-----+       +------+   |
                                 ^                                    |
                                 |                         +------+   |
                                 |                         | test |   |
                                 |                         +---+--+   |
                                 |                             |      |
                                 |                             v      |
+-----+        +-----+        +--+--+        +-----+        +-----+   |
|     +------->|     +------->|     +------->|     +------->|     +---+
+-----+        +-----+        +-----+        +-----+        +-----+
첫번째 commit  두번째 commit  세번째 commit  네번째 commit  다섯번째 commit

=> git merge test를 하면 HEAD가 가리키던 commit에 test branch가 가리키던 commit을 합쳐 새로운 commit을 만든다.
위로 스크롤