[Git] 4장 커밋
- 버전관리
- 2022. 6. 18. 21:52
참조
코드의 변화
- 깃은 개발 중인 코드의 이력을 만들 수 있습니다. 깃이 코드 변화를 기록하는 것을 커밋(commit) 이라고 합니다.
- 개발 과정에서 소스 코드는 수없이 수정됩니다.
- 일반적으로는 새로운 기능을 추가하는 코드를 삽입합니다. 또 버그를 수정하려고 많은 코드를 이동하거나 대체합니다.
- 이러한 코드 수정은 개발 목적을 달성하는 작업들입니다.
파일 관리 방법
- 깃이 없던 시절, 전통적인 파일의 이력 관리 방법을 알아봅시다.
- 보통 우리는 의미 있는 변경을 할 때 파일을 복사합니다. 그리고 복사한 새 파일에는 추가하거나 변경하고 싶은 내용을 적용합니다.
- 하지만 이렇게 파일을 복사하는 형태는 파일의 변경 내역을 기록하는 것보다 더 많은 파일을 생성하고 관리해야 하는 부작용이 있습니다.
- 반면, 깃의 커밋은 새로 변경된 부분만 추출하여 저장합니다.
- 그것도 파일 이름을 변경하지 않고도 동일한 파일 이름으로 하나로 관리가 가능합니다.
- 즉, 시간에 따라 변화되는 내용만 관리하고, 코드가 변화된 사간 순서에 따라서 영구적으로 저장합니다.
- 이를 커밋(commit) 이라고 합니다.
- 개발자 입장에서는 복잡한 구조의 파일을 관리하지 않아도 되고, 여러개의 파일보다는 파일 하나로 모든 이력을 처리하기 때문에 유용합니다.
새 파일 생성
- 실습을 위해 파일 하나를 간단히 작성합니다.
<!DOCTYPE html>
<html>
<head>
<meta charset=“utf-8” />
<meta name=“viewport” content=“width=device-width, initial-scale=1”>
<title>Page Title</title>
</head>
<body>
</body>
</html>
소스트리에서 새 파일 감지
- 소스트리를 사용하여 깃의 status 명령어와 동일한 상태를 확인할 수 있습니다.
- 저장소에 새 파일이 추가 되면, Unstaged Files 영역에 새파일이 표시됩니다.
깃에 새 파일 등록
- 깃의 워킹 디렉터리에 새 파일이 생성되었습니다.
- 워킹 디렉터리에 있는 파일은 깃이 자동으로 추적 관리하지 않습니다. 커밋을 하려면 파일의 사태가 추적 가능해야 합니다.
- 워킹 디렉터리에 새로 추가된 untracked 상태의 파일을 추적 가능 상태로 변경하는 것을 등록이라고 합니다.
- 또 파일을 등록하면 워킹 디렉터리의 파일이 스테이지 영역에 추가됩니다.
- 스테이지 영역의 관리 목록에 추가된 파일만 깃에서 이력을 추적할 수 있습니다.
스테이지에 등록
- 깃에서 등록이란 워킹 디렉터리에 있는 파일을 스테이지(stage) 영역으로 복사하는 것을 의미 합니다.
- 여기서 '복사' 는 실제 파일을 복사하는 것을 의미하지는 않습니다.
- 깃 내부에서 논리적인 기록을 변경하는 과정일 뿐입니다. 복사라고 표현한 것은 이해하기 쉽게 풀어쓴 의미입니다.
- 워킹 디렉터리에 추가된 모든 파일을 커밋할 때는 반드시 이 과정을 거쳐야 합니다.
- 그래야 깃에서 버전 이력을 관리할 수 있습니다.
- 스테이지에 등록되지 않은 unstage 상태의 파일들은 커밋할 수 없습니다.
- 깃은 커밋하기 전에 파일들이 stage 상태인지 unstage 상태인지를 판단합니다.
- 스테이지 영역으로 등록된 파일들은 tracked 상태로 자동 변경됩니다.
파일의 추적 상태 확인
- 워킹 디렉터리에 있는 새로운 파일이 스테이지 영역에 등록되었습니다.
- 콘솔창에서 status 명령어를 사용하여 등록 상태를 다시 한번 확인합니다.
파일 등록 취소
- tracked 상태의 파일은 untracked 상태로 변경할 수도 있습니다.
- 스테이지에 등록하는 것과 반대 과정입니다.
- 등록 취소는 워킹 디렉터리와 스테이지 영역을 서로 왔다 갔다 할 수 있는 방법입니다.
- unstage 상태로 변경하려면 삭제(rm) 나 리셋(reset) 명령어를 사용합니다.
$ git rm - cached index.html ---- 스테이지 삭제
rm 'index.html'
HEAD
- 커밋을 학습하기 전에 HEAD 개념을 하나 더 알아봅시다.
- 깃에는 HEAD 라는 포인터 개념이 있습니다. HEAD는 커밋을 가리키는 묵시적 참조 포인터입니다.
- HEAD는 최종적인 커밋 작업의 위치를 가리킵니다.
- 앞에서 새로운 커밋은 이전 부모 커밋을 기반으로 새로운 커밋을 만든다고 했습니다. HEAD는 바로 부모 커밋 을 가리킵니다.
- 단 깃을 설치하고 처음 커밋할 때는 HEAD의 포인터가 없습니다. 최소한 한 번 이상 커밋을 해야만 HEAD가 존재합니다.
- HEAD는 커밋될 때마다 한 단계씩 이동합니다. 그리고 마지막 커밋 위치를 가리킵니다.
- HEAD는 커밋이 변화한 최종 시점을 의미합니다.
스냅샷
- 커밋은 파일 변화를 깃 저장소에 영구적으로 기록합니다. 이러한 커밋은 이전에 파일을 복사하여 관리하던 방식과는 큰 차이가 없습니다.
- 깃이 다른 버전 관리 도구와 다른 점은 스냅샷(snapshot) 방식을 이용한다는 것입니다.
- 파일을 복사하는 방식으로 수정본을 관리하면 같은 내용을 반복해서 저장하기에 많은 용량을 차지합니다.
- 또 수정된 부분들을 일일이 찾아야 하기 때문에 검색할 때도 매우 불편합니다.
- 깃은 이러한 시스템적인 단점을 해결하려고 변경된 파일 전체를 저장하지 않고, 파일에서 변경된 부분을 찾아 수정된 내용만 저장합니다.
- 마치 변화된 부분만 찾아 사진을 찍는 것과 같다고 하여 스냅샷 방식 이라고 합니다.
- 깃의 스냅샷은 HEAD가 가리키는 커밋을 기반으로 사진을 찍습니다.
- 그리고 이를 스테이지 영역과 비교하여 새로운 커밋으로 기록합니다.
- 이처럼 깃은 스냅샷 방식을 이용하여 빠르게 버전의 차이점을 처리하고, 용량을 적게 사용합니다.
파일 상태와 커밋
- 커밋은 변화된 내용을 영구적으로 깃 저장소에 기록합니다.
- 새롭게 생성된 파일을 커밋하려면 반드시 tracked 상태로 변경해 주어야 합니다. tracked 상태로 파일이 변경됨과 동시에 스테이지 영역에 등록합니다.
- tracked 상태인 파일을 수정하면 다시 modified 상태로 변경됩니다. modified는 untracked 상태입니다.
- untracked 상태의 파일은 반드시 등록 명령으로 다시 스테이지 상태로 재등록해야 합니다. 재등록 하면 다시 tracked 상태로 변경됩니다.
- 커밋을 하려면 스테이지 영역에 새로운 변경 내용이 있어야 합니다.
- 수정된 내용이 스테이지 영역으로 등록되지 않으면 커밋을 할 수 없습니다. 커밋은 수정된 내용을 한 번만 등록합니다.
- 스테이지 영역의 파일이 변경되지 않았다면 커밋을 두 번 실행할 수 없습니다.
- 깃은 스테이지 영역의 변경된 내용을 기준으로 스냅샷을 만들어 커밋하기 때문입니다.
스테이지 초기화
- 먼저 터미널에서 status 명령어를 실행해서 상태를 확인합니다.
로그 기록 확인
- 깃은 커밋 목록을 확인할 수 있는 log 명령어를 별도로 제공합니다.
- log 명령어는 시간 순으로 기록을 출력하는데, 최신 커밋 기록부터 내림차순으로 나열합니다.
$ git log
파일 수정
- index.html 파일의 내용을 수정합니다.
<!DOCTYPE html>
<html>
<head>
<meta charset=“utf-8” />
<meta name=“viewport” content=“width=device-width, initial-scale=1”>
<title>Page Title</title>
</head>
<body>
<h1>hello GIT world!</h1>
</body>
</html>
파일 변경 사항 확인
- 파일을 수정 후, 터미널에서 status 명령어를 다시 한번 실행합니다.
- 이전과 다른 새로운 메시지를 확인할 수 있습니다.
- 처음 우리가 파일을 생성했을 때는 new file:index.html 메시지를 보았습니다.
- 파일을 수정한 후에는 modified:index.html 메시지가 출력됩니다.
수정된 파일 되돌리기
- 파일을 수정하면 modified 상태로 변경됩니다. 하지만 수정하는 과정에서 파일을 잘못 수정할 수도 있습니다.
- 깃을 이용하면 수정한 파일을 커밋 전 마지막 내용으로 쉽게 되돌릴 수 있습니다.
- 수정 파일을 되돌리면 이전 커밋 이후에 작업한 수정 내역은 모두 삭제합니다.
$ git checkout - 수정파일이름
스테이지에 등록
- 변경된 소스 코드를 커밋하는 것은 처음 파일을 생성하고 등록하는 과정과 매우 유사합니다.
- ➊. 기존 파일을 수정하면 해당 파일은 modified 상태로 변경됩니다. 그리고 다시 워킹 디렉터리로 이동합니다.
- ➋. 파일이 수정되면 반드시 add 명령어로 스테이지 영역에 재등록해야 합니다. 즉, 파일을 수정할 때마다 등록 작업을 반복해야 한다는 것입니다.
$ git add 수정파일이름
두 번째 커밋
- 수정된 파일을 커밋할 수 있는 사전 준비 작업을 마쳤습니다.
- 커밋과 동시에 간단하게 한 줄까지 커밋 메시지도 작성할 수 있습니다.
- 커밋할 때는 --m 옵션을 사용합니다.
- --m 옵션 옆에 간단히 입력한 내용을 바로 커밋 메시지로 처리합니다.
$ git commit --m "커밋메시지"
두 번째 커밋 확인
- 두번째 커밋을 마쳤다면, 다시 한번 로그 확인을 해보겠습니다.
- 로그 메시지가 새롭게 추가된 것을 보실 수 있습니다.
메시지가 없는 빈 커밋
- 커밋을 할 때는 반드시 커밋 메시지를 같이 작성해야 합니다.
- 하지만 의미 없는 커밋이라 커밋 메시지를 생략하고 싶을 때도 있습니다.
- 이러한 특별한 상황에 대비하여 깃은 메시지가 없는 커밋 작성도 허용합니다.
- 이를 간단히 '빈 커밋' 이라고 합니다.
- 빈 커밋 작성 방법은 지금까지 살펴본 메시지 작성 방법과 약간 다릅니다.
세 번째 커밋
- 실습을 위해 index.html 파일을 다시 수정하고 커밋하도록 하겠습니다.
<!DOCTYPE html>
<html>
<head>
<meta charset=“utf-8” />
<meta name=“viewport” content=“width=device-width, initial-scale=1”>
<title> BeomHeeJo</title>
</head>
<body>
<h1>헤더 추가</h1>
</body>
</html>
소스트리에서 빈 커밋
- 소스트리에서는 메시지가 없는 빈 커밋을 하기가 더 쉽습니다.
- 예를 들어 파일 상태 탭을 선택한 후 아래쪽의 커밋 메시지 입력란을 비워 두고 커밋을 누르면 됩니다.
- 그러면 다음과 같은 화인 메시지가 표시됩니다.
빈 커밋 확인
- 빈 커밋 메시지를 확인할 수 있습니다.
- 터미널에서 log 명령어를 입력합니다.
- 소스트리에서 자동적으로 빈 커밋을 하게 되면, no message 라는 문구를 입력하여 커밋합니다.
커밋 아이디
- 각 커밋에는 aa92947d350db27b604d1351930d4f809f96886e 와 같은 이상한 영문과 숫자가 있습니다.
- 이를 커밋 아이디 라고 합니다.
- 커밋 아이디는 특정 커밋을 가리키는 절대적인 이름이고, 명시적 참조 값입니다.
- 커밋 아이디는 다수의 커밋을 구분할 수 있는 키이며, 브랜치나 태그 등에도 많이 사용됩니다.
SHA1
- 커밋 아이디가 이렇게 복잡한 영어와 숫자로 된 이유는 SHA1 이라는 해시알고리즘을 사용하기 때문입니다.
- SHA1 해시키 값은 40 자리의 복잡한 hexa 값으로 되어 있습니다.
- 깃은 스테이지 영역의 변경된 내용을 기반으로 SHA1 해시키를 생성합니다.
- 따라서 SHA1 해시는 중복되지 않은 고유의 키를 생성할 수 있는 장점이 있습니다.
- 깃이 SHA1 해시를 이용하는 것은 콘텐츠 추적과 분산형 저장 관리를 운영하면서 충돌을 방지하기 위해서입니다.
단축키
- SHA1 해시키는 매우 복잡한 모양의 영어와 숫자로 되어 있습니다.
- 해시는 40자리의 16진수로 입력하다 실수로 잘못 입력할 가능성이 높습니다.
- SHA1 해시키는 매우 큰 숫자이기 때문에 고유 접두사로 간략하게 사용할 수 있는데, 해시의 앞쪽 7자만으로도 중복을 방지하면서 전체 키 갑을 사용할 수 있습니다.
- 해시는 매우 큰 값으로 웬만해서는 앞쪽 숫자 값이 변경되는 경우가 드뭅니다.
커밋 로그
- 깃은 터미널 기반의 응용 프로그램입니다.
- 깃의 로그는 저장소 커밋 기록들을 확인할 수 있습니다.
- 또 커밋 메시지, 아이디도 확인할 수 있고, 브랜치 경로 등을 분석할 수 있는 옵션들도 제공합니다.
간략 로그
- 커밋 메시지를 여러 줄 작성했다면 일반적인 로그 정보를 복잡하게 느낄 수 있습니다.
- 로그 옵션 중에서 --pretty-short 를 사용하면 로그를 출력할 때 첫 번째 줄의 커밋 메시지만 출력합니다.
- 특정 커밋의 상세 정보도 확인할 수 있습니다. 특정 커밋의 상ㅅ 정보를 확인하고 싶다면 show 명령어를 사용합니다.
$ git show 커밋ID
특정 파일의 로그
- 전체 커밋과 달리 특정 파일의 로그 기록만 볼 수도 있습니다.
- 이때는 log 명령어 뒤에 파일 이름을 적어 주면 됩니다.
- log 명령어의 옵션은 매우 다양합니다.
--p 옵션 : diff 기능(수정한 라인 비교)을 같이 포함하여 출력할 수 있습니다.
--stat 옵션 : 히스토리를 출력합니다.
--pretty=oneline 옵션 : 각 커밋을 한 줄로 표시합니다.
diff 명령어
- diff 명령어는 커밋 간 차이를 확인합니다.
- 보통 리눅스나 macOS 같은 유닉스 계열의 운영체제에는 유용한 diff 명령어가 있습니다.
- 깃 또한 초기 시작은 리눅스 커널을 개발하려는 것이었기 때문에 유사한 기능을 하는 diff 명령어를 제공합니다.
파일 간 차이
- 깃의 장점은 파일들의 수정 이력을 커밋이라는 형태로 구분할 수 있다는 것입니다.
- 앞에서 살펴보았듯이, 깃은 커밋으로 파일들의 수정 내역을 추적합니다.
- 파일 수정이란 파일 내용 일부가 수정, 추가, 삭제되는 것을 의미합니다. 개발하면서 수많은 소스 코드가 수정, 추가, 삭제되곤 합니다.
- 깃은 커밋을 기준으로 이러한 파일들의 수정 이력을 비교해 볼 수 있는 diff 기능을 제공합니다.
- diff 기능으로 파일의 수정 및 변경 내역을 쉽게 파악할 수 있습니다.
워킹 디렉터리 vs 스테이지 영역
- 아직 add 명령어로 파일을 추가하지 않은 경우, 워킹 디렉터리와 스테이지 영역 간 변경사항을 비교할 수 있습니다.
- index.html 파일을 수정합니다.
<!DOCTYPE html>
<html>
<head>
<meta charset=“utf-8” />
<meta name=“viewport” content=“width=device-width, initial-scale=1”>
<title> BeomHeeJo</title>
</head>
<body>
<h1>헤더 추가</h1>
<h2>깃을 이용하면 소스의 버전 관리를 쉽게 할 수 있습니다.</h2>
</body>
</html>
커밋 간 차이
- 스테이지 영역에 있는 수정된 파일을 아직 커밋하지 않았다면, 최신 커밋과 변경 내용을 비교하여 볼 수 있습니다.
- HEAD 는 마지막 커밋을 가지고 있는 포인터입니다.
- HEAD는 최근의 커밋 중 가장 마지막 커밋의 위치를 가리키는 값입니다. HEAD를 이용하면 최신 커밋과 이전 커밋을 비교하여 출력할 수 있습니다.
정리
- 커밋 작업은 깃에서 소스 코드를 관리하는 첫 단추입니다.
- 너무 많은 코드를 수정한 후 커밋하는 것보다는 작은 단위로 코드를 수정한 후 커밋하는 것을 추천합니다.
- 커밋의 수정 부분이 적을수록 검토하기 쉽고, 오류도 쉽게 찾을 수 있습니다.
728x90
'버전관리' 카테고리의 다른 글
[Git] 6장 브랜치 (0) | 2022.06.19 |
---|---|
[Git] 5장 서버 (0) | 2022.06.19 |
[Git] 3장 깃 개념 잡기 (0) | 2022.06.18 |
[Git] 2장 깃과 소스트리 설치 및 환경 설정 (0) | 2022.06.18 |
[Git] 1장 깃과 버전관리 (0) | 2022.06.18 |
이 글을 공유하기