index

git status

git status는 현재 리포지토리의 상태를 보여주는 명령어이다

how git status works

git은 스테이징 영역과 워킹 디렉토리를 HEAD와 비교하여 각 파일의 추가/수정/삭제 등의 변경을 감지한다

감지된 변경의 상태 값에 따라 분류한 뒤 메시지를 생성하고 브랜치 정보와 함께 상태를 출력한다

messages

Changes not staged: 변경 사항이 워킹 디렉토리에만 존재

Changes to be committed: 변경 사항을 스테이징 영역에 추가

Untracked: git이 관리하지 않는 파일

git status command

git status 명령은 브랜치 정보 및 변경 감지한 파일들을 상태별로 분류하고, 각 상태마다 처리할 수 있는 다른 명령어와 함께 메시지를 출력한다

$ git status

# 브랜치 정보
On branch main

# 로컬 main 브랜치와 원격 main 브랜치 동기화 정보 (up to date)
Your branch is up to date with 'origin/main'.

# 스테이징 영역 정보
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   test2/a

# 워킹 디렉토리 변경 사항 정보
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:   main.py

# 추적 중이지 않은 파일 정보
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test.py

git status -s command

git status -s 명령은 변경 감지된 파일에 대해 짧은 형식으로 상태를 표시한다

기호

$ git status -s
M  test.py   # 스테이징 영역에 추가된 변경 사항
 M main.py   # 스테이징 영역에 추가되지 않은 변경 사항
A  test2/a   # 스테이징 영역에 추가된 추적되지 않은 파일 
?? test.py   # 추적되지 않은 파일

state list

로컬 브랜치 상태

원격 브랜치와의 동기화 상태

리포지토리 작업 상태

git diff

git diff는 git 리포지토리에서 파일 간 또는 워킹 디렉토리, 스테이징 영역, 커밋 간의 변경 사항 차이점을 표시하는 명령어로 텍스트 파일만 비교할 수 있다

비교 대상(워킹 디렉토리 vs 스테이징 또는 스테이징 vs HEAD)을 설정하면 Diff 알고리즘을 이용하여 파일별 줄 단위 변경 사항을 계산한다

추가된 줄은 +로 삭제된 줄은 - 기호를 사용하여 출력한다

commands

git diff [<file>]: 워킹 디렉토리 vs 스테이징 영역의 변경 사항을 비교한다 (워킹 디렉토리와 스테이징 모두 변경 사항이 있어야 출력되며, 만약 스테이징만 변경 사항이 있는 경우 --staged 옵션을 사용해야 함)

git diff --staged [<file>] 또는 git diff --cached [<file>]: HEAD와 스테이징 영역의 변경 사항을 비교한다

git diff <commit1> <commit2>: 지정된 두 커밋 간의 변경 사항을 비교한다

git diff --stat: 변경 사항 통계 요약

git diff command

파일 변경 사항

# file.txt의 변경 사항을 스테이징 영역에 추가한다
$ echo "hello" > file.txt
$ git add file.txt

# 이후 워킹 디렉토리에서 파일을 한 번 더 변경한다
$ git "git" >> file.txt

명령 실행

$ git diff file.txt

# a: 변경 전 파일 (스테이징의 file.txt 변경 사항)
# b: 변경 후 파일 (워킹 디렉토리의 file.txt 변경 사항)
diff --git a/file.txt b/file.txt

# 파일 해시 및 모드 정보
# ce01362: 변경 전 파일의 Blob 객체 SHA-1 해시
# 23509e0: 변경 후 파일의 Blob 객체 SHA-1 해시
# 100644: 일반 파일(읽기/쓰기 권한, 실행 불가)
index ce01362..23509e0 100644

# ----: 변경 전 상태의 파일 경로, 삭제된 줄을 표시할 기준 파일 (스테이징의 a/file.txt)
# ++++: 변경 후 상태의 파일 경로, 추가된 줄을 표시할 대상 파일 (워킹 디렉토리의 b/file.txt)
--- a/file.txt
+++ b/file.txt

# @@ -1 +1,2 @@: 변경이 발생한 줄 범위를 나타내는 청크 헤더
# -1: 변경 전 파일의 시작 줄 번호와 범위 (-1은 첫 번째 줄부터 1줄을 의미함)
# +1,2: 변경 후 파일의 시작 줄 번호와 범위(+1,2는 첫 번째 줄부터 2줄을 의미함)
# 변경 전에 1줄이었던 파일이 변경 후 2줄로 늘어난 것을 의미한다
@@ -1 +1,2 @@

