[Git]Git으로 협업하기

Inung_92·2024년 10월 28일
1

버전관리

목록 보기
1/1
post-thumbnail

개념

Git이란?

버전 관리 시스템(Version Control System)의 한 종류로 스냅샷 기반의 데이터 저장을 통해 성능에 중점을 둔 분산 버전 관리 시스템

Git의 작동 구조

  • 스테이징 : git add [파일명]를 통해 Staging Area라는 논리적 영역에 스테이징 상태로 변경
  • 스냅샷 : git commit -m ""을 통해 스테이징 상태의 파일의 스냅샷을 저장하고, 해시값 부여
  • git push를 통해 커밋된 변경 사항을 원격 저장소로 전송

Git의 논리적 구조

  • 분산 버전 관리 시스템
    - 독립적 로컬 저장소 사용으로 전체 코드베이스의 복사본을 저장
    - 중앙 서버에 문제가 발생해도 각 로컬에서 지속적 작업 가능으로 중앙 서버 의존성 감소
  • 스냅샷 기반의 데이터 저장
    - 파일의 변경분 저장이 아니라, 각 커밋 시점의 전체 프로젝트 상태를 스냅샷으로 저장
    - 변경되지 않은 파일은 이전 스냅샷을 참조하여 중복 저장 방지
  • 해시(Hash)로 관리되는 객체
    - SHA-1 해시를 사용해 고유하게 식별
    - 해시를 통해 데이터의 변경 여부를 확인할 수 있어 무결성을 보장
  • 트리(Tree) 구조
    - 디렉토리 구조와 파일에 대한 정보를 담고 있는 트리를 통해 전체 구조를 표현
    - 트리 객체는 블롭(blob) 객체와 다른 트리 객체를 가리킴

Git의 객체 모델
Git은 내부적으로 4가지 주요 객체를 사용하여 데이터를 관리
1. 블롭(blob) : 파일의 내용 자체를 저장
2. 트리(tree) : 디렉토리와 그 안의 포함된 파일 및 하위 디렉토리를 표현
3. 커밋(commit) : 프로젝트의 특정 시점(스냅샷)을 가리키며, 트리 객체를 참조
4. 태그(tag) : 특정 커밋이나 객체에 별칭을 부여

트리 객체의 역할

  • 디렉토리 표현 : 디렉토리 하나를 표현
  • 연결 구조 : 해당 디렉토리 안의 파일과 하위 디렉토리에 대한 정보를 보유하여 이를 통해 전체 프로젝트의 디렉토리 구조를 나타냄

트리 객체의 구성

  • 모드(mode), 해시(hash), 타입(type), 파일 또는 디렉토리 이름으로 구성되는 여러 개의 엔트리(entry)를 포함
  • 엔트리는 블롭, 다른 트리로 두 가지 타입을 가질 수 있음

트리 객체의 연결 구조 상세

  • 위 프로젝트 구조는 다음과 같다.
  • 블롭 : 각 파일에 대한 객체
    - README.md
    - src/main.py
    - src/utils.py
    - docs/manual.md
  • 트리 : 디렉토리 객체
    - src/
    - docs/
    - root/
  • 커밋 : 루트 트리 객체를 가리키며, 커밋 메세지와 메타데이터를 포함

위 내용을 토대로 시각화하면 다음과 같다.

이렇게 연결하는 이유?

  • 효율적인 데이터 관리
    - 동일한 파일 또는 디렉토리가 변경되지 않으면 이전에 생성된 객체를 재사용
    - 저장 공간 절약이 가능하고, 데이터의 중복을 방지
  • 빠른 변경 추적
    - 해시는 내용 기반으로 생성되어 내용이 변경되면 해시가 달라져 빠른 추적 가능
    - SHA-1 해시로 식별되므로 데이터의 무결성을 보장
  • 브랜치(branch)와 태그(tag)
    - 브랜치는 특정 커밋을 가리키는 가벼운 포인터로 새로운 기능 개발을 위한 독립적 작업 공간
    - 태그는 특정 커밋에 대한 스냅샷 이름을 부여하여 출시 버전 등을 표시하는데 사용

