다시 시작하는 Git, GitHub 기초 2

Hyuno Choi·2021년 3월 6일
0
post-thumbnail

2021년 3월 6일 밤

저번 포스팅에서 커맨들 라인과 Git의 기초에 대한 내용을 작성하였는데요, 이번 포스팅에서도 Git과 GitHub의 기초에 대해 적어나가겠습니다.

Git을 왜 사용할까?

대학에서 웹 프로그래밍 강의를 들은 적이 있었는데요, 첫 시간에 교수님께서 과제를 GitHub에 제출하고 하시고는 기본적인 커맨드 라인을 알려주셨던 기억이 납니다.
"Git을 왜 사용할까?"라는 질문을 그때 처음으로 해본 것 같습니다.🤔 강의에서는 Git을 사용하는 이유에 대해서 아래의 3개의 이유를 꼽았는데요,

  1. 버전 관리를 위해서(마치 ctrl + z와 같은 기능).
  2. 버전 간 소스코드 비교를 쉽게 하기 위해서.
  3. 협업을 쉽게 하기 위해서.

Git을 일반화하여 버전 관리가 필요한 이유에 대해 알아봅시다.📖 버전 관리가 필요한 이유에 대한 위키백과의 설명인데요, 세세하게 잘 정리되어 있는 것 같아 가져와보았습니다.

  1. 무언가 잘못되었을 때 복구를 돕기 위하여
  2. 프로젝트 진행 중 과거의 어떤 시점으로 돌아갈 수 있게 하기 위하여
  3. 여러사람이 같은 프로젝트에 참여할 경우, 각자가 수정한 부분을 팀원 전체가 동기화하는 과정을 자동화하기 위하여
  4. 소스 코드의 변경 사항을 추적하기 위하여
  5. 소스 코드에서 누가 수정했는지 추적하기 위하여
  6. 대규모 수정 작업을 더욱 안전하게 진행하기 위하여
  7. 가지내기(Branch)로 프로젝트에 영향을 최소화 하면서 새로운 부분을 개발하기 위하여
  8. 접붙이기(Merge)로 검증이 끝난 후 새로이 개발된 부분을 본류(trunk)에 합치기 위하여
  9. 많은 오픈 소스 프로젝트에서 어떠한 형태로든 버전 관리를 사용하고 있으므로
  10. 코드의 특정 부분이 왜 그렇게 쓰여 졌는지 의미를 추적하기 위하여

이 이유들을 종합한 3개의 주제를 통해 구체적으로 알아보도록 하겠습니다.🧐

실수 바로잡기

PPT 자료를 만들거나 문서를 편집할 때 Ctrl + z가 없다면 정말 끔찍할 것입니다.🙄 소스 코드도 마찬가지인데요, 논리적으로 연결되어 있는 코드의 특성상 한 부분의 실수를 놓치면 많은 시간과 노력을 실수를 찾아내는 데 소모할 수도 있습니다.

Git을 비롯한 버전 관리 시스템은 이런 상황에서 큰 도움을 줄 수 있습니다.

  • 문제가 생긴 버전과 이전 버전을 비교해보면서 잘못된 코드를 찾거나
  • 단순히 이전 버전으로 파일을 되돌릴 수 있습니다.

동료와 함께하기

모든 소스 코드 작성과 프로젝트 진행을 혼자 진행한다면 자신만의 방식으로 버전 관리를 해도 괜찮을 것입니다. 그러나 프로젝트의 규모가 커지면 자연스럽게 다른 사람과 함께 프로젝트를 진행하게 됩니다. 이럴 때 각자의 버전 관리 방법을 제멋대로 사용하게 된다면 큰 혼란이 생길 것입니다.🤯

역시 이럴 때에도 버전 관리 시스템이 유용하게 쓰입니다.

  • 자신이 작업한 내용을 원격 저장소에 업로드하고, 원격 저장소의 내용을 자신의 작업 환경에 내려받을 수 있습니다.
  • 수정 사항이 있다면, 누가 어느 부분을 수정했는지 수정 이력을 확인할 수 있습니다.

