Git 개념 총정리 1부

우현민·2021년 1월 19일
1

Git 개념 총정리

목록 보기
1/4
post-thumbnail

Git의 역사

원래 Linux 커널은 BitKeeper라는 버전 관리 시스템을 통해 오픈소스로 운영되고 있었다. 유로 서비스이지만 특별히 Linux에게는 무료로 공개해 주고 있었는데, Linux 커뮤니티 측 개발자의 잘못으로 인해 BitKeeper와 Linux 커뮤니티 사이의 관계가 틀어지며, BitKeeper는 Linux 커뮤니티에 대한 배려를 끊고 이용료를 유료로 돌려 버렸다.

이에 Linux를 만든 리누스 토발즈는, 유료로 BitKeeper를 사용하기보다 그냥 자기가 새로 버전관리 툴을 만들어 세상에 내놓는데, 이게 바로 Git이다. 그렇게 지금은, Git은 세계에서 가장 거대하고 강력한 분산 버전 관리 시스템이 되었다.

Git의 특징

Git의 가장 큰 장점은 '빠른 속도의 분산 버전 관리'라고 생각한다.

Git과 Github

여기까지 온 사람이라면 아마 Github는 알고 있을 것이다. 사실 Git과 Github는 명백히 다르다. Git은 버전관리 시스템이지, 서버가 아니다. Git을 이용하면 버전관리를 할 수 있으나 그걸 업로드할 서버가 없다면 무용지물이다. 때문에 Git을 위한 서버들이 몇 개 있는데(Github, Gitlab 등), 그 중 가장 유명하고 무료이고 공개된 곳이 Github이다. 또한 github.com은 github 서버 위에서 git을 유용하게 쓰도록 도와주는 프론트엔드 페이지이자 서비스이다.

repository (저장소)

저장소는 크게 로컬 저장소와 서버 저장소로 나눌 수 있다. 간단하게, 서버에 있는 코드를 로컬 저장소로 받아 와서(clone 또는 pull), 수정하고 싶은 대로 수정해서, 올리면 된다(push). 이 '한 번 다운받고 올리는 등의 작업'을 할 때의 작업 단위가 바로 repository이다.

일반적으로 repository의 크기는 상당히 크다. 한 서비스 내에서 서로 코드 단위로 상호작용하는 모든 것들은 같은 repository에 있다고 볼 수 있다. 가령 웹 페이지의 frontend를 만든다고 하면, 그 웹 페이지 frontend를 만들 때 들어가는 모든 코드가 한 repository에 들어 있을 것이다. 때로는, 정말 큰 코드의 경우 전체 코드를 다운받는 데만 몇 시간이 걸리는 경우도 있다.

앞서 말했다시피 코드를 다운받는 등의 작업이 repository 단위로 이루어지기 때문에, 가령 그 repository에 파일이 1000개 있지만 내가 수정하고 싶은 기능은 아주 작다면, 1000개의 파일을 다운받고 그 중 한 파일에서 한 줄만 고쳐서 업로드해야 할 수도 있다. 이렇게 봐서는 단점 같아 보일 수는 있으나.. 일반적으로 로컬에서 그 코드를 이용해서 build를 하든 뭘 하든 전체 코드가 다 필요할 테니, 오히려 장점이라고 생각한다.

Stage (추적)

로컬에 코드를 다운받았을 때, 서버에서 볼 때 repository 안에 코드들이 있듯이, 로컬에서 볼 때는 폴더 안에 코드들이 있는 형태로 보인다. 이때 Git은 폴더 안에 어떤 파일들이 있는지 자동으로 인식한다. 그리고 유저의 명령에 따라 이 파일들을 Git에서 추적할지 말지 결정한다. 로컬에 repository를 clone하면 .git 폴더가 생겨 있는 걸 본 적이 있을 텐데, 이 친구가 Git 내역을 관장하는 폴더이다. 수정 내역, 파일 추가 내역 등 모든 게 이 폴더에 저장된다.

여기서 추적이란, Git이 파일의 변화를 자동으로 감지할지, 그리고 commit이나 push를 할 때 그 파일을 포함할지를 뜻한다. 무조건 그냥 다 추적하면 된다고 생각할 수 있지만, 생각보다 그렇지 않다. 가령 로컬에서 generate할 수 있는 내용은 굳이 업로드할 필요가 없다. 가령 doxygen이나, package 파일 등은 '어떤 거를 다운받으세요'라고만 말해 두고 로컬에서 알아서 다운받아서 빌드하는 게 낫다. 가령 react의 node_modules 폴더 등이 있겠다.

때문에, 일반적으로는 필요한 파일만 stage하는 것이 대부분이다. stage는 add 명령어를 이용하여 한다. add를 한 번 하면, 그 이후로 Git은 그 파일의 모든 것을 추적한다. 변화, 변화 시간, 삭제, 삭제 시간 등등.. 물론 파일을 실수로 stage했다면 unstage하는 방법도 있다.

그렇다고 모든 파일에 대해 git add를 해 줘야 하느냐; 그건 아니다. 이럴 때 사용하는 것이 바로 .gitignore이다. 이 파일은 Git에게 추적하지 않을 파일들(의 패턴)을 명시해 준다. 일반적으로는, .gitignore파일을 만들어 놓고 git add .을 하여, .gitignore이 명시한 파일들 빼고 모든 파일을 자동으로 stage하는 것이 일반적이다.

commit (커밋)

앞서, 코드를 다운받고 올리는 과정은 아주 큰 코드를 다운받아 아주 큰 코드를 올리도록 한다고 말했다. 하지만, Git을 써 봤다면, Git의 큰 장점 중 하나가 '모든' 수정 내역을 확인할 수 있고, 언제든 그 시점으로 돌아갈 수 있는 것이다. 그렇다면 이 모든 시점을 복사해서 그 시점의 스냅샷을 저장해 둘 것이냐; 그렇지 않다.

commit은 하나의 수정 내역 조각이다. 파일 추가, 파일 수정(몇 번과 몇 번 줄을 지우고 몇 번과 몇 번 줄을 추가한다는 등) 등의 정보를 저장한다. 이는 링크드리스트처럼 구현되어 있는데, 가령 지금 커밋을 두 번 했다면,

원본 코드 -> (커밋 1ebd72)몇번 줄에 뭐라고 쓰고 몇번 줄은 지운다 -> (커밋 1deea5)또 뭔가 쓰고 뭔가 지운다 -> 현재 코드 

이런 식으로 이어지는 것이다. 때문에 중간 단계 커밋이 하나라도 망가지면 앞선 내역들도 다 망가질 것이기 때문에, .git 폴더는 건드리지 않아야 한다. 물론 못 건드리게 Git이 내부적으로 어느 정도 잡아주겠으나... 아무튼.

또한 이런 커밋 내역이 로컬에 저장된다는 말은 바로 오프라인 작업이 가능하다는 말이다. 커밋은 서버와 상호작용하는 활동이 아니다. 이는 Git의 큰 장점 중 하나이다.

눈치챘겠지만, 푸시 역시 .git 폴더에 저장되어 있는 커밋 내역의 목록을 푸시하는 것이지, 전체 코드를 서버에 업로드하는 과정이 아니다. 또한 그렇기 때문에, 열심히 로컬에서 파일을 수정했어도, 커밋하지 않으면 push 명령어를 아무리 입력해도, 푸시할 게 아무 것도 없기 때문에 서버에 있는 코드는 변하지 않는다. (사실, push하고 싶으면 커밋하라고 Git이 경고를 신나게 날린다.)

profile
프론트엔드 개발자입니다

0개의 댓글