Git의 필요성

  • 효율적인 버전 관리 : 코드의 변경 사항을 시간순으로 기록하여 언제든 이전 상태로 복구 가능
  • 원활한 팀 협업 : 여러 개발자가 동일한 코드베이스에서 동시에 작업할 수 있어 생산성이 향상되며, 충돌 방지에 대한 시스템이 구축
  • 독립적인 개발환경 제공 : 메인 코드베이스에는 영향을 주지 않고, 새로운 기능 개발 등 실험적 작업이 가능
  • 자동화 및 지속적 통합(CI/CD) : CI 도구를 사용하여 코드 변경 시 자동으로 빌드와 테스트를 수행 가능
  • 투명한 코드 리뷰 & 관리 : PR 등을 통한 변경사항 알림과 수정 내용을 GUI로 확인가능하여 효율적인 코드 리뷰가 가능

위와 같은 이유들로 인해 다수의 개발자가 작업하는 환경에서는 Git의 사용법을 숙지하여 코드 관리 및 리뷰에 대한 안정성 및 연속성을 제공하여 생산성을 향상시키는 것이 중요하다.


협업

협업 전략 : Feature Branch WorkFlow

각 개발자의 격리된 작업 환경을 제공하기 때문에 다수의 팀 구성원이 메인 코드베이스를 중심으로 안전하게 새로운 기능을 개발 할 수 있는 전략으로 메인 코드베이스(master)는 항상 버그 프리 상태로 유지할 수 있어 안정적인 상태가 되며, CI를 적용하기도 수월하다.

협업 절차

코드베이스 초기 세팅

로컬 저장소와 원격 저장소 연결
기존에 생성된 로컬 저장소에 새로운 원격 저장소를 연결하고, 로컬 저장소의 데이터를 푸시하는 방식을 의미

git init
git add .
git commit -m "initial commit."
git remote add origin [repository URL]
git push origin master

원격 저장소 코드 내려받기
원격 저장소의 코드를 새로운 로컬 저장소를 생성하여 원격 저장소의 모든 데이터를 내려받는 것을 의미

git clone [repository URL]

작업 브랜치 생성

메인 베이스코드(master)에 직접 작업하는 것이 아닌 새로운 기능 개발을 위한 분리된 작업 브랜치 생성

