Git

민지킴·2021년 5월 17일
0

Git이란?

Git이란 소스코드를 효과적으로 관리하기 위해 개발된 '분산형 버전 관리 시스템'입니다. 원래는 Linux 소스코드를 관리할 목적으로 개발 되었습니다.

Git에서는 소스 코드가 변경된 이력을 쉽게 확인할 수 있고, 특정 시점에 저장된 버전과 비교하거나 특정 시점으로 되돌아갈 수도 있습니다.

또 내가 올리려는 파일이 누군가 편집한 내용과 충돌한다면, 서버에 업로드 할 때 경고 메시지가 발생됩니다.

Git repository

  • 이력을 관리하는 저장소
    저장소(Git repository)란 말그대로 파일이나 폴더를 저장해 두는 곳입니다. 그런데 Git 저장소가 제공하는 좋은 점 중 하나는 파일이 변경 이력 별로 구분되어 저장된다는 점입니다. 비슷한 파일이라도 실제 내용 일부 문구가 서로 다르면 다른 파일로 인식하기 때문에 파일을 변경 사항 별로 구분해 저장할 수 있습니다.

repository 종류

Git은 원격 저장소와 로컬 저장소 두 종류의 저장소를 제공합니다.

원격 저장소(Remote Repository): 파일이 원격 저장소 전용 서버에서 관리되며 여러 사람이 함께 공유하기 위한 저장소입니다.
로컬 저장소(Local Repository): 내 PC에 파일이 저장되는 개인 전용 저장소입니다.
평소에는 내 PC의 로컬 저장소에서 작업하다가 작업한 내용을 공개하고 싶을 때에 원격 저장소에 업로드 합니다. 물론 원격 저장소에서 다른 사람이 작업한 파일을 로컬 저장소로 가져올 수도 있습니다.

Commit Message 권장 양식

1번째 줄 : 커밋 내의 변경 내용을 요약
2번째 줄 : 빈 칸
3번째 줄 : 변경한 이유

Staging, Index

Git의 '커밋' 작업은 '작업 트리'에 있는 변경 내용을 저장소에 바로 기록하는 것이 아니라 그 사이 공간인 '인덱스'에 파일 상태를 기록(stage - 스테이징 한다고 표현하기도 합니다)하게 되어 있습니다. 따라서 저장소에 변경 사항을 기록하기 위해서는, 기록하고자 하는 모든 변경 사항들이 '인덱스'에 존재해야 합니다.

예를 들어, 10개의 파일을 수정했지만 그 중에 7개만 저장소에 공개하고 싶을 때를 생각해 보세요. 변경한 10개의 파일 중 7개를 선택하는 작업이 바로 '인덱스에 등록' 또는 '스테이징(stage)'이라 표현하는 작업 입니다.

이렇게 인덱스란 가상 공간이 중간에 있는 덕분에 작업 트리 안에 있는 커밋이 필요 없는 파일들을 커밋에 포함하지 않을 수 있고, 파일에서 내가 원하는 일부 변경 사항만 인덱스에 등록해 커밋할 수 있습니다.

브랜치(branch)란?

브랜치란 독립적으로 어떤 작업을 진행하기 위한 개념입니다. 필요에 의해 만들어지는 각각의 브랜치는 다른 브랜치의 영향을 받지 않기 때문에, 여러 작업을 동시에 진행할 수 있습니다.

master 브랜치

저장소를 처음 만들면, Git은 바로 'master'라는 이름의 브랜치를 만들어 둡니다. 이 새로운 저장소에 새로운 파일을 추가 한다거나 추가한 파일의 내용을 변경하여 그 내용을 저장(커밋, Commit)하는 것은 모두 'master' 라는 이름의 브랜치를 통해 처리할 수 있는 일이 됩니다.

'master'가 아닌 또 다른 새로운 브랜치를 만들어서 '이제부터 이 브랜치를 사용할거야!'라고 선언(체크아웃, checkout)하지 않는 이상, 이 때의 모든 작업은 'master' 브랜치에서 이루어 집니다.

checkout

Git 에서는 항상 작업할 브랜치를 미리 선택해야 합니다. 처음에 Git을 설치하게 되면 'master' 브랜치가 선택되어 있죠. 현재 선택된 브랜치가 아닌 다른 브랜치에서 작업하고 싶을 때에는, '체크아웃(checkout)' 명령어를 실행하여 원하는 브랜치로 전환할 수 있습니다. 체크아웃을 실행하면, 우선 브랜치 안에 있는 마지막 커밋 내용이 작업 트리에 펼쳐집니다. 브랜치가 전환 되었으므로 이 후에 실행한 커밋은 전환한 브랜치에 추가됩니다.

stash

