[Git] 깃 실속있게 정복하기 Part 1

2023. 4. 23. 17:56Git

반응형

Git의 개념부터 기본 명령어를 설명합니다.
clone, add, commit, push, pull, checkout, branch, merge, rebase

Git 이란?

위키백과에서 Git을 설명한 내용을 보면 다음과 같다.

“컴퓨터 파일의 변경 사항을 추적하고 여러 명의 사용자 간에 해당 파일들의 작업을
조율하기 위한 스냅샷 스트림 기반의 분산 버전 관리 시스템이다.”


가볍게(?) 한 문장으로 잘 표현한 것 같다. 변경을 추적하고 작업을 조율한다는 것이 무엇인지,
스냅샷 스트림이 무엇인지, 분산 버전 관리 시스템이 무엇인지 알아보자.

Git 은 아래 두 가지 상황을 커버한다.

Image 1. 버전 관리의 어려움 1

첫 번째, 위 사진처럼 파일들을 관리하게 되면 어떤 파일이 최신 파일이며
각 파일이 어디가 어떻게 변경됐는지 알기 어렵다.

Image 2. 버전 관리의 어려움 2

두 번째, 공유 파일을 여러 명이 동시에 편집하게 될 경우
먼저 작성한 사람의 작성 내용(v1)이 마지막에 작성된 내용(v2)으로 덮어써지는 경우도 있다.

Git은 소스 코드가 변경된 이력을 쉽게 확인할 수 있고, 특정 시점에 저장된 버전과 비교하거나
특정 시점으로 되돌아갈 수 있게 해 준다. 또 내가 올리려는 파일이 누군가 편집한 내용과 충돌한다면,
서버에 업로드할 때 경고 메시지를 띄어 순조롭게 합칠 수 있도록 도와준다.

스냅샷 스트림

Git은 다른 VCS와는 다른 방식으로 변경 사항을 관리한다.
기존 VCS 방식은 파일 세트로 저장하고 데이터와 시간 경과에 따라 각 파일에 적용된 변경 사항을 관리한다.
이를 델타 기반 버전 제어라고 한다.

Image 3. 델타 기반 버전 제어

Git 정식 홈페이지에서 다음과 같이 말한다.

“Snapshots, Not Differences”

Image 4. Git의 스냅샷 스트림1

Git 은 작은 파일 시스템의 일련의 스냅샷으로 관리한다.
Git은 Commit 한 시점의 프로젝트 전체 스냅샷을 찍고, 스냅샷에 대한 참조를 저장한다.
변경되지 않은 파일의 경우에는 똑같은 파일을 반복해서 저장하지 않고 이전에 저장한 동일한 파일의 링크를 저장하여 관리한다.

Image 5. Git의 스냅샷 스트림2

분산형 버전 관리 시스템(DVCS)

중앙집중형 버전관리 시스템(CVCS)과 비교하면 다음과 같다.

Image 6. 로컬 버전 관리 시스템과 중앙집중형 버전관리 시스템(CVCS)

위 이미지(Image 5)를 보면 CVCS에서 project를 가져올 때는 Client에 최신의 코드만 받아온다.

Image 7. 분산형 버전 관리 시스템(DVCS)

반면에 DVCS는 저장소를 통째로 받아온다.
즉, 소스 코드뿐만 아니라 변경 이력까지 받아오면서 Client의 컴퓨터 또한 완전한 저장소가 된다.

이렇게 되면, 저장소를 받아온 이후에 서버와는 별개로 자신의 로컬에서 개발을 진행할 수 있고, 보다 빠른 UX를 경험할 수 있다.

Git 기본

Image 8. Git 동작 메커니즘

git clone

원격 저장소의 내용을 통째로 다운로드하는 명령어
이때 .git폴더가 생성되고, .git폴더를 가지고 있는 폴더를 Working Directory라고 한다.

