본문 바로가기
Development/DevOps

[Git]그래서 Git이 뭔데?! Git 이론 정리

by 다봄이 2020. 10. 8.

인공지능 교육과정에 퍼실리테이터로 참여한지 어느덧 한 달이 지났다. 초반에 깃허브 관련한 질문을 받으며 깃 명령어 사용법보다는, 깃의 사용 이유 등 이론적인 내용을 짧게나마 얘기할 필요가 있었기에, 깃의 이론 위주로 정리했던 자료인데 공유 요청이 들어와서(ㅎㅎ) 슬쩍 가져왔다. 제목도 그대로...


Git, 알고 사용하자!

초반에 환경 세팅 부분을 진행하며 많은 분들이 github 사용에 어려움을 호소하였습니다.
git은 개발자로서 가장 많이 사용하게 될 툴이지만, 사용하기 까다로워 익숙해지는 데 시간이 꽤 걸린다는 흠이 있지요. 그렇다면 그 놈의 깃이 도대체 뭔지!! 뭐길래 우리를 이렇게 힘들게 하는지!! 도대체 이 에러는 왜 발생하는지!! 원리부터 알아보도록 합시다. 알고 쓰는 것과 모르고 쓰는 것에는 많은 차이가 있으니까요...!

git과 github

우리는 git을 쓰기 위해 github를 사용하고 있습니다. 그런데, git과 github의 구체적인 역할과 차이점은 무엇일까요?

git : 소프트웨어 버전 관리 방식

git을 이해하기 위해서는 우선 소프트웨어 버전 관리 방식을 알아야 합니다. 소프트웨어 버전 관리 방식에는 크게 3가지가 있습니다. 현재는 소프트웨어 버전 관리로 git을 사용하지만, 그 이전에는 SVN을 사용했었다고 합니다.

  • 공유 폴더 방식 : 버전 관리 자료가 로컬 컴퓨터의 공유 폴더에 저장되어 관리된다.
    • ex. 윈도우의 폴더 공유
  • 클라이언트 서버 방식 : 버전 관리 자료가 중앙 시스템(서버)에 저장되어 관리된다.
    • 서버의 자료를 개발자별로 자신의 PC(클라이언트)에 복사하여 작업한 후 변경 내용을 서버에 반영한다.
    • 모든 버전 관리는 서버에서 수행된다.
    • SVN
  • 분산 저장소 방식 : 버전 관리 자료가 하나의 원격 저장소와 분산된 개발자 PC의 로컬 저장소에 함께 저장되어 관리된다.
    • 개발자별로 원격 저장소의 자료를 자신의 로컬 저장소로 복사하여 작업한 후 변경 내용을 로컬 저장소에서 우선 반영(버전 관리)한 다음 이를 원격 저장소에 반영한다.
    • Git

즉, git은 분산 버전 관리 시스템이네요! 구체적으로, git은 로컬 저장소에서 버전 관리를 운영하는 시스템, github는 내가 로컬에서 git으로 관리하는 자료를 저장하고 다른 사람들과 공유하기 위한 서버입니다. github 말고도 gitlab에서 자료를 저장하고 공유할 수도 있습니다!

git을 사용하는 이유

이제 git을 버전 관리를 위해 사용한다는 점을 어렴풋이 알게 되었습니다. 그런데 이 버전관리는 왜 필요할까요? 간단한 예시를 하나 들어 봅시다.

당신은 카카오톡 개발자입니다. 카카오톡의 현재 버전은 8.9.7입니다. 
당신은 8.10.7으로의 업데이트를 위해 동료들과 열심히 기능을 개발하고 있지만, 실행이 되지 않는 문제가 발생했습니다! 
이 때는 다시 버전 8.9.7로 되돌려야 하겠지요. 그러나 너무 많은 수정이 발생하여 원래 코드가 뭐였는지 기억할 수가 없습니다...

이와 같은 상황을 막기 위해 나온 것이 버전 관리 시스템(VCS)입니다. 처음에는 버전 8.9.7 코드, 8.10.7 코드, 나중에 나올 버전 8.11.7 코드 등을 모두 서버에 따로 저장하여 사용하였습니다. 그러나 이 방법도 서버가 터질 수도 있으니 안전하지 않기 때문에, 백업을 할 수 있는 방식을 떠올렸습니다. 개발자 각각의 컴퓨터에 저장하고, 서버가 터질 경우 개발자 중 한 명의 컴퓨터에 저장해두었던 버전을 다시 서버로 올리고, 다른 사람들은 그것을 다운받으면 될 수 있도록, 그리고 개발자 컴퓨터가 고장나면 서버에서 다운받을 수 있도록이요.