커밋하지 않은 변경 내용이나 새롭게 추가한 파일이 인덱스와 작업 트리에 남아 있는 채로 다른 브랜치로 전환(checkout)하면, 그 변경 내용은 기존 브랜치가 아닌 전환된 브랜치에서 커밋할 수 있습니다.

단, 커밋 가능한 변경 내용 중에 전환된 브랜치에서도 한 차례 변경이 되어 있는 경우에는 체크아웃에 실패할 수 있습니다. 이 경우 이전 브랜치에서 커밋하지 않은 변경 내용을 커밋하거나, stash 를 이용해 일시적으로 변경 내용을 다른 곳에 저장하여 충돌을 피하게 한 뒤 체크아웃을 해야 합니다.

stash 란, 파일의 변경 내용을 일시적으로 기록해두는 영역입니다. stash 를 사용하여 작업 트리와 인덱스 내에서 아직 커밋하지 않은 변경을 일시적으로 저장해 둘 수 있습니다. 이 stash 에 저장된 변경 내용은 나중에 다시 불러와 원래의 브랜치나 다른 브랜치에 커밋할 수 있습니다.

rebase

merge 와 rebase 는 통합 브랜치에 토픽 브랜치를 통합하고자 하는 목적은 같으나, 그 특징은 약간 다릅니다.

  • merge
    변경 내용의 이력이 모두 그대로 남아 있기 때문에 이력이 복잡해짐.

  • rebase
    이력은 단순해지지만, 원래의 커밋 이력이 변경됨. 정확한 이력을 남겨야 할 필요가 있을 경우에는 사용하면 안됨.

merge 와 rebase 는 팀 운용 방침에 따라 구별해 쓸 수 있습니다.
예를 들어 이력을 하나로 모두 모아서 처리하도록 운용한다고 치면 아래와 같이 구별해 사용할 수 있습니다.

토픽 브랜치에 통합 브랜치의 최신 코드를 적용할 경우에는 rebase 를 사용,
통합 브랜치에 토픽 브랜치를 불러올 경우에는 우선 rebase 를 한 후 merge

branch 모델

메인 브랜치(Main branch)

'master' 브랜치와 'develop' 브랜치, 이 두 종류의 브랜치를 보통 메인 브랜치로 사용합니다.

  • master
    'master' 브랜치에서는, 배포 가능한 상태만을 관리합니다. 커밋할 때에는 태그를 사용하여 배포 번호를 기록합니다.

  • develop
    'develop' 브랜치는 앞서 설명한 통합 브랜치의 역할을 하며, 평소에는 이 브랜치를 기반으로 개발을 진행합니다.

피처 브랜치(Feature branch)

피처 브랜치는, 앞서 설명한 토픽 브랜치 역할을 담당합니다.

이 브랜치는 새로운 기능 개발 및 버그 수정이 필요할 때에 'develop' 브랜치로부터 분기합니다. 피처 브랜치에서의 작업은 기본적으로 공유할 필요가 없기 때문에, 원격으로는 관리하지 않습니다. 개발이 완료되면 'develop' 브랜치로 병합하여 다른 사람들과 공유합니다.

릴리즈 브랜치(Release branch)

릴리즈 브랜치에서는 버그를 수정하거나 새로운 기능을 포함한 상태로 모든 기능이 정상적으로 동작하는지 확인합니다. 릴리즈 브랜치의 이름은 관례적으로 브랜치 이름 앞에 'release-' 를 붙입니다. 이 때, 다음 번 릴리즈를 위한 개발 작업은 'develop' 브랜치 에서 계속 진행해 나가면 됩니다.

릴리즈 브랜치에서는 릴리즈를 위한 최종적인 버그 수정 등의 개발을 수행합니다. 모든 준비를 마치고 배포 가능한 상태가 되면 'master' 브랜치로 병합시키고, 병합한 커밋에 릴리즈 번호 태그를 추가합니다.

릴리즈 브랜치에서 기능을 점검하며 발견한 버그 수정 사항은 'develop' 브랜치에도 적용해 주어야 합니다. 그러므로 배포 완료 후 'develop' 브랜치에 대해서도 병합 작업을 수행합니다.

핫픽스 브랜치(Hotfix branch)

배포한 버전에 긴급하게 수정을 해야 할 필요가 있을 경우, 'master' 브랜치에서 분기하는 브랜치입니다. 관례적으로 브랜치 이름 앞에 'hotfix-'를 붙입니다.