.git폴더가 로컬저장소 역할을 한다. 서버와의 링크와 히스토리 정보를 모두 가지고 있는 폴더다. 이 폴더는 git 명령어를 통해 운영되므로
직접 추가/수정/삭제할 필요가 없다.

git clone [url(https/ssh)]

 

https 방식을 사용할 때는 별 무리 없이 clone 받을 수 있지만 ssh 방식을 사용하려면 일련의 설정들이 필요하다.
아래의 포스팅을 참고하면 되겠다.

[githug ssh 접속 설정하기]

https://medium.com/@june.programmer/github-ssh-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-20b34a9a15f8

 

[Github] SSH 접속 설정하기

SSH에 대한 개념과 SSH방식으로 github repository에 접근하는 방법을 설명한다.

medium.com

git add

Working Directory에 처음 생성한 파일을 추적하거나, 수정한 파일을 Staged 상태로 변경하기 위한 명령어(Modified/UnTracked => Staged)

Working Directory에 처음 생성된 파일은 Git의 추적 대상이 아니며, 히스토리 정보가 없다. add의 의미는 프로젝트에 파일을 추가한다기보다 다음 Commit에 추가한다고 생각하면 좋다. 명령어를 실행하면 파일이 Staging Area에 등록되고 파일의 추가, 수정, 삭제 등 히스토리를 Git이 관리한다.

git add .
git add [파일명]

git commit

Staging 된 파일들을 Local Repository로 등록하는 명령어

명령어를 실행하면 현재 Staging Area에 있는 파일들을 스냅샷으로 만들어 Local Repository에 저장한다. 스냅샷 방식 덕분에 커밋은 매우 가벼우며 히스토리를 통해 특정 시점으로 되돌릴 수도 있다

git commit -m "Commit message…"

git push

Local Repository 저장한 히스토리를 서버에 올리는 명령어

git push -u origin main

git pull

Remote repository 를 다운로드해서 Local repository와 싱크를 맞추는 명령어

git branch

독립적인 작업 공간을 만들어주는 명령어

Image 9. main과 feature branch

작업을 하다 보면 기존 소스 코드나 다른 개발자가 작업하는 코드에는 영향을 주지 않는 독립적인 작업 공간이 필요할 때가 있다.
이때 Branch를 만들면 된다.
Branch는 하나의 커밋과 그 부모 커밋들을 포함하는 작업 내역으로 기억하면 된다. Branch도 놀랍도록 가볍다고 한다. Branch는 특정 Commit에 대한 참조(reference, pointer 라고도한다)에 지나지 않기 때문이다. 그래서 Git의 예찬론자들은 다음과 같이 말한다고 한다.

“Branch를 서둘러서, 그리고 자주 만드세요”

git branch [브랜치명]

git checkout

특정 시점 Commit으로 이동하거나 특정 Branch로 Working Directory를 전환하는 명령어

git checkout [commit id] / [branch 명]

Git 2.23부터는 checkout을 대신할 수 있는 switch, restore가 도입되었다.

위에서 설명한 것처럼 checkout은 두 가지 기능을 한다.
1. 특정 시점의 Commit으로 이동
2. Working Directory 전환

checkout 명령어는 지나치게 많은 기능을 하나로 처리하고 있어서 직관적이지 않았다. Git은 더 나은 인터페이스 제공을 위해서 checkout의 기능을 switch, restore로 분리했다.

git switch: 브랜치 변경/생성

git switch -c feat/new-feature 

* -c 옵션은 이동하려는 브랜치가 없을 경우 새로 생성

git restore: working directory의 파일 복원

git restore .   << 전체 파일 복원
git restore [file name]  << 특정 파일 복원

git merge

Branch를 병합하는 명령어

특정 기능을 개발하기 위해 만든 Branch는 개발이 완료된 이후에 원래 소스 코드에 반영될 필요가 있다.
이때 merge를 하면 되는데 merge는 두 개의 부모 Commit을 가리키는 특별한 Commit을 만든다. 이는 두 부모의 모든 작업 내역을 포함한다는 의미이다.

