9. 버전 관리
개발 생산성 향상에 대한 요구 증대
소스 코드의 변경 이력을 관리
소프트웨어 형상 관리의 일부분
SVN, Git, ClearCase, CVS, !
Visual Source Safe
10. 버전 관리 - Dark Age
• 파일 이름에 날짜, 버전(v1,v2..)를 붙여서 복사!
• tar등으로 압축하여 통재로 복사!
• 변경된 부분에 대해서 소스코드 비교!
• 실수로 인한 코드 유실!
• rm -rf!
• 사장님은 그져 백업이 중요하다고만 하셨어~
11. 버전 관리 시스템
• VCS(Version Control System)!
• SCM (Source Code Management System)!
• 특정 시점 및 변경 추적!
• 다양한 버전 관리!
• 협업을 위한 코드 공유!
• 접근 제한
12. 버전 관리 시스템
소스 코드의 변경 이력을 관리
• 소스코드 추가/수정/삭제에 대한 기록을 저장
!
!
• 즉, 별도로 파일을 카피해 놓거나 백업하지 않아도 됨
• 언제든지 원하는 시점으로 파일의 상태 변경이 가능함으
로 파일 내용 변경에 대해서 유연성을 제공함
• 변경 내용에 대한 소스코드의 비교 가능
14. 중앙 집중형 VS 분산형
computer A
file
repository
computer B
file
repository
Server Computer
repository
computer A
file
Central VCS Server
repository
computer B
file
15. 분산형 소스 코드 버전 관리 시스템
• 지역 저장소와 원격 저장소로 구분!
• 지역 저장소에서 개별 버전 관리!
• 원격 저장소로 내용 공유!
• 원격 저장소 장애나 인터넷 연결이 되
지 않아도 버전 관리 가능함!
• 원격 저장소 장애로 내용물 유실시에
도 지역저장소에서 복구 가능함
computer A
file
repository
computer B
file
repository
Server Computer
repository
21. Git의 역사
• 1991-2002 - 리눅스 커널 개발 관련 하여 파일로 패치 관리!
• 2002 - 분산 버전 컨트롤 시스템인 Bitkeeper를 사용하게 됨!
• April 2005 - Bitkeeper 라이센스 이슈로 인하여 , Linus
Torvalds는 직접 개발(0.0.1)하게 됨(약 2주)!
• GitHub(2008년경)로 인해서 폭발적으로 성장함!
• Latest Version 2.4.4(2015/06/16)
22. Git의 특징
• 단순한 구조!
• 브랜치 모델 (비 선형적 개발 지원)!
• 빠른 성능 (Speed and Performance)!
• Git 특유의 분산환경 지원(지역 저장소, 원격 저장소)!
• 데이타 무결성 보장!
• 스테이징 영역 모델을 채용하여 커밋전 오류를 줄여줌!
• 리눅스 커널 같은 대형 프로젝트에 유용
23. 강의목표
• 지역저장소와 원격저장소의 개념을 이해합니다.!
• Git의 가장 큰 장점이라할 수 있는 브랜치에 대해서 알아봅니다.!
• Git의 동작 원리에 살펴 봅니다.!
• CLI(Command Line Interface) 명령과 이클립스(Eclipse)를
주로 사용해서 설명합니다.
88. • Working directory에 존재하는 파일들의 상태!
• 스냅샷 포함 유무!
✓ Tracked File - 이미 스냅샷에 포함되어 있는 파일로써
Repository 에 의해서 관리 되고 있는 파일이다.!
✓ Untracked File - 스냅샷에 존재하지 않으므로 등록되지 않
아 삭제되면 복구할 수 없다.(add를 통하여 Tracked File)
Status
89. Tracked File status Lifecycle
Tracked File은 Modified, Staged, Committed 상태로 관리
Working
Directory
Staging
Area
Commit
repository
Checkout the project
Staging
92. git status
On branch master!
!
Initial commit!
!
Untracked files:!
(use git add file... to include in
what will be committed)!
!
! .classpath!
! .project!
! .settings/!
! pom.xml!
! src/!
! target/!
!
nothing added to commit but untracked
files present (use git add to track)
$
94. Tracked File status Lifecycle
Tracked File은 Modified, Staged, Committed 상태로 관리
Working
Directory
Staging
Area
Commit
repository
Checkout the project
Staging
98. 물품리스트 주문내역
담기 구매
스테이징 영역
• 커밋될 예정인 파일의 내용을 준비하는 곳입니다.(곧 커밋할 것이라는 표시)!
• 커밋할때 의미적인 단위(atomic) 로 하는 것이 바람직하다. 다른 VCS에서는
골라서(in working directory - 고르는 비용 절감) 할 수 도 있지만 Git에서는
스테이징 영역에 등록하고 커밋을 한다.
“쇼핑몰에서 물건을 구매할때 먼저 장바구니에 넣는것과 유사하다”
106. git status
On branch master!
!
Initial commit!
!
Changes to be committed:!
(use git rm --cached file... to unstage)!
!
! new file: .classpath!
! new file: .gitignore!
! new file: .project!
! new file: .settings/org.eclipse.core.resources.prefs!
! new file: .settings/org.eclipse.jdt.core.prefs!
! new file: .settings/org.eclipse.m2e.core.prefs!
! new file: pom.xml!
! new file: src/main/java/chap02/Greeter.java!
! new file: src/main/java/chap02/Main.java!
! new file: src/main/java/chap02/Main2.java!
! new file: src/main/resources/applicationContext.xml
$
108. Tracked File status Lifecycle
Tracked File은 Modified, Staged, Committed 상태로 관리
Working
Directory
Staging
Area
Commit
repository
Checkout the project
Staging
130. .gitignore
• 관리하지 않는 파일의 규칙을 정의한다.!
• #은 주석이다.!
• 표준 Glob패턴을 사용한다.!
• 디렉터리는 슬래시를 끝에 사용하는 것으로 표현한다.!
• ! 로 시작하는 패턴의 파일은 무시하지 않는다.
131. .gitignore
‘#’ 으로 시작하면 주석이므로 적용되지 않습니다.!
# 확장자가 .a인 파일 무시!
*.a!
# 윗 줄에서 확장자가 .a인 파일은 무시하게 했지만 lib.a는 무시하
지 않는다. 순서상 뒷 부분에 위치 해야함!
!lib.a!
# 루트 디렉토리에 있는 TODO파일은 무시하고 subdir/TODO처
럼 하위디렉토리에 있는 파일은 무시하지 않는다.!
/TODO
관리하지 않는 파일의 규칙을 정의
132. .gitignore
# build/ 디렉토리 하위에 있는 모든 파일 및 디렉터리를
은 무시한다.(tree object가 상위부터 생성)!
build/!
# `doc/notes.txt`같은 파일은 무시하고 doc/server/
arch.txt같은 파일은 무시하지 않는다.!
doc/*.txt!
# `doc` 디렉토리 아래의 모든 .txt 파일을 무시한다.!
doc/**/*.txt
관리하지 않는 파일의 규칙을 정의
136. git status
On branch testing!
Changes not staged for commit:!
(use git add file... to update
what will be committed)!
(use git checkout -- file... to
discard changes in working directory)!
!
! modified: src/main/java/chap02/
Main.java!
!
no changes added to commit (use git
add and/or git commit -a)
$
162. config
• 환경 설정 값들을 지정하거나 조회할 수 있음!
• git commit 명령어 사용시 이메일, 이름이 설정되어 있어야 함
$ git config --global user.name YOUR NAME
$ git config --global user.email YOUR EMAIL
165. config
• 적용순위 : 저장소 변수 사용자 변수 시스템 변수!
• 사용자(User) 설정 - 사용자 홈 디렉터리의 ~/.gitconfig!
• 저장소(Repository) 설정 - .git/config!
• 시스템(System) 설정 - /etc/gitconfig!
• 동일 변수가 3군데 존재할 수 있음 !
• 우선순위가 높은 값으로 override됨
166. git config --list$
user.name=jiwon!
user.email=jiwon@narusec.com!
filter.media.clean=git media clean %f!
filter.media.smudge=git media smudge %f!
filter.media.required=true!
core.excludesfile=/Users/jw0201/.gitignore_global!
difftool.sourcetree.cmd=opendiff $LOCAL $REMOTE!
difftool.sourcetree.path=!
mergetool.sourcetree.trustexitcode=true!
filter.hawser.clean=git hawser clean %f!
filter.hawser.smudge=git hawser smudge %f!
filter.hawser.required=true!
merge.tool=vimdiff!
user.name=Jongmin Kim!
user.email=jw0201@gmail.com
시스템 설정
사용자 설정
저장소 설정
167. git config [--global] key [value]
환경 설정 값 set/get!
!
git config --global user.name [이름]
$
253. 정의
• 공통의 개발 코드에서 병행(비 선형) 개발 하기 위해서 특정 분기 생성!
• 사전적 의미 - 분기하다. 갈라지다.
branch
hotfix
master
254. 목적
• 브랜치를 이용한 병행개발을 통해서 지속적이고 안정적인 소프트
웨어 개발이 가능하다.!
✓ 기본적으로 master 브랜치 와 topic 브랜치를 분리!
• 브랜치를 이용하여 목적에 맞는 제품 개발이 가능하다.!
✓ 제품 출시 일정, 기능, 고객에 맞는 제품 개발
255. 브랜치 전략
• 신규기능, 버그수정, 실험 적인 작업이 요구될때 사용한다.!
• 같은 기능 개발 중에서도 다양한 실험의 목적으로 브랜치에서
도 새로운 브랜치를 생성한다.!
• 브랜치로 작업하고 있다면 수정된 내용을 모두 취소 하고 싶을
때 브랜치만 삭제하므로 간단하다.
256. Git 브랜치 장점
• 규모가 큰 프로젝트에서도 빠르고 안정적이다.!
• 브랜치 이동(switch)이 매우 간편하다.(vs 중앙 집중형)!
• 브랜치 생성 비용이 낮다.(vs Mercurial)!
• 브랜치의 이력도 병합시 모두 포함 된다.
260. commit
commit size
Spring4-Chap02 Initial Commit
-tree d12825
-auther Jongmin
•commiter Jongmin
886230
Snapshot A Snapshot B
commit size
Main.java에 테스트 코드 추가
-tree 9be6b2
-auther Jongmin
•commiter Jongmin
269f3d
Git commit의 객체 데이터
261. snapshot
commit size
Main.java에 테스트 코드 추가
tree size
blob size
/target/
.settings/
.classpath
.project
-blob 30b2b7 .gitignore
-blob 3e1dab pom.xml
•tree b7d9de src
-tree 9be6b2
-auther Jongmin
•commiter Jongmin
blob size
tree size
?xml version=1.0
encoding=UTF-8 ?
project xmlns=http://
maven.apache.org/POM/4.0.0
269f3d
9be6b2
30b2b7
3e1dab
b7d9de
저장소의 커밋 데이터
snapshot:commit객체로
찾을 수 있는 tree 이하 부분
tree a61fb9 main
263. commit
Snapshot C
commit size
Main.java에 테스트 코드 추가 두번째
-tree fe9cc4
-auther Jongmin
•commiter Jongmin
df0902
commit size
Spring4-Chap02 Initial Commit
-tree d12825
-auther Jongmin
•commiter Jongmin
886230
Snapshot A Snapshot B
commit size
Main.java에 테스트 코드 추가
-tree 9be6b2
-auther Jongmin
•commiter Jongmin
269f3d
Git commit의 개체 데이터
264. master branch
Snapshot A Snapshot B Snapshot C
886230 269f3d df0902
master
가장 최근 커밋 정보를 가리키는 브랜치
master : Git에서의 기본 브랜치명
319. git checkout master$
git merge testing$
Auto-merging src/main/java/chap02/
Main2.java!
Merge made by the ‘recursive’ strategy!
!!!!!!!!src/main/java/chap02/Main2.java
| 1+!
!!!!1 file changed, 1 insertion(+)
3-Way Merge(Auto Merge)
320. 886230 269f3d df0902 d9124a
testing
master
7b19650
b00809c
git merge testing$
40c02ed
3way-Merge에서는 Merge에 대한 정보가 들어 있는 커밋(Merge Commit)를 하나 만든다.
3-Way Merge(Auto Merge)
337. Git command flow
모든 repository는 개별적으로 branch이다.
remote
repository
local
repository
fetch
push
local
repository
push
fetch
local
repository
338. remote branch
• push도 하나의 원격 저장소 입장에서 merge 행위!
• merge는 내가 다른 branch의 것을 가져오는 행위!
• remote repository는 사람이 아니므로 FF만 허용됨!
• push하려는 local repository는 remote repository의 최
신의 상태를 가지고 있어야 함!
• 따라서 push 하기 이전에 pull 명령어를 사용하여 원격 저
장소에 가장 최근에 업데이트 된 내용을 모두 받아서 merge
해야함
358. The .git folder
• HEAD - 체크아웃된 브랜치(스냅샷 시작 포인트)!
• branches/ - 현재 사용되지 않음 !
• config - 해당 저장소에만 존재하는 git 환경 설정 파일!
• description - GitWeb 프로그램 에서만 사용 함!
• index - 스테이징 에어리어 정보를 저장(최초에는 존재하지 않음)!
• hooks/ - 클라이언트 훅이나 서버 훅 내용을 저장함(최초에는 .sample이 존재)!
• objects/ - git의 object가 저장되어 있는 데이터베이스 디렉터리(repo content)!
• refs/ - commit object의 포인터를 저장!
• logs/ - commit 명령어를 통해서 생성되고 git-log명령어를 통해서 조회
ref: ref/head/master
360. • Blob - 파일이 저장되는 객체(실제 저장되는 파일)!
• Tree - Blob(또는 Tree)을 포인팅하는 디렉터리 객체!
• Commit - 커밋하면 생성되는 객체!
• Tag - 특정 commit 객체에 대한 alias
Git is a content-addressable filesystem
.git/objects
4가지 객체
361. commit, tree, blob
tree a61fb9 main
commit size
Main.java에 테스트 코드 추가
tree size
blob size
/target/
.settings/
.classpath
.project
-blob 30b2b7 .gitignore
-blob 3e1dab pom.xml
•tree b7d9de src
-tree 9be6b2
-auther Jongmin
•commiter Jongmin
blob size
tree size
?xml version=1.0
encoding=UTF-8 ?
project xmlns=http://
maven.apache.org/POM/4.0.0
269f3d
9be6b2
30b2b7
3e1dab
b7d9de/ 디렉터리 역할
snapshot:commit객체로
찾을 수 있는 tree 이하 부분
363. commit’s parents
Snapshot C
commit size
Main.java에 테스트 코드 추가 두번째
-tree fe9cc4
-auther Jongmin
•commiter Jongmin
df0902
commit size
Spring4-Chap02 Initial Commit
-tree d12825
-auther Jongmin
•commiter Jongmin
886230
Snapshot A Snapshot B
commit size
Main.java에 테스트 코드 추가
-tree 9be6b2
-auther Jongmin
•commiter Jongmin
269f3d
364. 4가지 개체
• Blob - 파일이 저장되는 객체(실제 저장되는 파일)!
• Tree - Blob(또는 Tree)을 포인팅하는 디렉터리 객체!
• Commit - 커밋하면 생성되는 객체!
• Tag - 특정 commit 객체에 대한 alias
Git is a content-addressable filesystem
.git/objects
374. 4가지 객체
• Blob - 파일이 저장되는 객체(실제 저장되는 파일)!
• Tree - Blob(또는 Tree)을 포인팅하는 디렉터리 객체!
• Commit - 커밋하면 생성되는 객체!
• Tag - 특정 commit 객체에 대한 alias
Git is a content-addressable filesystem
.git/objects
378. tree
• Blob object를 포함하는 최소 1개 존재!
• 현재 Index된 정보에 대해서 tree생성!
• Git은 empty 디렉터리를 추적 하지 않음!
• 디렉터리에 파일이 존재하면 Tree Object를 생성하여 연결!
• Blob, Tree 에 대한 정보 포함!
• Filename, SHA-1, type(blob or tree), Permission
379. tree
git commit -m “commit file”$
2f398
0644 blob 1f7a7 test.txt
name : SHA-1
content : 암호화된 내용
plumbing$ git write-tree!
2f39845a4a2c3ad86adebb00b1ddabd959c131c4 test.txt
381. • Blob - 파일이 저장되는 객체(실제 저장되는 파일)!
• Tree - Blob(또는 Tree)을 포인팅하는 디렉터리 객체!
• Commit - 커밋하면 생성되는 객체!
• Tag - 특정 commit 객체에 대한 alias
Git is a content-addressable filesystem
.git/objects
4가지 객체
386. • Blob - 파일이 저장되는 객체(실제 저장되는 파일)!
• Tree - Blob(또는 Tree)을 포인팅하는 디렉터리 객체!
• Commit - 커밋하면 생성되는 객체!
• Tag - 특정 commit 객체에 대한 alias
Git is a content-addressable filesystem
.git/objects
4가지 객체
389. 파일이 조금이라도 변경되서 다시
객체가 계속 만들어지면 나중에 .git
의 용량이 너무 커지는거 아닌가요?
390. packfile
• 최초에 생성된 object를 Loose 개체 포맷이라고 한다.!
• 스냅샷을 각 commit별로 별도로 생성되는데 만약 1byte라도
변경되면 새로운 스냅샷을 생성하게 된다.!
• 압축(zlib)을 하지만 그래도 중복이 많다.!
• packfile을 만들어 유사한 내용을 제거하여 관리할 수 있다.!
• git gc로 수동 생성!
• git push에서 자동 수행!
• object의 숫자가 증가하면 자동으로 수행
391. packfile
git gc$
$ git gc!
Counting objects: 73, done.!
Delta compression using up to 8 threads.!
Compressing objects: 100% (45/45), done.!
Writing objects: 100% (73/73), done.!
Total 73 (delta 22), reused 0 (delta 0)
393. 참고
• 프로 Git , 스캿 사콘(인싸이트)!
• http://git-scm.com/book/ko/v1!
!
• EGit 사용자 가이드!
• https://wiki.eclipse.org/EGit/User_Guide!
!
• 분산 버전 관리 Git 사용설명서(제이펍)!
• 협업 소프트웨어 개발을 위한 강력한 도구와 기술(제2판)!
• 존 롤리거, 매튜 매컬러프 공저!
!
• 리누스 토발즈 인터뷰!
• http://techholic.co.kr/archives/31767
394. Git 학습 방법
• 점짐적 학습, 즉 쉽고 간단한 명령부터 복잡하고 정교한 명령 사용!
• 직접 해 보는 것이 무엇 보다 중요!
• CLI, GUI 툴 동시 사용!
• 내부 동작을 이해하는 것이 많은 도움이 됨
395. About Conflict
• local branch의 merge 또는 pull하는 과정에서 발생함!
• 되도록 만나지 않으려면 최대한 자주 pull, push 하도록 권장!
• 자주 커밋할 수 있도록 하려면 논리적으로 작업을 잘 분할 해야 함!
• 부득이하게 pull과 checkout작업이 필요할 경우 stash할 수도 있음!
• merge tool을 사용한 적극적인 resolving conflict