바로 이 방법처럼 여러 대의 컴퓨터(각각의 개발자 컴퓨터)와 하나의 메인 서버가 소통하는 방식이 Git(각각의 개발자 로컬 컴퓨터)과 Github(메인 서버)의 관계입니다. 이제, git을 사용하는 이유를 정리하면 아래와 같을 것입니다.

  • 자유롭게 코드의 수정, 추가, 삭제가 가능하다.
  • 필요할 경우 이전 버전으로 되돌릴 수 있다.
  • 같은 파일을 여러 명이 동시에 수정하는 경우 등, 충돌이 일어나는 지점을 알려주기 때문에 여러 사람과 동시에 개발하는 것이 편리하다.

스냅샷과 커밋 기록

이것이 어떻게 가능하냐구요? 특정 시점의 진행 상황을 저장해두기 때문에, 그 시점으로부터 시작하거나 이전 시점으로 돌아갈 수 있는 것입니다.

깃허브에서는 특정 시점의 진행 상황을 snapshot이라고 합니다. snapshot은 40자의 문자열로 저장되는데, 한 번 커밋 하면 하나의 snapshot이 생성됩니다. 구체적으로 예시를 볼게요.

log

노란색 글씨로 commit 옆부분에 알파벳과 숫자 조합이 보이시나요? 이것이 바로 40자의 문자로 저장된 snapshot입니다. 좀 더 직관적으로는 커밋 기록이라고 불러요.

커밋을 한 번 할 때 마다 어떤 내용이 저장되었는지 이렇게 기록이 쌓이기 때문에 마지막 커밋 시점으로부터 다음 작업을 진행하게 되며, 필요할 경우 특정 커밋 시점으로 돌아가서 작업을 진행할 수 있게 되는 것입니다.

커밋 단위와 커밋 메시지

따라서, 해당 시점이 어떤 작업을 한 시점인지 알려주기 위해 커밋 메시지를 적는 거랍니다. 위의 사진을 참고해서 보면, 밑에서 두 번째 커밋에는 [Create] 0918 md & Daehyuns' solution 이라는 메시지가 붙었네요. 이 메시지를 보면 무슨 작업을 한건지 한 눈에 들어오나요?

이처럼 커밋은 해당 작업 시점이기 때문에, 언제 커밋을 할 것인지를 나누는 것도 중요한 문제입니다. 일반적으로는 하나의 기능을 완성했을 때 커밋을 하곤 합니다.

또한, 커밋 메시지를 봤을 때 해당 작업 내용이 무엇인지 직관적으로 알 수 있게 하는 것 또한 중요한 문제랍니다. 이것도 규칙이 정해져 있지는 않지만, 일반적으로 [Create], [Update] 등과 같은 태그를 붙여서 해당 작업이 무슨 작업인지 알려주고, 그 옆에 간략히 작업 내용을 설명하는 방법을 흔히 사용합니다. 또한, 다양한 기능이 들어가는 서비스에서는 [Client] [Server] [Docker] [Infra] 등을 태그로 달아두기도 합니다.

커밋 히스토리 추적

그렇다면, 이 커밋 히스토리는 어떻게 확인할 수 있을까요? 크게 두 가지 방법이 있습니다.

  • git log

    • 터미널에서 git log 명령어를 입력하시면 위에 보신것과 같은 커밋 히스토리를 쭉 확인하실 수 있습니다.
    • 로그를 종료하실 땐 q 를 입력하시면 터미널로 돌아올 수 있답니다.
  • 깃허브에서 확인

    log

    • 깃허브에서도 브랜치별로 커밋 히스토리를 확인할 수 있습니다.
    • 7자리 문자열 버튼을 누르시면 해당 커밋의 구체적인 정보를 보실 수 있어요.

Git workflow

gitflow

기본 깃허브 워크플로우를 이해하기 위해 위 그림을 먼저 봅시다. working directory는 본인이 현재 작업하고 있는 폴더, 그리고 git init 명령어를 통해 .git폴더를 생성한 디렉토리입니다.

  • 작업을 진행한 후, git add 명령어를 통해 스테이징 영역에 올립니다. 스테이징 영역에 올라온 파일부터는 깃허브가 '추적한다'고 표현합니다.
  • git commit -m "Message" 명령어를 통해 스테이징 영역의 모든 파일을 커밋하여 HEAD(최종 확정본)에 반영합니다.
  • git push 를 통해 원격저장소(깃허브)에 반영되는 내용은 바로 이 HEAD 입니다. 즉, add만하고 commit하지 않으실 경우 push할 수 없습니다.

Stage area

스테이징 영역을 두는 이유는 무엇일까요? 바로 깃을 사용하는 이유를 생각해보시면 됩니다. 깃은 버전 관리 시스템이라고 위에서 말씀드렸죠. 그렇다면 스테이징 영역을 두는 이유도 이와 연관이 있겠지요?!

깃의 스테이징 영역은, 안정된 버전 관리를 위한 중간 단계입니다. 예를 들어볼게요.

git add를 통해 몇 개의 파일을 스테이징 영역에 올려두었습니다. 그런데 그 중에 버그가 있네요!!

이처럼 스테이징 영역에서 오타나 오류를 발견할 수 있으면 최종 확정본에 반영하기 전에 수정할 수 있습니다.

