0. Git은 코드 전용 클라우드가 아니다
나의 경우처럼, 독학이라고 하기에는 애매하지만(코딩과 관련된 인터넷 강의를 듣긴 했다) 사수가 있는 것도, 어디다 물어볼 지인이 있는 것도, 전공생인 것도, 부트캠프를 수료한 것도 아닌 경우에는 은근히 git과 같은 것에 대해 제대로 알기 어렵다고 본다. 부진정 독학러로서는 코딩 그 자체를 배우는 것만으로도 정신없기 때문에, 자연스럽게 특정 언어에 대해 공부하거나 포트폴리오를 만드는데 치중하게 되고 git은 그저 개발자들이 쓰는 구글 드라이브 수준으로만 활용하는게 현실이지 않나 싶다. 특히나 협업 경험이 없다면 십중팔구는 코드 전용 클라우드로만 쓰이고 있지 않을까?
물론 이 포스팅을 쓰는 현 시점에서 생각해보자면, 이 포스팅에 담겨져 있는 수준의 내용은 이미 Git의 공식 Documentation(Book)에 잘 정리되어 나와있다는 점에서 부끄럽긴 하다. 하지만 돌이켜보자면 언제든 시간을 내어 차분히 읽어봤다면 알 수 있었을 내용조차도 읽어 볼 엄두가 나지 않았고, 무엇보다도 그 필요성을 못 느꼈다는 점이 결정적이었다.
그래서 나는 주니어 개발자가 되기 위해서 알아야 할 Git의 핵심 내용은 무엇인지, 개발자는 Git을 왜 쓰는 것이고, 실무에서는 어떻게 활용할 수 있는지를 정리해보려 한다. 또한, 이 포스팅은 취지상 주니어가 꼭 알아야 할 내용만 다룬다는 점에서 보다 자세한 내용은 Git 공식 Documentation으로 제공되는 무료 eBook을 참조하길 바란다.
1. 본질적으로 Git은 VCS이다
VCS란 Version Control System를 의미한다.
기본적으로 Git은 파일을 바이너리 코드(0,1)를 바탕으로 버전관리를 하기 때문에 대부분의 컴퓨터 파일에 대하여 버전 관리가 가능하다.
Git은 DVCS이다. VCS는 앞서 말했으니, D가 무엇인지만 알면 될 것이다.
D는 Distributed의 약자이다. 즉 분산이라는 뜻이다.
그럼 분산이 아닌 것도 있느냐? 그렇다. 아주 원시적인 단계의 로컬 버전관리도 있고, 중앙집중식 버전 관리(CVCS)도 있다. 하여튼 그렇다. 이 이야기는 이쯤에서 접어두자.
Git은 commit 시점의 데이터를 스냅샷 형태로 찍어둔다. 각 파일마다의 시계열 기록이 아니라, Git의 대상이 되는 파일들 전체에 대해 시점별 스냅샷을 찍는 것이다. 기존 VCS가 종단기록이라면, Git은 횡단기록인 셈. 바로 이 점 때문에 Git은 강력한 Branch 기능을 구현할 수 있었고, 이것이 Git의 가장 큰 특징이자 장점이다.
다시 말해, Branch를 쓰지 않는다면 Git을 제대로 쓰고 있는게 아닌 셈.
그래서 우리는 Branch에 대해서 공부할 필요가 있다.
하지만 그전에 기본적인 VCS로서의 기능부터 짚고 넘어가자.
2. 버전 관리를 위해 꼭 알아야 할 'add'와 'commit'
git 에는 3가지 Area가 있다. Working Directory, Staging Area, Repository가 그것이다.
Working Directory는 말 그대로 작업을 하는 공간이다. 코드를 수정하거나, 파일을 생성하거나 지우거나 하는 등의 작업이 이루어지는 공간이다. 여기에 머물고 있는 작업은 git에 기록되지 않는다.
그렇다면 어떻게 해야 git에 기록할 수 있을까? 바로 다음에서 설명할 git add 명령어와 git commit 명령어를 통해야만 한다.
git add : commit의 대상이 될 변경 시점을 기록
$ git add [file/directory]
Working Directory에 있는 작업내용(파일의 생성, 수정, 삭제)을 Stage Fix하여, Staging Area에 추가한다.
add 단계에서 보통 자주 쓰는 명령어는 다음과 같다.
$ git add .
이는 사실 '.' 즉 현재 디렉토리를 add 한다는 뜻이다. (일반적으로 '.'은 현재 디렉토리를 의미한다. cd ./test를 입력하면 현재 디렉토리 내에 존재하는 test라는 디렉토리로 접근하게 되는 것도 '.'이 현재 디렉토리를 뜻하기 때문이다.)
이 때, add 명령어는 그 대상이 파일인 경우에는 해당 파일만을 Stage Fix하지만, 디렉토리인 경우에는 디렉토리 하위의 모든 것을 Stage Fix한다. 따라서 프로젝트의 최상위 디렉토리를 add하게 되면, 프로젝트 전체가 Stage Fix 되는 것이다.
Staging Area에 머물고 있는 변경사항은 일종의 임시저장과 유사한 측면이 있다.
Staging Area에 있다가도 변경사항을 취소 및 되돌리기를 하거나 (git checkout -- <file>) Unstaged 상태로 변경(git reset HEAD <file>)한다면 변경사항은 Staging Area에서 사라져, git과 아무런 관련이 없게 된다. 즉, git에 기록되지 않는다는 뜻이고, 결과적으로 Working Directory에만 머물고 있는 작업내용은 추후 git을 통한 복구가 불가능하다.
이 때, checkout은 Working Directory상의 파일 자체를 가장 마지막에 commit된 버전으로 되돌려(덮어)버리므로 변경사항이 아예 초기화된다는 특징이 있어 주의를 요하는 명령어이다.
git commit : add시점의 작업내용을 Repository에 저장
$ git commit -m '[message]'
Staging Area에 있는 파일의 스냅샷을 Repository에 올린다.
여기서 가장 중요한 부분은 add를 통해 기록되지 않은 변경사항은 Repository에 등록되지 않는다는 점이다. 즉, commit을 실행하면, add 명령이 실행된 바로 그 시점의 파일 상태가 commit 된다. 만일, add로 기록한 뒤 곧바로 commit하지 않고 다시 해당 파일을 수정한 후 비로소 commit을 실행하면, git은 add 시점의 파일 상태를 commit하게 되므로 add와 commit 사이에 이루어진 수정사항은 commit 되지 않는다.
그렇다면 아래 그림과 같은 상황에서 ?에는 (상태 1)과 (상태 2) 중 어떤 것이 올까?
결국 첫 부분에 적었듯, git commit은 Staging Area의 내용만을 대상으로 동작하기 때문에 (상태 1)이 commit된다.
참고로 (상태 2)와 같이 Staged되지 않은 수정사항을 Modified 상태라고 부르며, 약자로 M으로 표현한다.
또한, commit은 영구적인 저장과 유사한 개념이다. 아래의 경우(git commit --amend)를 제외하면 사실상 한 번 commit된 내용은 지우거나 변경할 수 없고 항구적으로 남는다.
좀 과격한 예를 들자면, 장난으로(?) 상사 욕을 쓴 뒤 commit 해버린 경우 repository를 새로 만들지 않는 이상 해당 기록은 영원히 박제된다. 누가 언제 작성했는지까지도 모두 다. repository를 새로 만든다는건 그간의 모든 버전기록을 다 버린다는 뜻이므로 사실상 회사의 product repository는 새로 만드는 것이 불가능하다. 즉, 영원불멸의 박제.
또 다른 예를 들자면, 개인정보나 공개되어서는 안될 Private Key 혹은 Secret Key 같은 것들 역시도 한 번 commit 되고 나면 영원히 엑세스 가능하게 된다.
따라서, commit은 항상 신중하게 해야하며, 원치 않는 파일이나 원치 않는 정보가 commit 되지 않도록 주의 또 주의해야 한다. 이와 관련된 내용은 향후 .gitignore에 대해 이야기할 때 더 자세히 다뤄보겠다.
commit 단계의 유용한 flag 명령어
$ git commit --amend
바로 직전에 수행한 commit을 덮어쓴다. 이 경우, 이전의 commit을 기록에서 완전히 지울 수 있다.
지금까지는 모두 로컬 저장소에서 벌어진 일이다.
이상에서 살펴본 명령어는 로컬 컴퓨터에서의 작업 내용을 로컬 저장소에 있는 git에 기록하는 방법에 관한 것이다. 즉, 이상의 내용들은 어디까지나 로컬 컴퓨터 내에서 쿵짝쿵짝 이루어진 것이다.
하지만, 우리는 다른 컴퓨터에서도 이 컴퓨터에서 기록한 git 정보를 읽어올 수 있다. 바로 원격 저장소를 통하면 가능하다.
3. 협업 혹은 여러 컴퓨터에서 작업하기 위해 알아야 할 'push' 와 'pull'
git push : 로컬의 최신 commit 버전을 리모트 저장소에 밀어 넣다.
리모트 저장소
리모트 저장소라는 개념이 나왔다. 프로젝트를 혼자서만 진행한다면 사실 리모트 저장소와 로컬 저장소는 크게 다를게 없다. 하지만 협업을 하거나 혼자하더라도 여러 기기에서 작업을 하게 된다면, 그때부터 리모트 저장소 개념은 중요해진다. 리모트 저장소를 통해서 서로 교류하기 때문이다.
리모트 저장소는 원격 저장소이지만, 반드시 네트워크상에 존재해야만 하는 것은 아니다. 이론상으로는 하나의 로컬 시스템상에 리모트 저장소와 로컬 저장소가 함께 존재할 수도 있다. 일반적으로 git과 함께 사용하는 github나 gitlab, bitbucket 등이 대표적인 리모트 저장소이다.
$ git push [리모트 저장소] [브랜치]
앞에서도 말했듯이, 우리가 commit을 하게 되면 .git 폴더에 관련된 정보가 저장되어 로컬 환경상에서 git에 의한 버전관리가 가능해지기는 한다. 하지만 이는 어디까지나 로컬 환경에서의 이야기이다. 이렇게 로컬에서 commit에 의해 확정적, 영구적으로 저장된 버전 관련 정보를 원격 저장소에 올리는 것이 바로 push다.
push는 리모트 저장소와 로컬 저장소 간의 동기화(혹은 Clone)를 진행한 가장 최근 시점 이후, 다른 사람이 push 하지 않았을 때만 사용할 수 있다. 리모트 저장소에 쓰기 권한이 있어야 함은 물론이다. Clone 이후 누군가 push를 했다면, 다른 사람이 push한 데이터를 나의 로컬에 merge한 이후에만 push를 할 수 있다.
리모트 저장소의 이름은 기본적으로 origin으로 설정된다. 이는 git clone 명령어를 수행하면 자동으로 리모트 저장소 이름을 'origin'으로 설정하기 때문이다. 브랜치의 이름인 main(master)이 큰 의미가 없으며, 우리가 수정해줄 수 있는 것처럼 리모드 저장소 이름도 마찬가지이다. 그냥 기본 설정상 이름일뿐이다.
참고로 배포서비스 중 하나인 heroku의 리모트 저장소 이름은 기본값이 heroku이다.
따라서, git push heroku main 과 같은 명령어를 통해 배포하게 되는 것이다.
만일, 리모트 저장소 이름이 origin으로 설정된 github 리모트 저장소의 main 브랜치에 push하고 싶다면 git push origin main 명령어를 써야할 것이다.
git pull : 리모트 저장소의 데이터를 로컬 저장소로 당겨 오다.
$ git pull
pull은 리모트 저장소의 데이터와 로컬 저장소의 데이터를 같게 만드는 명령어이다. 다만, push가 로컬의 데이터를 기준으로 리모트 저장소의 데이터를 업데이트 하는 명령어였다면, pull은 리모트 저장소의 데이터를 기준으로 로컬 저장소의 데이터를 업데이트 하는 명령어이다. pull은 리모트 저장소에서 가져온 데이터를 곧바로 Merge까지 시켜주기 때문에, 리모트 저장소를 기준으로 로컬 저장소의 파일이 생성/변경/삭제된다.
pull과 유사한 개념으로 fetch가 있다.
github desktop을 이용하는 경우, fetch를 본 적이 있을 것이다.
fetch와 pull의 차이는 자동 Merge가 이루어지는지 여부이다. fetch는 pull과 달리 수동으로 Merge를 해줘야한다.
다시 말해, fetch는 리모트 저장소에는 있지만 로컬에는 없는 데이터를 모두 가져온다는 점에서 pull과 동일하지만, fetch만으로는 merge가 이루어지지 않기 때문에 사용자가 직접 수동으로 merge를 진행해야한다.
4. Git이 코드 전용 클라우드가 아닌 이유 : 브랜치
이상에서 설명한 내용은 사실 버전관리가 이루어지는 클라우드와 크게 다를바 없다. 이 글의 가장 첫 부분에서 Git은 코드 전용 클라우드가 아니라고 해놓고서는 실컷 클라우드스러운 얘기만 늘어놓은 것 같지만, 그렇다고 해서 가장 기본적인 위 내용을 설명하지 않을 수는 없었으니 이해해주길 바란다.
그렇다면 Git이 단순히 코드 전용 클라우드가 아니게끔 하는 가장 핵심은 무엇일까? 도입부에서 말했듯, 바로 Branch이다.
만약 Git을 사용하면서 단 한번도 Branch를 써본 적이 없다면, 혹은 Branch가 아직 어색하고 불편하다면, 사실상 Git을 제대로 활용하지 못하고 있는 셈이다.
그리고 Branch에 관해서는 다음 글에서 본격적으로 다뤄보려고 한다.
'Learning-Log > Computer Science' 카테고리의 다른 글
[Windows11] 결국 BitLocker 해제했습니다. (+ 삼성전자 공식답변) (0) | 2022.06.19 |
---|---|
[WSL2] 폴더를 VSCode로 여는 방법 3가지와 각 경우의 폴더 경로 (0) | 2022.06.14 |
[JS/Array] 배열 Method 및 배열 고차 함수 정리 (0) | 2022.06.13 |
[JS/반복문] 반복문 및 반복문을 대체할 수 있는 기능 6가지 총 정리 : for 문, while 문, do ... while 문, forEach 메서드, for ... in 문, for ... of 문 (0) | 2022.06.13 |
[JS/함수] 함수의 유형 (1) - 즉시 실행 함수 (0) | 2022.06.07 |