Git도 쓸 줄 모르는 개발자 없제?

언젠가만날날·2024년 8월 26일
post-thumbnail

🔢 Git and VCS

Git은 분산 버전 관리 시스템(Version Control System)이다.

이 글에서는 협업에 가히 필수적인 git을 이해하고 활용하기 위한 방법을 소개한다. 우선 버전 관리 시스템에 대해 알아보자.


버전 관리 시스템

정의

버전 관리 시스템(VCS)은 파일 변화를 시간에 따라 기록했다가 나중에 특정 시점의 버전을 다시 꺼내올 수 있는 시스템이다.

쉽게 말해서 파일의 변경점을 관리해주는 프로그램이다.

장점

VCS를 사용하면 파일을 시간에 따라 기록해두었기 때문에, 파일을 잃어버렸거나 망가뜨렸을 때, 파일을 이전 상태로 쉽게 되돌리거나 이전 상태와 비교 할 수 있다. 또한 협업 과정에서 파일을 변경한 사람과 시기를 조회할 수 있다.

종류

  1. 로컬 버전관리 (Local VCS)

    서버 없이 로컬 컴퓨터 안에 데이터베이스를 만들어서 버전 관리를 한다.

  1. 중앙집중식 버전관리 (Centralized VCS)

    서버가 별도로 있고, 파일을 수정하려는 사람이 수정하려는 파일만 로컬 컴퓨터에 다운받아 작업한 후 서버에 업로드한다.

    중앙집중식의 가장 치명적인 단점은 업로드를 받는 서버에 있다. 서버에 문제가 발생하면 그 동안 작업을 할 수 없으며, 서버가 날아가면 각각의 컴퓨터에 있는 ‘수정하려는 파일’을 제외한 모든 프로젝트가 백지화 될 수 있다.

    또한 여러 사람이 같은 파일을 수정하면 충돌이 발생할 수 있다.

  2. 분산 버전관리 (Distributed VCS)

    이 글의 주제인 Git이 이에 속한다.

    서버가 별도로 있는 것은 중앙집중식과 동일하지만, 파일을 수정하려는 사람이 프로젝트 전체를 로컬 컴퓨터에 복제하여 작업한다는 차이점이 있다. 즉, 전체 작업 파일을 내 컴퓨터에 다운받는 것이다.

    때문에 서버에 문제가 발생해도 복제된 파일을 이용해 작업을 지속할 수 있으며, 파일을 수정하고 있는 모든 사람이 각각의 로컬 컴퓨터에 프로젝트를 복제했기 때문에 최종적으로 서버에 올릴 때만 신경 쓰면 수정 시 충돌의 가능성이 크게 줄어든다.


이해

구조

  1. Git은 ‘분산 버전 관리 시스템’ 의 일종이기 때문에, Git은 로컬 저장소라는 이름으로 전체 프로젝트를 작업 폴더에 넣어서 관리한다. 이로 인해 얻는 이점은 다음과 같다.

    1. 굉장히 빠른 속도를 가진다.
    2. 네트워크를 이용하지 않기 때문에 서버에서 새 파일을 받는 것을 제외한 거의 모든 작업을 오프라인에서 할 수 있다.
    3. 당연히 서버에 일시적인 문제가 있어도 작업을 지속할 수 있다.
  2. 작업이 끝나면 Git 원격 저장소에 push(발행)하는데, 로컬 저장소에서의 작업이 끝나면 파일을 메인 저장소와 합치기 전에 Branch라는걸 이용해 각 Branch의 작업이 완료될 시 메인 저장소와 merge 한 후 Branch를 제거하는 ‘가지치기’ 작업이 가능하다.

    ‘가지치기’ 기능 자체를 지원하는 툴은 많지만, Git은 이 기능을 굉장히 가볍고 빠르게 수행한다고 한다.

