깃이 코드 변화를 기록하는 것을 커밋이라고 한다.
커밋(commit)은 영어로 '~을 적어두다' 라는 의미이고 커밋은 의미있는 변경 작업들을 저장소에 기록하는 동작이다.
깃은 코드의 변경 이력과 시점을 커밋으로 기록한다.
깃이 없었을 때는 파일을 복사해서 변경하는 방법을 이용했다.
상대적으로 더 많은 파일을 생성 및 관리해야하고 모든 내용이 중복되기 때문에 용량도 많이 차지 한다.
깃의 커밋은 새로 변경된 부분만 추출하여 저장한다.
파일이름을 변경하지 않고도 동일한 파일 이름 하나로 관리가 가능하다.
=> 시간에 따라 변화되는 내용만 관리하고 코드가 변화된 시간 순서에 따라 영구적으로 저장한다.
파일 하나로 이력을 처리하기 때문에 유용하다.
부모커밋을 기반으로 변화된 부분만 새로운 커밋으로 생성하고 파일의 시간적 변화도 함께 저장한다.

$ mkdir 새파일명 ------------- 새 폴더 생성
$ cd 새파일명 ------------------ 새 폴더로 이동
$ git init -------------------- 저장소를 깃으로 초기화
$ code index.html ------------- VScod를 사용해 파일 작성
index.html에 내용은 적지말고 title만 바꿔서 HTML파일은 만든다.
파일을 생성하면 워킹 디렉터리에 index.htm 이름으로 저장된다.
모든 작업은 워킹디렉터리 안에서 진행된다.
워킹 디렉터리에 새 파일이 추가되면 깃은 변화된 상태를 자동으로 감지한다.
이때 깃 상태를 확인하는 명령어가 status이다.
git bash에 status 명령어를 입력하면 Untracked files에 새로운 파일이름이 빨간색으로 뜬다.
=> Untracked files 라는 메시지는 워킹 디렉터리에 새로운 파일이 등록되었다고 알려주는 것이다.
워킹 디렉터리에 새 파일이 추가되면 상태를 감지하고 향후 이력을 추적할지 여부를 결정한다.
커밋을 하려면 파일의 상태가 추적가능 해야한다.
워킹디렉터리에 새로 추가된 untracked 상태의 파일을 추적 가능 상태로 변경하는 것을 등록이라고 한다.
파일을 등록하면 워킹 디렉터리의 파일이 스테이지 영역에 추가된다.
스테이지 영역의 관리 목록에 추가된 파일만 깃에서 이력을 추가할 수 있다.
워킹 디렉터리는 작업을 위한 일종의 샌드박스(서로 분리되어 있는 영역)와 같다.
등록이란 워킹 디렉터리에 있는 파일을 스테이지(stage) 영역으로 복사하는 것을 의미한다.
복사란 깃 내부에서 논리적인 기록을 변경하는 과정일 뿐이다.
스테이지에 등록되지 않은 unstage 상태의 파일을 커밋할 수 없다.
깃은 커밋하기 전에 파일들이 stage인지 unstage 상태인지 판단한다.
스테이지 영역으로 등록된 파일들은 tracked상태로 자동 변경된다.
add명령어는 워킹 디렉터리의 파일을 스테이지 영역으로 등록한다.
$ git add 파일이름
add 명령어를 실행하면 지정된 파일은 스테이지 영역으로 등록된다.
스테이지 영역에 파일이 등록되면 파일은 tracked 상태로 변경된다.
파일이름 대신 점(.)을 이용하면 전체 파일과 폴더를 모두 등록할 수 있다.
$ git add .
필요한 파일만 스테이지 영역에 등록하여 이력을 추적하면 된다.
스테이지 영역에 등록되지 않은 파일은 커밋 작업에 포함되지 않는다.
빈 폴더는 스테이지 영역에 등록할 수 없다.
untracked 상태인 파일은 소스트리의 스테이지에 올라가지 않은 파일 영역에서 확인할 수 있다.
파일을 선택하여 상위 영역의 스테이지에 올라간 파일 부분으로 옮긴다.

전체 파일을 스테이지 영역에 등록할 때는 모두 스테이지에 올리기를 누른다.
스테이지 영역에 등록된 파일은 스테이지에 올라간 파일 목록에서 확인할 수 있다.

new file 메세지가 뜨고 이것은 스테이지 영역에 파일을 정상적으로 등록했다는 의미이다.
스테이지 영역에 등록되었다고 해서 커밋이 된 건 아니다.
unstage 상태로 변경하려면 삭제(rm)나 리셋(reset) 명령어를 사용한다.
rm 명령어로 삭제할경우 --cached 옵션을 함께 사용해야한다.
$ git rm --cached 삭제할파일이름 --------- 스테이지에서 삭제
스테이지의 캐시 목록에서 파일이 삭제된다.
status 명령어로 확인해볼 경우 다시 untracked 상태로 변경