git rebase

Branch를 병합하는 명령어

Branch를 병합하는 방법은 merge뿐만 아니라 rebase도 있다.
그렇다면 rebase와 merge의 차이점은 무엇인지 알아보자.

Merge vs Rebase

Image 10. Merge 와 Rebase 의 git log 차이

Merge

git의 병합 기법 중 하나이다.
Merge는 병합되는 Branch의 Commit log를 그대로 유지한다.

장점
1. Git log를 보면 각 병합이 발생한 방법과 시기가 표현되어 있어서 전체 기록을 볼 수 있다.
2. 따라서 실수를 찾고 해결하기가 쉽다

단점
1. 로그와 기록을 철저하게 관리해야 하며 서투르게 관리될 경우 장점을 잃어버린다.
2. UX가 좋지 못하다.

출처:   https://blog.carbonfive.com/always-squash-and-rebase-your-git-commits/

Rebase

git의 병합 기법 중 하나이며,
병합되는 Commit들을 모아서 다른 Commit에 떨궈 놓는다.
Rebase라는 이름처럼 병합되는 Commit들의 base를 병합하는 Commit으로 옮긴다고 생각하면 된다.
이에 따라 Commit log가 한 줄로 만들어져 보기 편하다.

장점
1. Commit log가 선형이어서 보기 쉽다.
2. Commit 이동이 쉽다.

단점
1. 병합되는 Branch의 Commit log를 삭제하므로 해당 Commit이 병합된 시기와 방법을 알 수 없다.

Mix Merge and Rebase

회사에 따라, 프로젝트에 따라 Commit log를 어떻게 관리할지 다를 수 있다.
어떤 상황/리더에 따라서 Branch를 병합할 때 Merge를 사용할지 Rebase를 사용할지 다를 것이다.
여기서는 Merge와 Rebase를 적절히 혼합해서 사용하는 방법을 설명한다.

여러 명의 개발자들이 프로젝트를 진행하면 각자 맡은 기능을 구현하기 위해 Main으로부터 Branch를 만들어서 작업한다.
그뿐만 아니라, Branch에서 작업을 하다가도 Branch의 Branch를 만들어서 작업할 때가 많다. 이런 상황에서 Merge와 Rebase를 적절히 섞어 쓰면 되겠다.

Image 11. branch에 branch를 만든 commit log

위에서 설명했던 것처럼 내가 맡은 특정 기능을 구현하려고 이것저것 시도하기 위해 F 브랜치에 F`브랜치를 하나 더 만들었다.
F`브랜치에서 하던 작업이 마무리되어 F브랜치로 병합하려고 할 때 Rebase를 사용하면 좋겠다. F`브랜치는 결국 특정 기능을 구현하기 위한 여러 시도 중 성공한 케이스이다. 실패한 케이스들을 굳이 log에 남겨서 Commit log를 더럽힐 필요는 없기 때문이다.

Image 12. 사소한 commit은 Rebase

이후 특정 기능을 성공적으로 구현했고, 이를 Main에 반영할 때에는 Merge를 사용하면 좋겠다.
특정 기능의 구현 여부는 개발 과정에서 큰 포인트가 될 수 있기 때문에 이는 충분히 log로 관리될 필요가 있기 때문이다.

Image 13. 중요한 기준점이 될 수 있는 commit은 Merge
 

마무리

Part 1에서는 Git 개념과 기본 명령어에 대해서 소개했다.
Part 2는 Commit history를 이리저리 옮겨 다니기 위해 HEAD와 상대참조에 대해서 설명하려고 한다.

** 사실과 다른 것이 있다면 언제든지 조언 부탁드립니다.

반응형

'Git' 카테고리의 다른 글

[Git] 깃 실속있게 정복하기 Part 3  (0) 2023.04.23
[Git] 깃 실속있게 정복하기 Part 2  (0) 2023.04.23