안전하게 수정하기

여러 팀원이 같은 프로젝트 내의 파일의 서로 다른 부분을 동시에 수정하는 경우를 생각해봅시다. 이때 원격 저장소에서 파일을 가져오고 내가 수정한 파일을 업로드 하는 과정에서 의도치 않게 변경 내용들이 섞여 들어가 프로젝트 뒤죽박죽이 될 위험이 있습니다.

Git에서는 수정 사항마다 원래의 프로젝트 흐름과는 독립적인 가지(Branch)🌱를 만들어 이러한 문제를 예방합니다. 각각의 가지에서 안전하게 수정 작업을 하고, 나중에 본 프로젝트 파일과 합치는(Merge) 과정을 거치는데요, 이때 각각의 수정 사항이 꼬인다면 충돌을 발생시켜 문제 발생을 사전에 예방합니다.

Git에서의 가지치기와 병합, 충돌 문제는 포스팅 뒷부분에서 자세히 다루겠습니다.✍️

Git vs SVN

Git과 함께 버전 관리 시스템으로 많이 쓰이는 것 중 SVN이라는 것이 있는데요, Git 강의이기도 하고 현업에서도 Git이 차지하는 비율이 높아지는 만큼 간단한 차이점만 살펴보고 넘어가겠습니다.🔎

출처 : https://dzzienki.tistory.com/46

일단 Git과 SVN의 가장 큰 차이점은 중앙 집중 관리이냐 분산 관리이냐의 차이입니다. commit과 동시에 중앙 서버에 실시간으로 번경 내역이 반영되는 SVN과는 달리 Git은 commit을 하게 되면 일단 로컬 저장소에만 반영됩니다. 이후 원격 저장소와의 통합을 통해 작업 내용이 원격 저장소에 반영되는 방식입니다.

이러한 차이 때문에 생기는 Git만의 장점이 있는데요,

  1. 여러 사람이 다른 Branch에서 독립적인 작업을 수행할 수 있습니다.
  2. 서버가 마비되더라도 로컬 저장소에서 복구가 가능합니다.

둘의 차이점을 간단하게 표로 정리하면 다음과 같습니다.

GitSNV
수동 저장
오프라인 사용
관리 방식분산 관리중앙 집중

변경 내용 확인하기

<Git을 사용해야 하는 이유> 부분에서 보았듯이 변경 내용을 확인하는 작업은 오류를 잡는데 매우 중요합니다. 가장 간단한 방법으로 bash 창에서 $ diff 파일1 파일2 명령어를 사용하는 방법이 있습니다.

명령어를 입력하면 이렇게 두 파일 간 다른 부분을 보여주는데요, diff 명령어 대신 웹 서비스를 이용할 수도 있습니다.

https://www.diffchecker.com/

Diffchecker라는 사이트입니다. 두 파일의 텍스트를 각각 붙어넣으면 다른 부분을 강조해서 보여줍니다.

Git 자체에서도 변경 내역을 확인할 수 있는데요, 레퍼지토리 페이지에서 확인할 수 있고, $ gitk 명령어를 통해 GUI 툴로 commit 간 차이점을 확인할 수도 있습니다.

gitk를 사용해 commit 간 변경 이력을 확인하는 모습입니다.

Git 레포지토리의 commit 이력 페이지에서도 깔끔하게 변경 이력을 볼 수 있습니다.

변경 이력을 확인하는 GUI 툴은 여러가지가 있는데요, 다음 목록에 있는 것들이 예시입니다.

  1. 내장 GUI $ gitk
  2. Sourcetree
  3. 깃 크라켄
  4. VS Code Git 플러그인 등

Commit

Git에서는 원격 저장소에 push하기 전, 반드시 commit 작업을 수행해야 합니다. 제가 처음 git을 배웠을 때는 commit을 해야하는 이유를 몰라서 commit을 건너뛰고 push만 하는 방법(!)을 찾기도 했었는데요, 지금 생각하면 정말 git을 구글 클라우드처럼 사용했던 것 같습니다.😂