# hello: 추가(+)나 삭제(-)없이 그대로 유지됨
# +git: 변경 후 파일(워킹 디렉토리)에서 새로 추가된 줄
 hello
+git

git diff --staged command

파일 변경 사항

$ cat file.txt
hello
git

$ echo "hello\nhansanhha" >> file.txt
$ git add file.txt

명령 실행

$ git status --staged file.txt

diff --git a/file.txt b/file.txt
index 23509e0..cf2a5ac 100644
--- a/file.txt
+++ b/file.txt

# -1,2: 변경 전 파일의 줄 범위
# +1,3: 변경 후 파일의 줄 범위 (2줄 늘어남)
@@ -1,2 +1,4 @@
 hello
 git
+hello
+hansanhha

git diff <commit1> <commit2> command

# 마지막 커밋과 직전 커밋 비교
$ git diff HEAD^ HEAD

diff --git a/file.txt b/file.txt
index 23509e0..968993b 100644
--- a/file.txt
+++ b/file.txt
@@ -1,2 +1,4 @@
 hello
 git
+hansanhha
+hello

git log

git log 명령은 현재 브랜치(HEAD)를 기준으로 커밋 히스토리를 표시한다

각 커밋의 SHA-1 해시, 작성자, 날짜, 커밋 메시지 등 메타데이터를 출력한다

git log: 커밋 히스토리의 각 커밋에 대한 상세 내역을 출력한다

git log -p(patch): 각 커밋의 변경 내역(diff)을 포함하여 출력한다

git log --oneline: 커밋 해시 일부와 메시지를 한 줄로 표시한다

git log --graph --all: 모든 브랜치를 포함하고 각 브랜치의 분기 구조를 시각화한다

git log --follow <file>: 특정 파일의 히스토리를 출력한다

git log --grep=<pattern>: 지정한 패턴을 커밋 메시지로 포함한 히스토리를 출력한다

git log -n <number>: 최근 n개 커밋만 표시한다

git log <start>..<end>: start부터 end까지의 로그를 출력한다

git show

git show 명령은 지정된 커밋의 메타데이터(작성자, 커밋 메시지 등)와 변경 내용(diff)을 출력한다

기본적으로 HEAD의 커밋을 대상으로 동작하며 특정 커밋이나 브랜치, 태그, 파일을 지정할 수 있다 (Blob 같은 저수준 객체도 표시 가능)

git log -1 -p 명령과 동일한 동작을 수행한다

git reflog

git flog 명령은 HEAD와 브랜치 참조가 이동한 모든 기록을 표시한다

.git/logs/ 디렉토리에 저장된 로그(.git/logs/HEAD, .git/logs/refs/)를 기반으로 동작하며 기본적으로 최근 30일 간의 기록을 유지한다

git log와 달리 삭제되거나 덮어씌워진 커밋(Detached HEAD, 고아 커밋 포함)까지 포함해 저장소의 모든 동작을 보여준다

용도

동작 과정

git reflog: 최근 HEAD 이동 기록을 표시한다

git reflog <branch>: 특정 브랜치의 로그를 출력한다

git reflog -n <number>: 최근 n개의 항목만 표시한다

example

git refloggit reset --hard 명령을 사용하여 삭제된 커밋의 이전 상태를 복구할 수 있다

# main 브랜치의 커밋 히스토리 확인
$ git log --oneline
5a0df1a add main.py
231734c add util.py
85a44ff add test.py

# 가장 최근 커밋 삭제
$ git rebase -i HEAD^

# main 브랜치의 커밋 히스토리 확인 (가장 최근 커밋 삭제됨)
$ git log --oneline
231734c add util.py
85a44ff add test.py

# reflog로 모든 로그 확인
$ git reflog main
760f761 (HEAD -> main) main@{0}: rebase (finish): refs/heads/main onto 760f761be966564fcc6f59c4a537438813b70f56
5a0df1a (HEAD -> main) main@{1}: add main.py 
231734c (HEAD -> main) main@{2}: add util.py 
85a44ff (HEAD -> main) main@{3}: add test.py 

# 삭제된 커밋의 상태로 하드리셋하여 상태 복구
$ git reset --hard main@{1}