1. 개념
1.1) 정의
Git은 분산형 버전 관리 시스템(Distributed Version Control System)이다.
Git은 리눅스의 아버지 리누스 토르발스가 오픈소스 커널인 Linux 소스코드를 관리 할 목적으로 만들었는데 2주만에 만들었다고 한다. 아래는 Git Repo의 리누스가 한 첫번째 커밋의 README.md
파일의 일부를 가져온 것인데, Git
은 그냥 아무 의미 없는 세글자 알파벳이라고 한다. 그냥 유닉스 명령어 중에 git
이라는 명령어가 없어서 정했다고 한다. 기분이 좋으면 “global information tracker”라고 하고 기분이 구리면 “goddamn idiotic truckload of sh*t”이란 뜻이란다.
- GIT
- the stupid content tracker“git” can mean anything, depending on your mood.
- random three-letter combination that is pronounceable, and notactually used by any common UNIX command. The fact that it is a mispronounciation of “get” may or may not be relevant.
- stupid. contemptible and despicable. simple. Take your pick from thedictionary of slang.
- “global information tracker”: you’re in a good mood, and it actuallyworks for you. Angels sing, and a light suddenly fills the room.
- “goddamn idiotic truckload of sh*t”: when it breaksLinus Torvalds git/git/README.md
Git을 이용하면 소스 코드가 변경된 이력을 쉽게 확인할 수 있고, 특정 시점에 저장된 버전과 비교하거나 특정 시점으로 되돌아갈 수도 있다. 또 내가 올리려는 파일이 누군가 편집한 내용과 충돌한다면, 서버에 업로드 할 때 경고 메시지가 발생된다.
즉, 코딩할 때 단순히 ctrl+z를 눌러 이전 상태로 되돌리는 것이 아니라, 원하는 시점마다 깃발을 꽂고(버전을 만들고) 이들 간에 자유롭게 돌아다닐 수 있다. 내가 만든 버전 뿐 아니라 동료가 만든 버전으로 이동할 수 있고, 동료와 내 버전을 비교해서 최신본으로 코드를 업데이트를 할 수 있다.
1.2) 기본 용어
-
저장소(repository) repository(저장소)는 파일이나 디렉토리를 저장하는 장소입니다. Git repository의 장점은 변경 이력이 존재하는 파일별로 구분되어 저장된다는 점입니다. 저장소는 내 컴퓨터에 있는 ‘로컬 저장소(local repository)’와 전용 서버에서 관리되는 ‘원격 저장소(remote repository)’의 2개가 존재합니다. 기본적으로 로컬 저장소에서 작업을 진행하고 그 결과를 원격 저장소에 저장할 수 있습니다.
Git은 원격 저장소와 로컬 저장소 두 종류의 저장소를 제공한다.
-
원격 저장소(Remote Repository): 파일이 원격 저장소 전용 서버에서 관리되며 여러 사람이 함께 공유하기 위한 저장소이다.
-
로컬 저장소(Local Repository): 내 PC에 파일이 저장되는 개인 전용 저장소이다.
-
-
브랜치(branch) 소프트웨어가 출시된 이후 버전의 지속적인 유지 보수를 통해 기능을 추가하거나 버그를 수정하게 됩니다. 이처럼 여러 버전을 관리하기 위해 브랜치(branch)라는 기능을 사용합니다.
-
커밋(commit) 파일을 추가하거나 변경사항을 저장소에 기록하기 위해 커밋 메시지를 남기는 작업을 말합니다.변경한 사람, 시간, 변경 내용 등을 기록해 과거 변경 이력과 내용을 손쉽게 파악할 수 있습니다.
간단한 협업 시나리오
- 내 컴퓨터에서 코드 작어
- 단계별로
커밋
만들기- Github 같은 곳에 저장소를 만들어 커밋을
푸시
- 동료 개발자와 인사한다. Hi!
- 동료 개발자가 본인 컴퓨터에 저장소를
풀
- 동료 개발자가 ‘fix/click-bug’
브랜치
를 만들어 버그를 고쳐준다.- ‘fix/click-bug’ 브랜치에서 작업이 끝나면 master 브랜치와
병합
한다.
- Git cheetcheat: https://www.atlassian.com/dam/jcr:e7e22f25-bba2-4ef1-a197-53f46b6df4a5/SWTM-2088_Atlassian-Git-Cheatsheet.pdf
2. 기본 명령어
2.1) init
아래 명령어로 .git 라는 이름의 숨김 폴더가 하나 만든다. 이것을 저장소라고 하는데 깃은 이 폴더의 모든 변경 내용을 여기에 저장한다. 이 파일을 지우면 더 이상 깃으로 폴더의 변경사항을 추적할 수 없다.
1 |
|
config
git config: Git 사용자 정보를 설정한다.(최초 1회만 실행)
1 |
|
2.2) status
깃이 파일의 변경 내역을 저장하는데 곧바로 저장하는 것이 아니라 “스테이징”이라는 단계를 거친다. 스테이징은 변경사항 중에서 “저장하고 싶은 부분만 선택해 임시로 저장”하는 개념이다. 이때 폴더의 파일들의 현재 변경 상태를 보는 명령어다.
1 |
|
2.3) add
1 |
|
2.4) commit
1 |
|
2.5) log
1 |
|
2.6) show
commit
의 상세 정보를 확인합니다.
1 |
|
2.7) branch
브랜치
는 일종의 독립된 작업을 진행하기 위한 작업 공간의 개념이다. 맨 처음 Git을 초기화했을 때 기본적으로 master
라는 이름의 브랜치가 하나 생성된다. 그 후 개발하는 기능 또는 버그 픽스에 따라서 브랜치를 새로 생성하고 거기서 작업한 후에 나중에 다시 master
로 합치는 것이다.
1 |
|
2.7) show
commit
의 상세 정보를 확인합니다.
1 |
|
2.8) checkout
글자 그대로, 현재 위치하고 있지 않은 저장소를 “체크아웃”할 수 있다. 이것은 체크하길 원하는 저장소로 옮겨가게 해주는 탐색 명령이다. master 브랜치를 들여다 보고 싶으면, git checkout master
를 사용할 수 있고, git checkout login
로 또 다른 브랜치를 들여다 볼 수 있다.
1 |
|
3. 중급 명령어
.gitignore 생성
Git 저장소를 생성할 때 간과하기 쉬운 부분이 .gitignore
파일을 생성해놓는 것입니다. .gitignore
파일은 Git으로 버전 관리를 하면 안 되거나, 할 필요가 없는 경로를 정의하는데 쓰입니다.
HEAD
브랜치 명령어를 통해 앞에 별표(*)된 것이 선택된 현재 브랜치라는 것을 알수 있다. 위치를 좀 더 정확하게 보여주는 정보가 있는데 바로 “머리(HEAD)” 라고 부르는 것이다. 헤드는 여러 개 가지로 뻗어있는 브랜치와 커밋 목록에서 현재 위치를 나타낸다. 체크아웃 하면서 브랜치를 이동할 때 마다 헤드는 수시로 변경된다. 뿐만 아니라 특정 커밋으로 체크아웃 할 수 있는데 이 때도 헤드는 그 커밋으로 이동한다.
3.1) reset
commit
을 취소 할 수 있습니다.
1 |
|
옵션 / 영역 ex) git reset [옵션] abcd(커밋) | working directory | staging area | repository |
---|---|---|---|
–soft | 바뀌지 않음 | 바뀌지 않음 | Head가 abcd(커밋)를 가리킴 |
–mixed | 바뀌지 않음 | abcd(커밋)내용으로 변경 | Head가 abcd(커밋)를 가리킴 |
–hard | abcd(커밋)내용으로 변경 | abcd(커밋)내용으로 변경 | Head가 abcd(커밋)를 가리킴 |
3.2) rm
파일을 지우거나 스테이지에서 해제할 때 사용합니다.
1 |
|
3.3) revert
지정한 커밋으로 되돌려 커밋합니다. 되돌린 이력이 남기때문에 충돌이 발생할 위험이 적으며 협업 상황에서 사용하는 것을 추천합니다.
1 |
|
3.4) remote
원격 저장소(remote repository)를 관리하는 명령어 입니다.
1 |
|
3.5) clone
원격 저장소의 내용을 통째로 다운로드하는 것을 말한다. 복제한 저장소를 다른 PC에서 로컬 저장소로 사용할 수 있게 된다. 변경 이력도 함께 로컬 저장소에 복제되어 오므로, 원래 원격 저장소와 똑같이 이력을 참조하고 커밋을 진행할 수 있다.
1 |
|
3.6) push
웹 상의 원격 저장소로 변경된 파일을 업로드하는 것을 Git에서는 푸시(Push)라고 합니다. push 를 실행하면, 원격 저장소에 내 변경 이력이 업로드되어, 원격 저장소와 로컬 저장소가 동일한 상태가 된다.
1 |
|
3.7) fetch
원격 저장소(remote repository)의 데이터를 가져옵니다. pull
로 병합하기 전에 어떤 변경점이 있나 살펴볼 때 사용하기 좋습니다.
1 |
|
3.7) pull
pull
명령어는 리모트 서버의 최신 소스를 가져와서 로컬 소스에 병합(Merge)
해주는 명령어이다. 만약 우리가 처음 소스를 클론한 후에 다른 사람이 리모트 서버를 상태를 갱신했더라도 리모트 서버가 우리에게 그 변경된 사항을 알려주지는 않기 때문에 우리가 직접 서버에 문의를 날려야 하는 것이다.
예를 들어 공동 작업물을 로컬저장소에서 작업해야할 때 이 명령어를 먼저 실행한 후에 작업한다.
- 여려명이 함께 작업할 때 프로세스 : pull - 작업 - commit - push
또한 pull
은 단순히 리모트 서버에서 로컬로 소스를 가져온다의 개념보다는 가져와서 합친다
의 개념이기 때문에 브랜치끼리도 pull
을 통해 소스를 합칠 수 있다.
1 |
|
오픈소스에 관심이 많은 분이라면 Pull Request
라는 단어를 들어보았을 것이다. 이 Pull Request
는 “내가 작업한 브랜치를 가져가서 합쳐줘~“라는 의미이다. Merge Request가 아닌 이유는 요청을 받은 사람 입장에서 브랜치를 가져와서 합친기 때문이다.
3.8) merge
브랜치에서 작업을 끝내고, 모든 협업자가 볼 수 있는 master 브랜치로 병합할 수 있다. git merge cats
는 “cats” 브랜치에서 만든 모든 변경사항을 master로 추가한다.
1 |
|
3.9) diff
1 |
|
3.10) tag
특정 커밋에 표기하는 기능입니다. 주로 릴리즈 시 이용합니다. 두 가지 종류가 있는데 Lightweight 태그와 Annotated 태그입니다. Lightweight 태그는 단순히 버전등의 이름을 남길 때 사용합니다. Annotated 태그는 만든 사람의 이름, 이메일, 날짜, 메시지까지 저장하며 GPG(GNU Privacy Guard)로 서명까지 가능합니다.
1 |
|
4. 상황별 팁
“히스토리를 변경하고 싶어요”
A작업을 마치고 커밋, B작업을 마치고 커밋, A’ 작업을 마치고 커밋을 만들었다. 깃 로그는 A -> B -> A’ 순으로 쌓이게 된다. 이왕이면 관련된 커밋을 한 곳으로 모으고 싶다.
지라 따위의 애자일 도구를 사용한다면 이런 경우가 자주 발생할 수 있다. 작업 번호로 커밋 메세지를 만들텐데 앞에 지라 번호를 붙여서 메세지를 작성할 것이다.
1 |
|
마지막 두 개 커밋의 순서를 바꾸면 작업을 이해하는데 더 좋고 의미있는 커밋이 될 것 같다. 코드의 가독성 뿐만 아니라 커밋의 가독성도 그것만큼 중요하니깐 말이다.
“리베이스(rebase
)”를 이용하면 커밋 순서를 변경할 수있다.
1 |
|
HEAD를 포함한 이전 3개 커밋을 재작성(rebase) 한다는 뜻이다.
에디터가 열려 커밋 목록이 나오고 여기서 순서를 변경할 수 있다.
1 |
|
만약 두개 커밋을 하나로 합치고 싶다면 마지막에 있는 ‘A 작업 추가함’을 2번 라인으로 옮긴다. 그리고 pick
대신 fixup
혹은 줄여서 f
를 입력한다. 그럼 이 커밋을 1번 라인에 있는 커밋과 합친다는 의미다(리베이스 액션에 대한 자세한 설명은 하단에 주석을 참고하기 바란다).
1 |
|
이렇게 수정하고 저장하고 편집기를 닿으면 1, 2번 라인의 변경내용을 합쳐 커밋을 다시 생성하는데 사용할 커밋메세지 입력을 위해 에디터가 다시 열린다. 저장하고 닫으면 커밋이 3개에서 2개로 변경된다.
1 |
|
“원격 저장소와 연결하고 싶어요”
깃헙 같은 원격에 있는 저장소를 컴퓨터에 다룬로드하는 것을 “복제(clone)한다”라고 한다.
원격 저장소는 다운로드를 위한 주소를 제공하는데 git으로 시작되는 주소나 https로 시작하는 주소를 제공한다. ssh 방식이고 공개키가 서버에 등록되어 있다면 이 방식으로 다운로드할수 있다. 후자는 아이디와 비빌번호를 사용해서 다운로드 할 수 있다.
보통 깃헙을 원격저장소로 많이 사용하는데 공개키를 등록해서 ssh 방식으로 사용하는 편이다.
1 |
|
다운로드한 원격 저장소는 저장소 이름으로 로컬에 폴더를 생성한다. 여기서 작업을 하고 커밋을 만든뒤 원격으로 내용을 업로드 하는 것을 “푸시(push
)”라고 한다.
1 |
|
협업하다보면 원격저장소를 클론한 다른 사용자가 코드를 먼저 푸시했을 수도 있다. 이렇땐 저장소의 최신버전을 가져와야하는데 이것을 “패치(fetch
)”라고 한다.
1 |
|
패치하면 원격 저장소의 최신 업데이트 내용을 로컬에 가져올 수 있다.
가져온 변경사항을 현재 브랜치와 머지하려면 pull
명령어를 사용한다.
1 |
|
원격 저장소의 변경 내용을 가져와 로컬 저장소에 반영된다. 패스트 포워드가 가능하면 바로 반영하고 그렇지 않으면 머지 커밋을 추가로 만든다.
내가 작업한 내용을 깨끗히 유지하고 싶으면 머지 커밋을 만들지 않고 리베이스로 변경사항을 반영할 수도 있다.
1 |
|
이렇게 하면 원격저장소에 있는 변경사항을 먼저 쌓고 그 위에 내가 작업한 변경사항을 쌓는 방식이다.
나는 머지보다는 리베이스를 선호하는 편이다. 커밋 그래프를 좀더 단순하게 유지하고 싶어서 그렇다.
“원격 저장소를 여러개 관리하고 싶어요”
원격 저장소로 부터 클론하면 원격지 이름은 기본적으로 “origin”이다. remote
원격지를 관리하는 명령어인데 -v
옵션으로 원격저장소 목록을 볼 수 있다.
1 |
|
원격 저장소는 여러개 붙일 수 있다. 원격 저장소가 여러개 있어야할 이유는 뭘까?
깃헙 포크를 이용하면 이게 무척 유용하다. 깃헙의 포크는 타인의 계정에 있는 저장소를 내 계정의 저장소로 하나 가져오는 기능이다. 내 계정으로 포크한 저장소를 클론하면 기본 이름인 origin으로 가져온다.
만약 타인의 원격 저장소에 변경사항이 있는데 이걸 내 로컬에 가져오고 싶으면 어떻게할까? 이때 “원격 저장소 하나를 더 추가”할 수 있다. 보통은 upstream이란 이름으로 원격저장소 하나를 더 추가한다.
1 |
|
이렇게 하면 하나의 저장소에 두 개의 원격지를 연결할 수 있다. origin으로 내 원격 저장소에 코드를 푸시하다가, 원본 저장소의 변경사항을 받을때는 upstream을 사용한다.
원격 저장소의 주소를 변경하고 싶은때는 set-url
로 변경할 수있다.
1 |
|
물론 원격 저장소의 이름을 변경할 수도 있다.
1 |
|