commit 하나는 독립된 하나의 버전을 의미하며 메시지가 포함되어 있습니다. 그리고 Git 초기 설정에서 등록한 사용자명과 사용자 이메일이 commit 이력에 남게 됩니다.

commit을 처음 할 때 가장 헷갈리는 부분 중 하나가 바로 commit의 크기인데요, REAME 파일에서 몇 글자 고친 것도 하나의 commit이라고 해야할 지, 코드 줄 수를 기준으로 commit을 해야할 지 고민이 많았던 것 같습니다.

Commit의 크기는?

  1. 작을수록 좋다.

  2. 논리적인 변경 사항이 있을 때 하면 좋다.

다소 의견의 차이는 있겠지만, 이 두 가지 규칙은 우리의 commit을 조금 더 "commit답게" 만들어줄 수 있습니다.

여기서 '논리적이다'의 기준은 다소 주관적입니다. 쉽게 말해서, 다른 사람에게 commit 단위를 나눈 기준을 납득할 수 있는 논리로 설명할 수 있다면 OK입니다.

'작다' 또한 주관적일 수 있는데요, 다음은 commit 크기에 대한 예시입니다.

변경작음적당
일주일 동안 구현한 기능
README 파일의 오타 1개
한 시간 동안 구현한 기능
두 버그를 모두 고친 결과물

이것 역시 절대적인 기준은 아니며, 개인의 판단에 따라 달라집니다. 그러나 대체적으로 다른 사람이 봤을 때 변경 사항이 한 눈에 들어오는 정도로 구성하는 것이 좋습니다.

또한 협업을 하는 경우 팀 안에서 미리 정해진 commit 규칙이 있는 경우가 많고, 회의를 통해 commit 규칙을 정하기도 합니다.

커밋과 자동저장?

우리가 사용하는 문서 편집기에는 대부분 자동 저장 기능이 있습니다. 예상치 못한 사고를 예방하고자 정해진 시간에 자동으로 알아서 저장을 해줍니다.

만약 소스 코드를 원격 저장소에 자동 commit하게 된다면 어떻게 될까요?

개발자가 commit 단위를 정하지 못한다면 그 프로젝트는 오류로 범벅이 될 것입니다. 중괄호를 닫기도 전에 commit이 되어버린다던가 하는 문제가 분명 발생할테니까요.

처음에는 자신이 하던 일의 흐름을 끊고 commit 작업을 하는 것이 번거롭게 느껴질 수도 있습니다. 하지만 commit 단위는 스스로 정해야 하며 자신이 해야 할 일을 작은 단위로 쪼갤 수 있는 능력은 개발자가 갖추어야 할 중요한 능력 중 하나입니다.
또한 이렇게 작업 단위를 나누는 훈련을 잘 해놓으면 일정 관리도 수월해지게 됩니다.

레퍼지토리

레퍼지토리의 정의는 "여러 파일을 하나로 모은 컬렉션" 정도가 될 수 있습니다. 프로젝트 하나가 여러 레퍼지토리를 가질 수도 있고, 작은 프로젝트의 경우 프로젝트 하나 당 레퍼지토리 하나를 가집니다 이것을 특별히 Monorepo라고 부릅니다.

레퍼지토리 관련 커맨드

Clone

Git 레퍼지토리 주소만 알고 있다면 clone이라는 명령어로 간단하게 내 로컬 저장소로 레퍼지토리를 그대로 복사해올 수 있습니다.

$ git clone 레퍼지토리 주소

이 명령어를 실행하면 현재 작업 디렉토리 안에 레퍼지토리 이름의 폴더가 생기게 됩니다.

Log

$ git log

레퍼지토리의 commit 이력을 볼 수 있습니다.

명령어를 입력하면 이렇게 이력이 뜨게 되는데요, 스페이스바를 이용해 목록을 밑으로 내릴 수 있고 q 키로 로그를 그만 볼 수 있습니다.

$ git log --stat

위의 log 명령어에 --stat이라는 옵션을 주게 되면 commit 이력에 stat 정보도 같이 출력됩니다.