커밋 히스토리 받아오기

여러 명과 작업을 진행하는 경우도 그렇지만, 혼자서 여러 컴퓨터를 사용해서 작업을 진행하게 되는 경우가 있을 것입니다. 이럴 경우 각 컴퓨터의 커밋 히스토리가 다르겠죠?!

회사 컴퓨터로 작업한 내용을 푸시하였습니다. 그런데 수정사항이 생겨서 수정하다가 푸시를 안 하고 퇴근했어요.
집에와서 노트북으로 원격 저장소에 푸시한 내용을 받아와서 수정 사항이 있던 부분을 수정하고 푸시합니다.
다음날 회사 컴퓨터로 작업하려니, 충돌이 일어났어요!!

이 경우는 회사 컴퓨터와 원격 저장소의 커밋 히스토리가 다릅니다. 왜 그런지 눈치 채셨나요? 집 노트북을 통해 한 번 더 커밋하고 푸시하였으니, 원격 저장소의 커밋 기록은 회사 컴퓨터의 커밋 기록보다 1개 더 많기 때문입니다. 이럴 경우 문제가 발생하게 됩니다. 문제를 방지하기 위해 이미 작업한 내용을 받아와야겠지요. 이 때는 git pull 명령어를 통해 받아올 수 있습니다.

  • git pull origin master 와 같은 방법으로 변경된 커밋 기록을 받아옵니다.
  • 작업을 시작하기 전, 풀 하는 습관을 들이세요!! 오류를 사전에 방지할 수 있습니다. 커밋 히스토리가 다르다면, 생각보다 많은 문제가 발생합니다.

그런데 원격 저장소에 커밋 히스토리가 업데이트 된 줄 모르고, 풀 하지 않은채로 로컬에서 작업하고 커밋해버렸습니다!! 이 경우에는 로컬과 원격 두 커밋 히스토리가 완전히 달라지는데요, 이러한 상황을 해결할 수 있는 가장 빠른 방법은 stash입니다.

  • git stash
  • 위 내용은 추후에 깃허브 마스터하기에서 다루도록 하겠습니다! 오늘은 깃허브의 흐름에 집중해보는 시간이니까요:)

원격저장소에서 파일 받아오기

원격저장소에 올라와 있는 파일을 가져와서 작업하게 될 경우가 많습니다. 협업할 때도 그렇고, 대표적으로 오픈소스 프로젝트를 진행할 때가 그렇지요. 이 때는 주로 git clone 내지는 git fork 를 사용하게 될 것입니다. 그렇다면 클론과 포크의 차이는 무엇일까요?

클론

깃허브에서 다른 사람의 레포를 내 로컬에 복사하여 새로운 로컬 저장소를 만드는 기능. 클론한 원본 레포를 remote 저장소 origin 으로 갖고 있습니다. 권한이 없는 경우 해당 저장소로 푸시하지 못하기 때문에 권한 설정이 필요합니다.

권한이 있다면 푸시할 수 있지만, 마스터 프로젝트 보호를 위해 브랜치에서 작업하여 pull request 를 보냅니다. 그러면 다른 팀원들이 코드 리뷰 후 merge 하는 과정을 보통 거칩니다. 이 때 머지 규칙은 각각 프로젝트별로, 혹은 팀별로 다릅니다.

머지하기 전, 혹은 작업하기 전엔 반드시 변경사항을 받아오는 pull 과정을 통해 변경사항을 받와야 합니다. 그렇지 않으면 컨플릭(conflict)이 발생합니다!!!

포크

깃허브에서 다른 사람의 레포를 내 레포로 복제하는 기능. 포크로 찍어서 복사하는 것과 같아서 fork라고 불립니다(믿거나 말거나). 내 레포로 fork 해온 저장소는 original repository와 연결되어 있어서, 원본 레포에 어떤 변화가 생기면 fork된 나의 레포로 반영할 수 있습니다.

포크한 레포의 변경사항을 original 레포에 적용하고 싶으면 해당 저장소에 pull request를 보내야 하는 것도 같습니다. 차이점은 원본을 내 저장소로 찍어오느냐 아니냐의 차이!

꼭 봐주세요! 참고 자료

가장 간단하지만 가장 많이 쓰는 깃허브 사용법과 명령어를 정리해둔 내용입니다.

git - 간편 안내서

아래 비디오는 깃 플로우에 대한 설명입니다. 브랜치를 포함해서 우리가 깃을 어떻게 사용하는지 잘 설명되어 있어요.

https://www.youtube.com/watch?v=EzcF6RX8RrQ&t=1116s

아래 글에는 깃 커밋 준수사항과 커밋 메시지 작성 방법이 아주 잘 정리되어 있습니다.

깃(Git) 커밋 가이드

'Development > DevOps' 카테고리의 다른 글

[Git]Git 입문자를 위한 Github 사용법  (2) 2020.08.07

댓글