예를 들어 'develop' 브랜치에서 개발을 한창 진행하고 있는 도중에 이전에 배포한 소스코드에 아주 큰 버그가 발견되는 경우를 생각해 보세요. 문제가 되는 부분을 빠르게 수정해서 안정적으로 다시 배포해야 하는 상황입니다. 'develop' 브랜치에서 문제가 되는 부분을 수정하여 배포 가능한 버전을 만들기에는 시간도 많이 소요되고 안정성을 보장하기도 어렵습니다. 그렇기 때문에 바로 배포가 가능한 'master' 브랜치에서 직접 브랜치를 만들어 필요한 부분 만을 수정한 후 다시 'master'브랜치에 병합하여 이를 배포하려고 하는 것이죠.

이 때 만든 핫픽스 브랜치에서의 변경 사항은 'develop' 브랜치에도 병합하여 문제가 되는 부분을 처리해 주어야 합니다.

fetch

  • 원격 저장소의 데이터를 로컬에 가져오기만 하기
    pull 을 실행하면, 원격 저장소의 내용을 가져와 자동으로 병합 작업을 실행하게 됩니다. 그러나 단순히 원격 저장소의 내용을 확인만 하고 로컬 데이터와 병합은 하고 싶지 않은 경우에는 fetch 명령어를 사용할 수 있습니다.

태그 (Tag)

태그란, 커밋을 참조하기 쉽도록 알기 쉬운 이름을 붙이는 것을 말합니다.

한 번 붙인 태그는 브랜치처럼 위치가 이동하지 않고 고정됩니다.

Git 에서는 일반적으로 이름 정보만을 갖는 '태그(Lightweight tag)'와 보다 상세한 정보를 포함하는 '주석 태그(Annotated tag)', 이 두 가지 태그를 사용할 수 있습니다.

  • 일반 태그(Lightweight tag)
    이름만 붙일 수 있어요

  • 주석 태그(Annotated tag)
    이름을 붙일 수 있어요
    태그에 대한 설명도 포함할 수 있어요
    서명도 넣을 수 있어요
    이 태그를 만든 사람의 이름, 이메일과 태그를 만든 날짜 정보도 포함시킬 수 있어요

보통 '릴리스 브랜치(Release branch)'에서는 주석 태그를 사용하여 설명이나 서명을 넣은 보다 상세한 정보를 포함하는 태그를 사용하고, 로컬에서 일시적으로 사용하는 '토픽 브랜치(Topic branch)'에서는 이름만 만들어 붙이는 태그를 사용합니다.

--amend

--amend 옵션을 지정하여 커밋을 수행하면, 같은 브랜치 상에서 이전에 커밋했던 내용에 새로운 내용을 추가하거나 설명을 수정할 수 있습니다.

사용 하는 경우 :
누락된 파일을 새로 추가하거나 기존의 파일을 업데이트 해야할 때
이전 커밋의 설명을 변경하고 싶을 때

revert

revert 명령어를 이용하면, 특정 커밋의 내용을 삭제할 수 있습니다.
rebase -i 명령어나 reset 명령어를 통해 커밋을 삭제할 수도 있지만, 해당 커밋이 이미 공개된 상태인 경우에는 이러한 삭제 작업을 함부로 하기 어렵습니다.

이러한 경우에는 revert 명령어를 이용해서 특정 커밋의 내용을 지우는 새로운 커밋(B')을 만들어 보다 안전하게 처리할 수 있습니다.

사용하는 경우 :

이전에 작성한 커밋을 안전하게 지우고 싶을 때

reset

reset 명령어를 이용하면 더 이상 필요 없어진 커밋들을 버릴 수 있습니다. 명령어 실행 시 어떤 모드로 실행할 지 지정하여 'HEAD' 위치와 인덱스, 작업 트리 내용을 함께 되돌릴지 여부를 선택할 수 있습니다.

커밋만 되돌리고 싶을 때 (soft)
변경한 인덱스의 상태를 원래대로 되돌리고 싶을 때 (mixed)
최근의 커밋을 완전히 버리고 이전의 상태로 되돌리고 싶을 때 (hard)

cherry-pick

다른 브랜치로부터 특정 커밋을 가져와서 내 브랜치에 넣기

cherry-pick 을 이용하면 다른 브랜치에서 지정한 커밋을 복사하여 현재 브랜치로 가져올 수 있습니다.

사용하는 경우 :

특정 브랜치에 잘못 추가한 커밋을 올바른 브랜치로 옮기려고 할 때
다른 브랜치의 커밋을 현재 브랜치에도 추가하고 싶을 때

--squash

이번에는 병합(merge) 할 때 사용할 수 있는, 조금 특별한 옵션인 '--squash'를 소개합니다.

이 옵션을 지정하여 브랜치를 병합하면 해당 브랜치의 커밋 전체를 통합한 커밋이 추가됩니다.

profile
하루하루는 성실하게 인생 전체는 되는대로

0개의 댓글