흐름

  1. 저장소 생성

    1. 새로운 Git repository를 생성한다.
    2. 존재하는 Git repository를 복제한다.

    위 두가지 방법 중 하나로 Git 저장소를 생성한다. 그럼 디렉토리 최상위에 .git이라는 디렉토리가 생성된다.

    • 로컬 저장소는 Git 치하의 세 단계로 구성되어있다.

    대부분 IDE에서 이를 기반으로 파일의 상태를 알려주니, 알아두면 좋다.

    • Working directory, 실제 파일로 이루어진다. (Modified 상태)

    • index(staging area), 준비 영역 역할을 한다. (Staged 상태)
      스테이징으로 불리며, commit 전에 파일의 변경 사항을 확인하고 commit할 파일을 선택할 수 있다. 따라서 변경 사항이 존재하는 파일만 여기로 올 수 있다.

    • HEAD, commit(확정)된 파일이다. (Committed 상태)

      이때 .git과 같은 위치에 .gitignore 파일을 생성하여 Git이 추적하지 않아도 되는 파일이나 디렉토리를 지정할 수 있다. 예를 들어어 빌드 결과물, 로그 파일, IDE 설정 파일 등을 다음과 같이 .gitignore에 추가하면

      /build/
      /dist/
      *.class
      *.jar
      
      *.log
      
      .idea/
      .vscode/
      *.iml
      
      .DS_Store
      node_modules/
      .env

      Git이 해당 파일들의 변경 사항을 무시하게 된다. 특히 .env와 같은 보안상의 문제가 생길 수 있는 파일의 경우, git이 원격 저장소에 올리지 못하게끔 하므로 .gitignore를 이용해야 한다.

  2. add(추가) 와 commit

    1. add를 통해 작업한 파일을 index에 추가한다.
    2. index에 있는 변경 내용을 commit한다.

    다음 과정을 통해 HEAD에 작업한 파일을 집어넣었다. 하지만 HEAD까지도 아직 로컬 저장소 안에 있다.

  3. 원격 저장소로 이동

    로컬 저장소의 작업 내용을 원격 저장소로 push하는 과정이다. 이때 저장소를 만들 때 같이 생긴 master branch를 기반으로 가지치기를 할 수 있다. 즉, 다른 branch를 이용해서 작업을 하고 마지막에 master branch에 merge하는 것이다.

    이러한 가지치기를 전략적으로 이용하여 협업 시 생산성을 증대시킬 수 있다. 이를 branch 전략이라고 하며, git flow 전략이 대표적이다.

    이렇게 생성한 branch를 원격 저장소에 push하기 전에는 다른 사람들이 branch에 접근할 수 없다. 따라서 branch는 작업자들이 서로의 작업물을 침범하지 않고 독립적으로 동시에 작업할 수 있게끔 해준다.

  4. pull(갱신) 과 merge

    pull을 통해 로컬 저장소를 원격 저장소에 맞춰 merge할 수 있다. 이때, 원격 저장소의 변경 내용이 자동으로 로컬 저장소에 fetch(받아지다)되고 merge된다.

    또한 다른 branch의 변경 내용을 받아와서 현재 branch에 merge할 수 있다.

    하지만 항상 merge가 성공하는 것은 아니고, 드물게 conflicts(충돌)가 발생하기도 한다. 여러 사람이 같은 부분을 수정했기 때문에 Git이 헷갈리는 것이다. 이때 Git이 어느 부분에서 conflicts가 생겼는지 알려주며, 사람이 직접 Git에게 어떤게 맞는지 알려주고 merge가 되도록 해야 한다.


사용

로컬 저장소

  1. 새 로컬 저장소를 만든다.

    git init
  2. 로컬/원격 저장소를 clone 하여 가져온다.

    git clone [경로]
    git clone [user]@[host]:[경로]

HEAD 관련

  1. 작업한 파일을 index에 추가한다.

    git add [파일명]

    다음과 같이 작성할 경우 변경 사항이 있는 모든 파일이 index에 추가된다.

    git add .
  2. 변경 내용을 commit한다.

    git commit -m [commit message]

원격 저장소

  1. 기존의 원격 저장소를 clone한 것이 아닐 때, 원격 저장소의 주소를 Git에게 알려준다.

    git remote add origin [주소]
  2. 등록되어있는 저장소들을 조회한다.

    git remote -v
  3. 특정 저장소를 삭제한다.

    git remote remove origin
  4. HEAD에 있는 파일을 원격 저장소로 보낸다.

    git push origin [branch명]

branch 관련

  1. branch의 목록을 확인한다

    git branch
  2. branch를 생성한다.

    git branch [branch명]
  3. (branch를 생성하고) 그 branch로 이동한다.

    git checkout (-b) [branch명]
  4. branch를 삭제한다.

    git checkout -d [branch명]
  5. branch를 원격 저장소로 보낸다.

    git push origin [branch명]

갱신

로컬 저장소를 원격 저장소(의 특정 branch)에 맞춰 pull한다.

git pull (origin [branch명])

병합

  1. 변경사항을 확인할 수 있다.

    git diff [branch명] [비교 대상 branch명]
  2. 다른 branch의 파일을 현재 가지에 merge한다.

    git merge [branch명]

🌿 Git Flow

Git flow는 git에서 branch를 나누는 방법 중 하나이다.


개념

git flow 전략은 협업 시 소스코드의 관리, 출시를 위한 branch management strategy(브랜치 관리 전략) 의 일종이다.


branch 분할

git flow는 branch를 다음 다섯 종류로 나눈다. 이때 master와 develop branch는 필수적으로 필요한 branch이고 나머지는 선택적으로 사용하는 branch이다.

master(main)