코드를 수정한다는 것은 옛날 코드를 삭제하고 새 코드를 추가하는 것과 동일한 의미를 갖습니다. stat에서 +- 기호가 갖는 의미가 그러한데요, 예를 들어 ++--는 두 줄이 추가되고 두 줄이 삭제되었다는 뜻입니다.

$ git log --pretty=oneline

--pretty 옵션을 통해 commit 이력을 원하는 방식으로 볼 수 있는데요, 여기서 oneline은 이력을 한 줄로 보겠다는 뜻입니다.

이렇게 commit 하나당 한 줄로 출력됩니다. 여기서 왼쪽의 노란 텍스트는 commit 아이디입니다.

$ git diff 커밋 아이디1 커밋 아이디2 이런 식으로 commit 아이디를 사용해 commit 간 차이점을 diff 명령어로 비교할 수 있습니다. commit 아이디는 앞의 일부분만 복사해도 비교가 가능합니다.

체크아웃

Git에서는$ git checkout 커밋아이디 명령어를 통해 로컬 저장소의 소스 파일을 해당 commit 버전과 똑같게 만들 수 있습니다.

Checkout에 대해 자세히 배우기 전에 이 명령어를 사용해 트러블 슈팅 실습을 진행하였습니다. 실습 코드는 '아스트로이드'라는 자바 스크립트 게임의 저장소를 사용했습니다.

트러블 슈팅 연습

저장소 : https://github.com/dmcinnes/HTML5-Asteroids

원하는 디렉토리 상에서 $ git clone 저장소 주소 명령어를 통해 프로젝트 폴더를 복사합니다.

이 프로젝트에는 어느 순간 오류가 생겼습니다. 우주선이 발사하는 레이저가 시간 간격을 두고 발사되어야 하는데 스페이스바를 누르고 있으면 무한대로 발사되는 오류입니다.

이제 commit 이력을 띄워놓고 하나하나 checkout 하면서 오류가 생기기 전 버전으로 돌아갑시다!🔎

gitk를 통해서 본 commit 이력입니다. 계속 checkout 명령어를 통해 내려가던 중, "I can't spell 'screen' apparently:)" 라는 커밋 메시지가 붙어있는 버전부터 갑자기 오류가 사라졌습니다.

이제 오류가 생기기 시작한 버전이 무엇인지 알았습니다.🙃 아마 오류는 "a couple missing ends with the ipad version" 이라고 적힌 commit 부터 발생한 것 같습니다.

이제 두 커밋 간의 변경 내용을 살펴보면 어느 코드가 오류를 발생시켰는지 알 수 있을 것입니다. diff 명령어를 사용할 수도 있지만 이왕 gitk를 사용한 김에 gitk를 통해 변경 내역도 확인해보겠습니다.

gitk에서 commit을 클릭하면 바로 밑의 commit과의 차이점을 보여주게 되는데요, 오류가 생기기 시작한 commit을 클릭해서 이전 버전과 코드를 비교해보았습니다.

변경된 줄이 몇 개 있었는데요, 제 눈에 들어온 것은 game.js 파일에서 삭제된

this.delayBeforeBullet = 10;

라는 코드였습니다.

제 예상으로는 사용자가 레이저를 발사하는 간격이 0보다 작으면 발사 간격을 강제로 10으로 고정하는 코드 같은데요, 이 코드가 사라지는 바람에 레이저가 연속으로 발사되는 오류가 발생했던 것 같습니다.

만약 이러한 버전 관리 시스템의 도움이 없었다면 저는 천 줄이 넘는 코드를 처음부터 끝까지 훑어보면서 무엇이 문제인지 일일히 확인해야 했을 것입니다.🤔

오류 수정과 소스 코드의 유지보수에 Git이 얼마나 유용하게 쓰이는지 깨달을 수 있었던 미션이었는데요, 다음 포스팅에서도 Git 기초에 관한 내용을 이어서 적겠습니다.👋


<참고 문서>

profile
프론트엔드 웹 개발자를 목표로 하고 있습니다.

0개의 댓글