# 존재하는 브랜치 확인
git branch -r
# 체크아웃
git checkout -b issue-[#이슈번호]
# 없으면 master 기준 생성 후 체크아웃
git checkout -b issue-[#이슈번호] master

변경사항 반영

새로 생성한 브랜치에서 작업을 완료하고, 반영

git status # git
git add . or [some-file]
git commit -m "커밋 메세지 작성"
git push origin issue-[#이슈번호]

커밋 메세지
커밋 메세지는 각자 작업한 변경사항에 대한 내용을 다른 개발자들과 공유한다는 생각을 가지고 작성해야한다. 따라서 다음과 같은 사항에 중점을 두고 작성해야한다.

  • 커밋 내용의 도메인을 명확하게 지정
  • 변경된 코드를 작성하는 것이 아닌 부분별 설명을 작성
  • 이슈를 해결하기 위한 커밋인 경우 이슈 번호를 반드시 명시
  • 사소한 부분이라도 헷갈리지 않도록 일관성 있게 커밋 메세지 작성

다음 예시처럼 작성하는 버릇이 필요하다.

# 구조
헤더 : type(커밋의 성격)
[Black Line]
본문
[Black Line]
바닥글 : 이슈 번호 및 기타 참고 사항

# 일반
git commit -m "
feat: Logging Intercepter 기능 구현

- 서비스 계층 메서드 실행 시 파라미터, 요청자에 대한 자동 logging 구현
- interceptor 구현을 통한 유지보수성 확보
- ...생략
"
git push origin [브랜치명]

# 이슈 해결
git commit -m "
fix : Logging Interceptor 미작동에 대한 이슈 해결

- 서비스 계층에서 메서드 호출 시 interceptor가 관여하지 않던 문제 해결
- DTO 매핑 간 상속의 문제로 인한 정상적인 로직 실행이 불가능
- early return 패턴의 조건 재설정
- ...생략

close : #42
"
git push origin issue-42

헤더에 해당 하는 타입 종류는 다음과 같다.

  • feat : 새로운 기능에 대한 커밋
  • fix : 버그 수정에 대한 커밋
  • build : 빌드 관련 파일 수정 및 방법 변경에 대한 커밋
  • chore : 그 외 기타 수정에 대한 커밋
  • ci : 지속적인 통합과 관련된 커밋
  • docs : 문서 수정에 대한 커밋
  • style : 코드 스타일 혹은 포맷팅 등의 관한 커밋
  • refactor : 코드 리팩토링에 대한 커밋
  • test : 테스트 코드 수정에 대한 커밋

MR(PR)

Merge RequestGitHub에서의 Pull Request와 동일한 기능을 하는 기능으로 GitLab에서 사용되는 용어이다.

개발자가 자신의 브랜치에서 작업한 변경 사항을 메인 브랜치나 특정 브랜치에 병합을 요청할 때 사용한다.

Merge Request 절차
1. 프로젝트 선택 > sidebar의 Merge Request 클릭

2. 새로운 MR 생성

3. source -> target 브랜치 선택

4. 요청 정보 입력

- 요청 제목
- 요청에 대한 간략한 설명
- 예시

	```
	Title : 로그인 기능에 OAuth 2.0 인증 방식 추가

	Description
	- Google과 Kakao 계정을 이용한 소셜 로그인 기능 구현
	- 기존의 자체 로그인 방식과 병행 가능
	- ...생략
	```
- Assignee : 해당 요청을 Assign할 대상 선택
- Reviewer : 코드를 검토하고 리뷰를 요청할 사람 선택
- Create merge request 버튼 클릭

코드 검토


해당 MR의 변경사항에 대한 코드 확인을 통해 코드에 발생 가능한 버그가 있는지 없는지 여부를 확인

Merge

  1. MR 검토 및 코멘트

    - Overview, Commits, Pipelines, Changes를 통해 각각 항목의 변경 사항 확인 가능
    - Approve 버튼을 클릭하여 MR 승인
    - Merge 권한자가 모든 Assignee에게 Approve가 완료됨을 확인하면 Merge 버튼 클릭
    - 만약 추가적인 Comment가 필요한 경우 하단에 작성 후 Comment 버튼 클릭
    - MR 검토 결과 내용이 잘못되었거나 불필요한 요청인 경우 Close merge request 클릭

이슈 관리

Issue 생성

경로

GitLab 리포지토리 - Plan - Issues - 우측 상단의 New Issue 클릭

Issue 등록

  • Title : Issue 제목으로 한눈에 알아볼 수 있는 내용에 대해서 작성
  • Type
    - Issue : 작업이 필요한 항목에 대한 일반적인 항목
    - Incident : 운영 환경에서 발생한 긴급 또는 중요한 문제
  • Description : Issue에 대한 설명이나 예시 코드 등을 기재하여 인식할 수 있도록 도와주는 항목
  • Assignee : 참조 대상 등을 설정
  • Due Date : 기한 설정
  • Label : Issue에 대한 라벨을 통해 유사한 성격의 Issue를 관리

Issue 처리 절차

새 브랜치 생성(Issue 전용)

이슈 작업에 대한 전용 브랜치를 생성한다. 이때 이슈 번호를 포함시켜 생성하면 어떤 이슈에 대한 브랜치인지 인식이 용이하고, 커밋 시 키워드 인식을 통한 처리가 간편해진다.

git checkout -b issue-#이슈번호

#!ex) git checkout -b issue-42
변경사항 반영
git add .
git commit -m "fixes 42 : 변경 내용 설명
- ...생략
"
git push origin issue-42

정상적으로 push가 완료되면 기존과 동일하게 머지 리퀘스트를 작성하여 이슈를 처리한다.

Issue 키워드

Git에서 커밋 메시지를 통해 이슈를 자동으로 닫거나 참조할 수 있는 키워드

자동 Close
  • fixes #이슈번호
  • fix #이슈번호
  • fixed #이슈번호
  • closes #이슈번호
  • close #이슈번호
  • closed #이슈번호
  • resolves #이슈번호
  • resolve #이슈번호
  • resolved #이슈번호
이슈 참조
  • see #이슈번호
  • refs #이슈번호
  • ref #이슈번호
  • references #이슈번호
  • related to #이슈번호
  • part of #이슈번호

예시

#! 병합 시 이슈 자동 닫기
git commit -m "Close #42 : 이슈 해결
- ...생략
"
#! 이슈 참조
git commit -m "Ref #42: 일부 코드 변경
- ...생략
"

오류 해결

Merge Conflicts

두 브랜치에서 동일한 파일의 같은 부분을 수정한 후 병합하려고 할 때 발생하는 문제

오류 메세지

Auto-merging [파일명]
CONFLICT (content): Merge conflict in [파일명]
Automatic merge failed; fix conflicts and then commit the result.

해결 방법
충돌 파일 확인

git status

충돌된 파일 열기

<<<<<<< HEAD
// 현재 브랜치의 변경 내용
=======
// 병합 대상 브랜치의 변경 내용
>>>>>>> branch-name

충돌된 부분을 수동으로 수정 후 아래와 같이 확인

git status

On branch inung
nothing to commit, working tree clean

수정된 내용 스테이징(add)

git add [파일명]

커밋

git commit

필요 시 메세지까지 작성

Non-fast-forward 오류

로컬 브랜치가 원격 브랜치보다 뒤처져 있는 경우에 git push 시도 시 발생

오류 메세지

! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart.

해결 방법
원격 변경 사항 병합

git pull origin master

충돌 발생 시 Merge Conflicts 오류와 동일하게 해결
푸시

git push origin master

Rebase 중 충돌 발생

리베이스를 시도하는 도중에 충돌이 발생하여 진행이 중단되는 경우

[!info]Rebase란?
Git에서 브랜치의 기반을 다른 커밋으로 변경하여 이력을 재구성하는 작업을 의미하며, 브랜치를 병합하는 또 다른 방법으로, 이력 그래프를 보다 깔끔하고 직선적으로 만들어줌

Rebase의 장점

  • 병합 커밋 없이 직선적인 이력을 유지 가능
  • 커밋의 순서를 변경하거나 수정할 수 있음
  • 코드 리뷰나 디버깅 시 이력 파악 용이

주의사항

  • 공유된 브랜치에 대한 Rebase를 할 경우 이력 불일치 문제가 발생
  • Rebase 후에는 기존 이력이 변경되기 때문에 원격 저장소에 강제로 푸시해야하는 위험성 존재

오류 메세지

error: could not apply commit_hash... commit message

해결 방법
충돌된 파일 확인 및 수정

git status

이후는 Merge Conflicts와 동일하게 해결

충돌 부분 수정 및 스테이징

git add [파일명]

리베이스 재개

git rebase --continue

리베이스 중단(필요 시)

git rebase --abort

"Your local changes would be overwritten by checkout" 오류

로컬에서 수정한 파일이 있을 때 다른 브랜치로 체크아웃을 시도하면 발생

오류 메세지

error: Your local changes to the following files would be overwritten by checkout:
    [파일명]
Please commit your changes or stash them before you switch branches.

해결방법
변경 사항 커밋

git add [파일명]
git commit -m "커밋 메세지"

브랜치 전환

git checkout branch-name

"Updates were rejected because the remote contains work that you do not have locally" 오류

원격 브랜치에 로컬에 없는 커밋이 있을 경우 푸시를 시도하면 발생

오류 메시지

error: failed to push some refs to 'origin'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.

해결 방법
원격 브랜치와 병합

git push origin [브랜치명]

충돌 발생 시 해결 : Merge Conflicts와 동일하게 해결
푸시

git push origin [브랜치명]

"fatal: remote origin already exists" 오류

이미 존재하는 원격 저장소를 다시 추가하려고 하는 경우 발생

오류 메세지

fatal: remote origin already exists.

해결 방법
원격 저장소 URL 변경

git remote set-url origin [변경할 URL]

원격 저장소 삭제 후 재추가

git remote remove origin
git remote add origin [추가할 URL]

"LF will be replaced by CRLF" 경고

운영체제 간 줄바꿈 문자 인식 차이로 인해 발생하는 경고

오류 메세지

warning: LF will be replaced by CRLF in filename.ext.

해결 방법

git config --global core.autocrlf false

충돌 방지

작업을 커밋, 푸시하기 전 항상 원격 브랜치의 최신 변경 사항을 가져오는 습관을 가지는 것이 좋다.

git fetch origin
git rebase origin/master
profile
서핑하는 개발자🏄🏽

0개의 댓글