제품으로 배포할 수 있는 완성된 branch이며, 보통 CI/CD 파이프라인을 통해 master branch의 변경 사항이 자동으로 실제 서비스에 적용되도록 한다. 따라서 master에 merge 한다는 것은 서비스의 새로운 버전을 배포한다는 뜻이다.

develop

master에서 갈라진 branch로, 개발자들이 코드를 상시적으로 commit하는 branch이다. feature에서 개발된 내용을 가지고 있다.

feature

develop에서 갈라진 branch로, 각 기능별로 개발된 내용을 가지고 있는 branch이다. 이때 branch명을 feat/<기능 이름> 으로 설정한다.
작업이 완료된 후 develop branch로 merge된다.

release

배포 직전 내용을 QA(품질 검사) 하기 위한 branch이다. 따라서 master branch에 merge한다.

hotfix

master로 배포를 하고 나서 버그가 발생하였을 때 이를 고치기 위한 branch이다. 기본적인 역할은 release branch와 비슷하며, develop에 merge하는 경우도 있지만 이미 배포된 버전에서 발생한 문제를 최대한 빨리 해결해야 하기 때문에 master에 merge하기도 한다.


💬 Commit message convention

Commit message convention은 commit을 할 때 commit message를 작성하는 규칙이다.

혼자 프로젝트 할 때 처럼 커밋 메시지를 대충 쓰다가 협업 시 큰 차질을 빚을 수 있다.


개념

변수명과 함수명의 naming convention은 camel case, snake case, pascal case 등이 있다. 이는 프로그램 상에서 강제된 것은 아니지만, 편의를 위해 개발자들끼리 약속한 것이다. commit message에도 이와 같은 convention이 있다.

개인 프로젝트를 혼자 개발할 때에는 commit message를 대충 작성하여도 무관하지만, 팀원과 함께 협업을 할 때에는 그럴 수 없다폐급. 모든 팀원이 이해할 수 있도록 commit message의 형식을 정하는 것이 commit message convention이다.

이 commit message convention은 여러 종류가 있고, 팀원끼리 정의하기 나름이지만 보통 udacity를 많이 사용하므로 본문에서는 udacity를 설명한다.


구조

공백을 기준으로 title, body, footer 영역을 나눈다.

type: Subject

body

footer

title

Title 영역에는 type과 subject를 :(콜론)과 공백으로 구분하여 작성한다.

Type이란 아래와 같이 대략적인 업데이트 작업의 종류를 나타낸다.

Feat새로운 기능 추가
Fix버그 수정
Docs문서 수정
Style로직의 영향이 없는 formatting 등의 코드 변경
RefactorRefactoring
Test로직에 영향이 없는 text 코드 추가
Chore코드의 변경이 없는 build 설정, package manager 변경 등의 기타 변경
DesignUI 디자인 변경
Comment주석 업데이트
Init프로젝트 초기 생성
Rename파일명, 폴더명 수정 혹은 경로 변경
Remove파일, 폴더 삭제
CiCi 설정 파일 변경
Perf성능 향샹

Type 뒤에 이어지는 subject는 commit message의 제목이며, 변경사항을 개조식 구분으로 간결하게 작성한다. 따라서 50자 이내로 작성하여야 하며 마침표를 포함한 특수문자는 사용하지 않는다. 영문으로 작성할 경우 첫글자는 대문자를 쓰고 동사원형을 문장의 맨 앞에 배치하여 명령문 형태로 작성하며 과거시제는 사용하지 않는다.

body

본문 영역으로, 업데이트 내역을, 그 중 무엇을, 왜 변경하였는지 상세히 설명한다. 생략할 수 있으며, 72자를 넘지 않도록 한다.

Issue 추적을 위한 영역이다. Issue tracker의 type과 issue 번호를 다음과 같은 형식으로 작성한다.

[type]: #[issue number]

이때 issue tracker type의 종류는 다음과 같다.

Fixes수정 중
Resolves해결됨
Ref참조할 issue 없음
Related to해당 commit에 관련된 issue 번호

마치며

프로젝트를 진행하다 보면 이따금 예상치 못한 git 관련 이슈가 생길 때가 있다. branch 병합 시 conflicts 뿐만 아니라 401, 403과 같은 이상한 에러가 날 때도 있고, 모종의 이유로 작업을 이전 상태로 되돌려야 하는 경우도 있을 것이다...

하지만 이 정도까지 이해했다면 Git을 활용한 협업에서 큰 어려움은 없을 것이다. 기본적인 구조를 알고 있기 때문에, 최소한의 구글링만으로도 문제를 파악하고 해결할 수 있다는 의미다.

1개의 댓글

comment-user-thumbnail
2024년 8월 27일

와;; 아니.. 제가 여태까지 버전 관리 구조도 모르고 Git을 쓰고 있었단 걸 이제 알았네요.. 진짜로 협업에 도움이 될 것 같은 알찬 내용인 것 같아요. 좋은 글 감사합니다!

답글 달기