2. 본 문서에 대하여
• Git을 사용하여 개발할 때에 경험한 헤딩을 공
유하고자 합니다.
• Git 자체를 설명하지는 않습니다.
• Git 자체에 대한 이해는 얄팍합니다. 절대로
Git에 대한 마스터피스가 아닙니다.
• remote repository로 GitHub를 사용합니다.
• linux 환경에서의 개발입니다.
• 대상은 CVS, SVN과 같은 버전닝, 소스관리
툴의 개념을 알고 있다는 전제입니다.
2
3. 본 문서의 거짓말에 대하여
• 본 문서에서 말하는 Git의 내부적인 것들은 대
부분 거짓말입니다.
• 하지만 Git을 사용하여 개발하는데 필요한 멘
탈 모델로서는 모순됨이 없네요.
• 단순히 Git의 사용을 위한 학습방법으로만 받
아들이시고, 인용하거나 사실로 오해하시면
안됩니다.
3
4. Git를 사용하면서 가려웠던 사항
• branch? stash? repository? remote? local?
• 내가 수정한 것과 Remote Repository의 것
과 비교하고 싶다.
• 내가 commit할 변경 내용을 한눈에 보고 싶
다.
4
5. 가장 곤란했던 헤딩 상황
• 내가 무언가를 수정했고, 이를 GitHub에
push하려는데 실패한다. 다른 팀원이 변경
한 것이 이미 GitHub에 올려져 있는 상황이
다.
5
7. How To : 프로젝트 다운 받아 개발시작하기
$ git clone git@github.com:kthcorp/mytest.git (1)
$ cd mytest
$ echo “first file” > first_file.txt
$ git commit –a –m “add new file” (2)
$ git push (3)
(1) 프로젝트 kthcorp/mytest.git를 mytest라는 폴더로 다운받는다.
(2) 변경된 것을 local repository에 commit하겠다.
(3) local repository에 commit 된 것을 remote repository에 반영하겠다.
7
8. Local Repository
• Local Repository는 SVN server로 생각하라.
• 따로 설치하거나 구동하지 않는다. 단지 linux에 git가 설치되어
있고, git clone으로 프로젝트를 다운받았으면 있는 것이다.
• local이라는 것은 로그인한 linux 박스에서의, 로그인한 계정에
서만 통한다는 것이다.
• 그러니까 모든 개발자는 별도의 서버를 운영하고 있는 것이다.
• 그 개별적인 서버에 혼자서 지지고 볶으면 된다. 다른 팀원과는
관계없다.
8
9. Remote Repository
• 그런데 하나의 단위 개발이 끝났으면, 이를 공유하여야 한다.
• 이를 위한 것이 Remote Repository이다. 별도로 구축할 수도
있다. KTH는 GitHub를 사용한다.
• Remote Repository의 것은 다 같이 공유되어야 하기에, 완성도
있는 것들만(compile되고, test 성공하고, …) 올려져야 겠다.
• 절대 SVN의 서버가 Remote Repository라 생각하지 마라. 그러
면 헷갈린다. Remote Repository에는 commit이라는 개념도
update라는 개념도 없다. commit과 update는 오직 Local
Repository하고만 관련된다.
9
10. Git에서의 commit
Work Local Remote
Space Repository Repository
개발
commit -a
push
• Work Space는 단지 개발하고 있는 파일시스템의 폴더일 뿐이다.
(„.git‟ 폴더가 존재하는)
• SVN의 commit과 마찬가지로 변경사항을 Local Repository에 적용.
• 그리고 이를 공유하기 위해 push로 Remote Repository에 올린다.
10
11. SVN에서는
• 수정하고, update하면 자동으로 merging해
주고, conflict난 경우 이를 표시해 준다.
Work SVN
Space Server
개발
누군가
commit
update
commit
11
12. 그런데, Git에서는 잘 안된다.
Work Local Remote
Space Repository Repository
개발
fetch
merge
• SVN의 update라는 명령이나 개념도 없다.
• 변경된 사항을 덮어쓸 수 있다고 하면서 merge가 실패한다.
• 먼저 commit하던가 stash(?)하라고 한다.
12
13. How To : 내가 수정한 것과 타인이 수정한 것
을 merging하여 commit하기
$ echo “some modification” >> first_file.txt
(1)
$ git commit –a –m “add first_file.txt”
(2)
$ git fetch
(3)
$ git merge origin commit의 –a 옵션은 git add 없
이 모든 변경된 것을 대상으로
(4) 하라는 의미
(1) 파일을 수정했다.
$ git push
(2) 변경된 (5) 전부를 local repository에 commit한다.
사항
(3) remote repository에서 최신의 것을 local repository로 가져온다.
(4) local repository에 가져온 최신의 것과 내가 commit한 내용을
merging한다.
(5) merging된 사항을 remote repository에 올린다.
13
14. Git에서의 commit과 merge
Work Local Remote
Space Repository Repository
개발
commit -a
fetch
merge origin
push
• 좀 이상하다. merge된 결과를 다시 commit하고 push해야 할 것 같은
데.
• 그리고 merge할 때의 „origin‟은 뭐지?
14
15. 브랜치
Work Local Remote
Space Repository Repository
master
commit -a
origin
fetch
• Git는 브랜치라는 개념으로 작업본을 관리한다.
• 내가 commit한 본은 „master‟라는 이름의 브랜치로, Remote
Repository에서 가져온 것은 „origin‟이라는 이름의 브랜치로 존재
15
16. 브랜치 간 merge
Work Local Remote
Space Repository Repository
master origin
merge origin
master origin
• merge origin은 현재 작업중인 브랜치 master에 origin이라는 브랜치
의 수정된 것을 병합하라는 것이다.
• merge origin을 실행한 후에는 origin의 수정 사항(십자가)가 HEAD에
반영되었다.
• 또한 merge된 결과는 다른 명령 없이 Work Space에 그대로 반영된
다. 16
18. How To : Local Repository에
새로운 branch 생성
(1) 새로운 브랜치 „test‟를 생성
$ ls 하고, 그 브랜치로 변경한다.
first_file.txt (2) 브랜치 리스트를 조회한다.
$ git checkout –b test (1) 별표(*)가 붙은 test 브랜치가
$ git branch (2) 현재의 브랜치이다.
master
* test
$ echo “my test” > test.txt (3) (3), (4) 새로운 파일 test.txt를
$ ls (4) 만들었다.
first_file.txt test.txt
$ git checkout master (5) (5), (6) 기존의 브랜치 master
$ ls (6) 로 변경했다. 브랜치 test에서
first_file.txt 만들었던 test.txt 파일은 존재
하지 않는다.
18
19. branch 생성, 수정
Work Local
Space Repository
master master
checkout -b test
test master test
개발
test commit -a master test
test master test
• 브랜치가 생성될 때 Work Space(그냥 폴더)의 내용은 master와 같다.
• 임의의 수정(별표)하고 commit 하면 Local repository의 test 브랜치에
그 내용이 적용된다. master하고는 관계없다.
19
20. How To : 현재의 브랜치를 확인, 다른 브랜치
로 전환, 브랜치 삭제하기
$ git branch (1)
* master
test
$ git checkout test (2)
$ git branch (3)
master
• test
$ echo “some modification” > some.txt
$ git checkout master
$ git branch –D test (4)
(1) 브랜치 리스트를 조회한다. „*‟표 붙은 master가 현재의 브랜치이다.
(2) 브랜치 test로 변경한다.
(3) 현재의 브랜치는 test이다.
(4) 브랜치를 삭제한다. 변경된 사항을 무시하고 강제 삭제하려면 –D 옵
션을 준다. 20
21. 브랜치 전환
Work Local
Space Repository
test master test
checkout master
master merge test master test
master master test
• 새 브랜치 test에 적용한 사항을 master에 적용하려면 master 브랜치
로 변환한 후 „merge test‟를 한다.
21
23. Index, Git의 구성 하나 더
Work Local Remote
Index
Space Repository Repository
add
commit
• 앞의 예에서 „commit –a‟라 한 것은 변경된 사항 전부를 commit의 대
상으로 한다.
• 정확히는 commit의 대상은 오직 Index에 포함된 것만이다.
• „commit –a‟는 변경된 사항 전부를 add하고 나서 commit을 실행한 것
과 같다.
• 앞의 예에서는 전부 commit –a를 사용하였다. 설명의 간편함을 위한
것이다. 선별적으로 commit할 대상을 add하는 것이 바람직하다. 23
24. How To : 변경된 상태 보기, 특정 파일만
commit 대상으로 포함하기
$ git checkout master old_app.py를 생성하고,
$ ls new_app.py, to_be_ignored.txt
old_app.py 를 새로 만들었다.
$ echo “print „hello‟” >> old_app.py
$ echo “print „hi‟” > new_app.py
$ touch to_be_ignored.txt (1) 상태를 조회한다.
$ git status (1) old_app.py는 수정되었지만
# Changes not staged for commit: commit되지 않을 파일이라 보
# old_app.py 여주고, 나머지 2 파일은 관리되
# Untracked files: 지 않는다고 보여준다.
# new_app.py, to_be_ignored.txt
(2) old_app.py와 new_app.py
$ git add old_app.py new_app.py (2)
$ git status (3)
를 commit 대상으로 포함한다.
# Changes to be committed: (3) old_app.py와 new_app.py
# old_app.py, new_app.py 는 이제 변경되었고 commit될
# Untracked files: 것임을 보여주고 있다.
# to_be_ignored.txt
24
25. How To : 특정 파일을 ignore하기
$ vi ~/.gitignore (1)
.svn
*.pyc
$ git config --global core.excludesfile ~/.gitignore (2)
• Index에 add되지 않은 파일은 commit에서 제외되기 때문에, 따로
ignore차리 하지 않아도 된다.
• 만약 git status에서도 보이지 않게 하려면 다음과 같이 한다.
(1) ignore 대상을 명시한 파일을 생성한다. 본 예에서는 .svn 폴더와 확장
자 pyc의 파일로 하였다.
(2) 생성한 파일을 적용하도록 설정한다.
25
27. How To : 현재 작업된 것과 Local Repository
과의 차이를 비교하기
$ git commit –m “old change”
$ echo “hi” >> test.txt
$ git diff (1)
…
+hi
(1) Local repository에 commit된 것과 현재 Work Space의 차이를 보여준
다.
27
28. How To : 좀더 다양한 diff
$ git diff : Local Repository의 최근 commit된 상태와
$ git diff --cached : Index와 Local Repository간 차이
$ git diff HEAD : git diff와 동일
$ git diff HEAD^ : Local Repository의 바로 전 revision과
$ git diff HEAD^^ : Local Repository의 바로 전전 revision과
$ git diff master test : 브랜치 master와 test 간 차이
$ git diff a1b2c3 : revision “a1b2c3”간 차이
$ git diff HEAD^ a1b2c3 : Local Repository의 바로전 revision과
revision „a1b2c3‟간 차이
$ git diff origin : fetch해서 가져온 origin과 비교
• git diff에 사용되는 옵션은 브랜치 이름이거나 revision이다. 똘똘하게
알아서 찾아 준다.
• Remote Repository와 현재의 것을 비교하려면 우선 fetch 명령으로
Local Repository로 가져온 다음 diff origin으로 비교할 수 있다.
28
29. branch, HEAD, revision, master, origin
• Git는 revision에 순차적인 번호을 사용하지 않는다.
• 특정 revision에 숫자와 문자가 섞인 7 character를 사용한다.
• 그렇기 때문에 어떤 브랜치의 어떤 리비전이라고 하지 않고, diff 시에
그냥 리비전만 주면 된다.
• 만약 브랜치의 이름이 주어지면, 가장 최근의 리비전을 사용한다.
• HEAD는 현재 작업중인 브랜치의 가장 최근 리비전을 가리키는 예약
어이이다.
• 만약 브랜치를 변경하지 않았으면 master가 현재의 브랜치가 되고 HEAD 대신
master로 하여도 결과는 같다.
• master는 기본 브랜치의 이름이다.
• origin은 Remote Repository에서 가져온 브랜치의 이름이다.
29
31. 당황스런 상황
• 타 팀원이 무언가를 수정한 것 같다.
• 그 것을 확인하고 나서 내가 작업한 것을 commit하고 싶
다.
• 다른 곳에 파일 카피를 해서 백업해 둘 수는 있는데, 그렇
게 하면 일일이 손으로 하나씩 확인하며 merging 작업을
해야만 한다.
31
32. How To : 작업 하던 내용을 백업하고,
다운받은 최신 버전에 나중에 적용하기
$ git diff (1)
# Changed …. : ….
$ git stash (2)
$ git diff (3)
$ git pull (4)
$ git stash pop (5)
$ git commit –a –m “my modification” (6)
(1) 변경된 사항이 있다.
(2) 변경된 사항을 Stash에 보관해 두고, 현재의 상태를 Local Repository
의 최근 commimt 상태로 변경한다.
(3) 변경된 사항이 없음을 확인
(4) Remote Repository에서 최신 것을 가져온다.
(5) Stash에 보관된 변경사항을 적용하여 머징한다.
(6) 변경된 사항을 Local Repository에 commit 한다.
32
33. Stash를 사용한 작업 백업
Work Local Remote
Stash
Space Repository Repository
개발
stash
pull
stash pop
add, commit
• 작업 해둔 사항(별)을 Stash에 보관해 둔다.
• 보관해 둔 변경 사항은 stash pop을 사용하여 merging할 수 있다.
• 이때의 merging은 단지 Work Space에서만 진행된다.
33
34. How To : Stash에 보관된 것과
비교하고 싶다.
$ git stash list (1)
stash@{0}: WIP on master: …
stash@{1}: WIP on master: …
$ git stash show -p (2)
…
$ git stash show –p stash@{1}
(3)
…
$ git stash apply (4)
$ git stash clear (5)
(1) Stash에 저장된 것을 조회한다. 현재 2개가 있다.
(2) 최신의 것과 비교한다. –p 옵션을 주면 내용까지 확인 한다.
(3) 이름 „stash@{1}‟로 저장된 것과 비교한다.
(4) 최신의 것으로 merging한다. „stash pop‟을 사용할 경우 merging하고
삭제한다.
(5) Stash에 저장된 것을 전부 삭제한다. 34
36. 머징, 브랜치, 커밋
• 핵심 기능 merging은 오로지 Local Repository에서만 이
루어 진다. 따라서 merging을 하고 싶으면 우선 commit하
여야 한다. 이점이 SVN과 가장 큰 차이이고, 헤딩하게 만
든 원인이다.
• 무언가를 해보고 싶으면 우선 branch 부터 만들고 시작하
자. 하다 관두고 삭제해도 좋고. 그곳에서 commit된 것은
그 branch만의 문제이다. 세세한 commit으로 구성된 전체
작업이 끝나면 master로 merging하자.
• SVN에서는 소소한 것들을 commit하기 거시기 했다. 이제
는 branch 만들고 마구마구 소소하게 commit하자.
36
37. 다시 보는 Git의 구성 요소들
Work Local Remote
Stash Index
Space Repository Repository
• Stash : 작업한 내용의 백업 용도. merging 기능을 사용할 수 있다는
그 이유 때문에
• Work Space : 작업하는 폴더 그것. 다른 브랜치로 변경하면, 자동으
로 폴더의 내용가지 변환된다.
• Index : 사용자 입장에서는 반길 것 없는. 덕분에 매번 add 해주어야
한다.
• Local Repository : 모든 브랜치와 변경된 사항은 여기서 관리된다.
• Remote Repository : 타인과 공유하기 위한 공간
37
39. „fast forward‟
• 실패하는 대부분은 fast forward와 관련되어 있다.
• 버전을 관리하자는 것은 최신의 것에 자신의 수정
부분을 적용하자는 것이고, 그런 상태를 „fast
forward‟라는 용어로 표현한다.
• 만약 어떤 이유로 최신 버전에 적용할 수 없는 경우
fat forward하지 않다고 하고, 작업한 결과를 읽어
버릴 수 있다고 하여 동작이 실패한다.
• commit 하지 않은 상태에서 pull할 경우가 fast
forward하지 않은 상태이며, 이때 pull 동작은 실패
한다.
39
40. How To : 파일 삭제, 파일 명 변경
$ git mv old.txt new.txt (1)
$ git rm useless.txt (2)
(1) 파일명을 변경.
(2) 파일을 삭제
• SVN과 마찬가지로 Git는 파일명의 변경을 일일이 알려 주어야 한다.
지우고 새로 만든 것인지, 파일명만 변경되었는지 파악하지 못한다.
• 그래서 파일시스템의 rm, mv를 사용하면 곤란하다.
40
41. How To : 로그 보기
$ git log -5 --decorate --graph –oneline (1)
$ git log -5 --author=dhrim –oneline (2)
$ git log --before={3.weeks.ago} --after={2010-04-18} (3)
$ git log --grep=“some message” (4)
(1) 최근 5개의 리비전을 그래프로 보여준다.
(2) 저자가 dhrim인 리비전을 5개 보여준다.
(3) 주어진 기간내의 리비전만 보여준다.
(4) commit 메시지에 “some message”가 포함된 것만 보여준다.
41
42. How To : commit 취소하기
$ git reset --soft HEAD^ (1)
(1) Local Repository의 최신 commit 리비전을 바로전 리비전(HEAD^)로
설정한다. Index와 Work Space는 건드리지 않는다.
42
43. How To : 특정 리비전 다운 받기
$ git checkout –b new a1b2c3 (1)
(1) 새로운 브랜치 „new‟를 생성하고 그 곳에 리비전 „a1b2c3‟을 내려받는
다.
43
44. How To : 매뉴얼 보기
$ git help stash (1)
$ man git-stash (2)
(1) stash 명령에 대한 man 페이지를 보여준다.
(2) 위 (1) 명령과 동일한 액션을 취한다.
44
45. How To : GitHub에 브랜치 만들기
• GitHub에서의 branch는 지금껏 얘기한 것과 약간 다른 용도로 사용됩
니다. 대표적인 것이 release를 위한 branch이죠. SVN에서의 branch
와 tag의 용도와 거의 유사합니다.
• linux상에서도 만들 수 있는 것 같은데 web으로 만드는 것을 설명합니 45
다.
46. How To : GitHub에 브랜치 만들기
• „Forks‟ 아이콘을 클릭합니다.
46
47. How To : GitHub에 브랜치 만들기
• „Fork Queue‟ 탭을 클릭합니다.
47
48. How To : GitHub에 브랜치 만들기
• „change it‟을 클릭합니다.
48
49. How To : GitHub에 브랜치 만들기
• „create a new branch‟에 새 브랜치의 이름을 입력하고 „change
branch‟ 버튼을 클릭합니다.
49
50. How To : GitHub에 브랜치 만들기
• 브랜치 리스트에 생성한 new_branch가 보입니다.
50
51. Reference
• git 홈 : http://git-scm.com/
• 한글과 그림으로 설명. 길지 않음. :
http://kimseunghyun76.tistory.com/116
• SVN과 비교한 설명 :
https://git.wiki.kernel.org/articles/g/i/t/GitSvnCrashCourse_512d.html
• 무엇 무엇 하기로 정리된. 한글 :
http://poongcha.blogspot.com/2009/06/git.html
• 자세한. 그러나 긴. 한글 : http://shinji.springnote.com/pages/2055296
• 브랜치의 활용을 설명한. 한글 : http://dalinaum-
kr.tumblr.com/post/15516936704/git-work-flow
• Git 공식 reference : http://gitref.org
• 치트시트 모음 : http://devcheatsheet.com/tag/git/
• 추천 online 치트시트. html : http://ndpsoftware.com/git-
cheatsheet.html#loc=local_repo;
51