파일 이름을 변경했다고 별도로 깃에 통보할 필요는 없다.
$ git mv 파일이름 새파일이름

이름을 변경한다는 의미는 기존 파일을 삭제하고 새파일을 다시 스테이지 영역에 등록하는 과정과 유사하다.
깃에는 HEAD라는 포인터 개념이 있다.
HEAD는 커밋을 가리키는 묵시적 참조 포인터이다.

HEAD는 최종적인 커밋 작업의 위치를 가리킨다.
HEAD는 바로 부모 커밋을 가리킨다.
깃을 처음 설치하고 처음 커밋할 때는 HEAD 포인터가 없다.
HEAD는 커밋 될때마다 한 단계씩 이동하다가 마지막 커밋 위치를 가리킨다.
=> HEAD는 커밋이 변화한 최종 시점을 의미한다.
커밋은 파일 변화를 깃 저장소에 영구적으로 기록한다.
깃이 다른 버전관리 도구와 다른 점은 스냅샷 방식을 이용한다는 것이다.
깃은 변경된 파일 전체를 저장하지 않고 파일에서 변경된 부분을 찾아 수정된 내용만 저장한다.
깃의 스냅샷은 HEAD가 가리키는 커밋을 기반으로 사진을 찍는다.
스냅샷 뱡식을 이용해 빠르게 버전의 차이점을 처리하고 용량을 적게 사용한다
새롭게 생성된 파일을 커밋하려면 반드시 tracked 상태로 변경해주어야 한다.
tracked 상태로 변경됨과 동시에 스테이지 영역에 등록합니다.
tracked 상태인 파일을 수정하면 modified 상태로 변경된다.
modified 상태는 untracked 상태이므로 반드시 등록 명령으로 다시 스테이지로 재등록해야 한다.
커밋전에는 status 명령어로 항상 상태를 확인하는 습관을 가져야한다.
워킹 디렉터리가 깨끗하게 정리되어있지 않으면 커밋 명령어를 수행할 수 없다.
수정된 파일 이력을 커밋하려면 commit 명령어를 사용한다.
$ git commit
깃의 커밋은 HEAD와 스테이지 영역 간 차이를 비교하여 새로운 객체를 생성한다.

커밋은 스냅샷을 이용하여 새로 수정된 파일과 디렉터리를 묶는 트리객체이다.
커밋을 하면 새로운 트리 객체로 변환하는 것과 유사하다.
커밋을 할때 생성된 객체를 기록하는 것과 동시에 이를 구별할 수 있는 메시지를 같이 작성해야 하는데 이를 커밋 메시지 라고 한다.
커밋은 파일 이름을 여러 개 사용하지 않고 하나만 가진다.
파일 이름을 사용하지 않고 별도로 작성한 메시지 문자열로 각 변경 객체들을 쉽게 구분할 수 있다.
모든 커밋은 반드시 커밋 메시지를 작성해야한다.
vi 에디터 사용 법 :
vi 에디터에 아무 내용도 넣지 않고 종료하면 커밋 명령은 취소된다.
커밋 메세지 작성시 요약내용과 상세내용을 분리해서 기록하면 좋다.
첫 째 줄을 분리하여 작성하는 것은 로그 출력을 간단하게 하기 위해서이다.
$ git commit -a
-a 옵션은 커밋을 하기 전에 자동으로 모든 파일을 등록하는 과정을 미리 수행한다.
더이상 추가된 새로운 파일과 수정된 파일이 없다는 의미인 working tree clean 메시지를 볼 수 있다.
커밋 목록을 확인할 수 있는 명령어는 log 명령어를 별도로 제공한다
$ git log
log 명령어는 시간 순으로 커밋 기록을 출력하는데 최신 커밋 기록부터 내림차순으로 냐열한다.

커밋 시간을 맹목적으로 믿을 수는 없다.
깃은 분산형 저장소로 각자의 PC에 설정한 시간 정보를 바탕으로 커밋기록을 작성한다.
작업중인 컴퓨터가 다른 지역의 시간이나 잘못된 시간으로 설정되어 있을 수도 있다.
소스트리에서 왼쪽의 브랜치 탭을 선택한다.
앞에서 status 명령어를 실행했을 때 'On branch master' 메세지와 log 명령어를 실행한 결과에서 (HEAD -> master) 부분도 보았다.
깃을 처음 생성하면 자동으로 master 브랜치 한개를 생성하고 커밋은 master 브랜치 안에 기록된다.
소스트리의 master브랜치를 선택하면 커밋의 로그 기록이 순차적으로 나열되는 것을 확인할 수 있다.

소스트리 목록은 크게 '그래프, 커밋 메시지(설명), 작성자, 날짜, 커밋 아이디' 다섯가지로 구분한다.