1. master 브랜치에서 커밑 c0,c1,c2를 수행한다.





2. iss53 브랜치를 생성한다.




3.iss53 브랜치에서 커밑 c3을 수행한다.




4.별도의 hotfix 브랜치를 또 생성하고 , 커밑 c4를 수행한다.




5. 이때 hotfix브랜치를 master 브랜치에 병합시키는데, hotfix브랜치의 커밑 내용(c0-c1-c2-c4)은 master 브랜치의 내용(c0-c1-c2)에서 c4가 추가된 것뿐이다. 따라서 hotfix의 내용을 그대로 참조해도 기존 master브랜치의 손상되는 커밑이 없다.


이처럼, 병합시 새로운 커밑없이 병합되는 것을 fast-forwarding 이라고 하는데, 이는 master 브랜치가  hotfix의 커밑 c4으로 가서 커밑 c4의 내용을 그대로 참조하면 되기 때문에 붙은 이름이다.





6. iss53 브랜치로 체크아웃후 커밑 c5를 수행한다.





7. iss53 브랜치를 master 브랜치로 병합시키려 한다. 이때, master브랜치의 내용(c0-c1-c2-c4)과 iss53의 내용(c0-c1-c2-c3-c5)은 c2커밑 이후에 완전 다르므로 위와 같은 fast-forwarding 방법을 사용할 수없다. 이와 같은 상황에서는 recursive 병합을 사용하는데, 병합을 위해 커밑 c6를 새롭게 생성한다.





1. branch 만들기

・브랜치를 해야하는 상황

기존에 여러가지로 응용될 수 있는 모듈을 개발해 놓은 상태

각각의 클라이언트의 맡게 기존 모듈을 부분적으로 수정해야함

기존 모듈을 더럽히지 않고, 각각의 클라이언트에게 맞는 새로운 소스코드를 브랜치에서 작성

・git branch : 브랜치의 목록을 볼 때

-브랜치를 생성하지 않아도, 기본 master브랜치가 존재

-브랜치를 생성하면, 직전 속해있던 브랜치의 상태를 그대로 가져온다.

・git branch "새로운 브랜치 이름" : 새로운 브랜치를 생성

・git checkout "전환하려는 브랜치 이름" : 다른 브랜치로 갈아탈 때




브랜치의 목록을 볼 때

git branch


브랜치를 생성할 때 

git branch "새로운 브랜치 이름"


브랜치를 삭제할 때

git branch -d


병합하지 않은 브랜치를 강제 삭제할 때 

git branch -D


브랜치를 전환(체크아웃)할 때

git checkout "전환하려는 브랜치 이름"


브랜치를 생성하고 전환까지 할 때 

git checkout -b "생성하고 전환할 브랜치 이름



2. branch 간 정보확인

[지금까지의 작업흐름]

master 브랜치에서 test1.txt에 내용 1추가

master 브랜치에서 test1.txt에 내용 2추가

exp 브랜치 생성한 후 exp브랜치로 head이동

exp 브랜치에서test2.txt생성

exp 브랜치에서 test2.txt에 내용 3추가

exp 브랜치에서 test2.txt에 내용 4추가

master 브랜치로 head이동

master 브랜치에서 test3.txt생성

master 브랜치에서 test3.txt에 내용 5추가

・git log --branches --graph --decorate : (HEAD -> exp)리스트와 (master)리스트가 별도로 표시됨

(log는 repository(commit된 대상)를 기준으로만 표시된다.)


・git log --branches --graph --decorate --oneline : 브랜치간 변화를 최소한의 행으로 보여줌

・git log "비교할 브랜치 명 1".."비교할 브랜치 명 2" : 마스터브랜치에는 없고 exp에는 있는 커밋을 보여줌

・git diff "비교할 브랜치 명 1".."비교할 브랜치 명 2" : 브랜치 간의 코드를 비교 할 때 



브랜치 간에 비교할 때

git log "비교할 브랜치 명 1".."비교할 브랜치 명 2"


브랜치 간의 코드를 비교 할 때 

git diff "비교할 브랜치 명 1".."비교할 브랜치 명 2"


로그에 모든 브랜치를 표시하고, 그래프로 표현하고, 브랜치 명을 표시하고, 한줄로 표시할 때 

git log --branches --graph --decorate --oneline


3.브랜치의 병합

[지금까지의 작업흐름]

master 브랜치에서 test1.txt에 내용 1추가

master 브랜치에서 test1.txt에 내용 2추가

exp 브랜치 생성한 후 exp브랜치로 head이동

exp 브랜치에서test2.txt생성

exp 브랜치에서 test2.txt에 내용 3추가

exp 브랜치에서 test2.txt에 내용 4추가

master 브랜치로 head이동

master 브랜치에서 test3.txt생성

master 브랜치에서 test3.txt에 내용 5추가

・각각의 브랜치에서 각기 다른 일을 전개해 나가다가 하나로 병합해야 할 일이생길때 사용하는 branch merge

・(HEAD가 master 브랜치에 있을 때) git merge exp

-이때 주의할 점은 exp 브랜치의 결과를 master 브랜치로 병합시키기 위해선, head를 마스터 브랜치로 설정한 상태에서merge명령어를 수행해야한다.

・merge후 탄생한 커밑은 master 브랜치의 최후 커밑(master 브랜치에서 test3.txt에 내용 5추가)과 exp 브랜치의 최후 커밑(exp 브랜치에서 test2.txt에 내용 4추가)를 동시에 부모로 갖는다.

・이때 master는 1,2,3,4,5를 전부가지지만, exp는 3,4만 지니므로 master와 exp는 완전이 동일하지 않다.

(master와 exp의 결과가 완전 동일하지 않아, HEAD가 master만을 가르키고 있는 것을 볼 수 있다)


・(HEAD가 exp 브랜치에 있을 때) git merge master -> 이제 master와 exp의 상태가 완전동일

(양쪽에서 서로를 병합한 결과 master와 exp의 결과가 완전 동일해, HEAD가 master와 exp 둘다를 가르키고 있는 것을 볼 수 있다)


・병합이 끝나면 

・git branch -d exp로 exp 브랜치 삭제



3. merge conflict

・충돌이 일어나는 이유
A와 B 브랜치가 가지고 있는 common.txt 파일의 같은 위치(같은 행)에서 변화가 일어나면, git은 A브랜치의 내용을 가져와야하는지 B브랜치의 내용을 가져와야 하는지 판단하지 못한다. 따라서 수동 fix가 필요하다.

・충돌시 해결법 : 수동으로 하는 방법뿐..

충돌이 생기면 아래와 같은 메시지가 뜹니다. 

git status를 하면 충돌이 일어난 파일을 찾을 수 있습니다. 

 충돌이 발생한 파일을 수정합니다. 아래와 같습니다. 

'<<<<<<< HEAD' 부터 '=======' 사이의 구간이 현재 체크 아웃된 파일의 내용이고 '=======' 부터 '>>>>>>> exp' 사시의 구간이 병합하려는 대상인 exp 브랜치의 코드 내용입니다.  이 정보를 참고로해서 두개의 코드를 병합한 후에 특수기호들을 제거해주시면 됩니다. 작업이 끝나면 파일을 저장.


4. stash

・stash

다른 브랜치로 checkout을 해야 하는데 아직 현재 브랜치에서 작업이 끝나지 않아 커밋을 하기가 애매한 경우에는

현재 브랜치의 변경사항을 커밑하지 않았기 때문에 다른브랜치로 checkout을 할 수가 없습니다.

이런 경우 stash를 이용하면 작업중이던 파일을 임시로 저장해두고 현재 브랜치의 상태를 마지막 커밋의 상태로 

초기화 할 수 있습니다. 그 후에 다른 브랜치로 이동하고 작업을 끝낸 후에 작업 중이던 브랜치로 복귀한 후에 

이전에 작업하던 내용을 복원할 수 있습니다. 여기서는 이 기능에 대해서 알아봅니다. 


[현재까지의 작업흐름]

master 브랜치에서 test1.txt에 내용 a추가

exp 브랜치 생성한 후 exp브랜치로 head이동

exp 브랜치에서test1.txt에 b내용 추가


・exp에서 2를 추가했는데, 이때 exp에서 제대로 커밑하지 않고 master 브랜치로 옮기면 수정된 내용이 master 브랜치에 까지 영향을 미친다.

-그렇다면, 아직수정이 안된 exp의 text1.txt를 커밑하지가 뭐한데.. 어떻게해야할까? 이때 사용하는 것이 stash!


・git stash하면 커밑하지 않은 작업내용(b추가)이 저장됨

・이후에는 master브랜치로 checkout도 가능해짐

・git stash apply하면 아까 stash했던 작업내용이 되살아남

・git stash list하면 stash했던 항목이 표시되는데, 한번 stash 리스트에 저장된 작업은, reset으로 날려도 다시 살릴 수 있다.

・그런데 stash 리스트에 복수개가 있으면 어떻게 할까?

・stash list에는 가장 최신이 위에 쌓이고, 이전것이 아래에 쌓이는데


stash@{0} : WIP on exp : 9161e43 1

stash@{1} : WIP on exp : 9161e43 1

stash@{0}을 적용하고 stash@{1}을 적용하고 싶다면

git stash apply (stash@{0} 적용)

->

git stash drop (가장 최신 stash인 stash@{0}삭제)

->

git stash apply (stash@{1} 적용)


 

・git stash pop : 가장 최신의 stash를 apply하고 적용한 stash를 삭제해버림

+ git stash는 index에 포함된 파일을 대상으로함. 즉 add까지는 된 놈이여야함.

[add, commit, status의 원리]


오브젝트 id란, 40개의 숫자의 영문자의 조합으로 이루어진 것으로 커밑 당시의 폴더구조와 파일내용의 전체 상태를 가르키는 참조값이다.


1. git add의 원리

・git add practice.txt를 하면 git의 target이 됨. 

add된 대상을 tracked라고 하고, 그렇지 않은 대상을 untracked라고함

・git의 object 폴더의 하위폴더78번(고유파일이름 98oxxail13k2k...)에 practice.txt의 내용을 담음

・index에 practice.txt의 파일이름을 담음


・git add practice2.txt를 하면 git의 target이 됨

・git의 object 폴더의 하위폴더80번에 practice2.txt의 내용을 담음

・index에 practice2.txt의 파일이름을 담음


・만약에 practice.txt파일을 복사해서 practice3.txt로 이름만 바꾸고 내용은 그대로라면?

・practice3.txt와 practice.txt의 내용이 동일할 경우, 내용은 이미 하위폴더78(고유파일이름 98oxxail13k2k...)에 담겨잇으므로 practice3.txt에 있어서는 패스를 참조만 시킴

・index 파일에는 practice3.txt의 이름을 담음


・정리하면 add를 하게되면 git 내부에서는 2가지의 일이 발생하는데,


-첫번째로, 파일의 내용을 담기위해 파일 내용을 특정한 규칙에 의해 40개의 영문자 조합으로 바꾼 값을 파일명(이것을 오브젝트id라고함)으로 지정하고, 또 그때의 파일내용을 생성된 오브젝트 id로 된 이름의 파일명 안에 내용물(바이너리)로 저장함(이때의 파일은 .git/objects 폴더 아래에 담김)


-두번째로, 파일의 이름을 index파일(바이너리)에 담음(이때의 파일은 .git/index 파일에 담김)


-add 할때 생성되는 오브젝트 아이디는 하나하나 파일명과 그 파일 내용만을 담지만,

commit할때 생성되는 오브젝트 아이디는 커밑할 당시의 모든 디렉토리와 파일에 대한 내용을 담는다.


-이때,내용이 같은 경우 파일의 내용을 참조하는 참조값(파일명)을 새롭게 생성하지 않고

같은 내용을 가진 오브젝트를 재활용하여 참조시키며, 새롭게 add한 파일이름만 index에 담음


・그런데 내용을 기반으로 해서 같은 파일이름을 만드는 원리는 어떻게 되는 것일까?

www.sha1・online.com을 참조해 hash 함수를 실행시켜볼것

・git은 파일의 내용을 hash 알고리즘을 통과시켜서, 그 결과 나온 해쉬값을 도출한다.

해쉬값의 맨앞 2글자를 object 하위의 폴더로 만들고, 그 밑에 나머지 해쉬값을 파일이름으로 저장한다.

・예)a를 입력하면 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 해쉬값 도출

.git(폴더) ・ object(폴더) ・ 86(폴더) ・ f7e437faa5a7fce15d1ddcb9eaeaea377667b8(파일)

・> 실제로 확인해 볼 것.

・실제 git은 입력한 정보와 git만의 고유 부가 정보를 합쳐 해쉬코드를 도출해낸다.







(.git 디렉토리를 열어본 모습, 실제로 index파일과 참조값(파일명)이 쌓이는 objects폴더가 존재함을 볼 수 있다)


2.git commit의 원리

・커밋을 시행할시 주요정보가 2개 만들어진다. 

-첫번째는 커밑의 오브젝트 id를 생선하는데, 커밑의 오브젝트 id는 "커밋이 일어난 시점"에 작업 디렉토리에 있는 모든 디렉토리와 파일정보(파일명,내용)을 담고있음. 

-두번째는 이전 커밋된 내용을 담는 parent 값이 생성되고,

-add 할때 생성되는 오브젝트 아이디는 하나하나 파일명과 그 파일 내용만을 담지만,

commit할때 생성되는 오브젝트 아이디는 커밑할 당시의 모든 디렉토리와 파일에 대한 내용을 담는다.


・각각의 커밋버전마다 서로다른 트리 이름을 참조하고 있고, 그 트리에는 당시 커밋 시점의 파일 이름과 내용의 참조값(파일명)을 가지게된다.


*git commit --amend : 커밑에서 내용누락시 오브젝트id는 그대로고 내용만 수정가능





・이러한 원리를 스냅샷을 찍었다고 부른다.


・object의 3형태

파일의 내용을 담고 있는 object참조값(파일명)을 가지는 blob

파일명과 내용을 담고 있는 object참조값(파일명)을 가지는 blob의 집합을 담고 있는 tree

마지막으로 commit



(tree에 blob의 집합 , blob에 파일내용을 참조하는 참조값(파일명)과 파일이름이 격납되어 있음을 알 수 있다.)



3.git status의 원리

index 파일에 담긴 값과 최후의 commit의 tree에 담긴 값들을 비교하여 알아낸다.





출처 : https://opentutorials.org/course/2708/15241

본글출처:http://slowalk.tistory.com/2470


혹시 git(깃)이라고 들어보셨나요? IT에 종사하거나 프로그래밍을 업으로 삼고 계신 분들은 알고 계실 텐데요. 오늘은 git을 처음 들어보신 분들이나, 써보려 했으나 진입장벽이 너무 높아 엄두가 안나셨던 분들을 위해 간략하게 git을 소개하고 활용하는 방법에 대해 알아보도록 하겠습니다(초보자 분들의 조금 더 쉬운 이해를 돕기 위해 git의 개념을 제 나름대로 재해석하였습니다).



git?

git은 분산 버전(이력)관리 시스템 입니다. 두 가지 기능이 합쳐져 있는데요. 바로 분산과 버전관리입니다. 자, 그럼 먼저 버전관리란 무엇일까요?

우리는 일상에서 알게 모르게 버전관리를 하고 있습니다. 간단한 예로, 학교 발표자료나 리포트를 작성한다고 했을 때, 여러분의 폴더 모습은 아마 아래와 같을 것입니다.

 

작성 중간중간 다른 이름으로 자주 저장해 두어야 정전과 같은 사태로 자료가 유실되는 불상사를 막을 수 있고, 잘못 수정된 자료가 있다면 과거 기록을 바탕으로 복원할 수 있겠죠? 위와 같이, 특정 시점을 기억하고 이를 재활용할 수 있게 규칙을 정해 파일을 관리하는 것을 버전(이력)관리라고 합니다.

그렇다면 분산은? 말그대로 내가 관리하는 문서를 여러 장소로 나누어 저장한다는 뜻입니다. git은 아래 그림과 같이 네트워크를 통해 연결된 다른 컴퓨터에 문서를 분산하여 관리할 수 있는 기능을 제공합니다.



문서를 분산하여 저장하면 어떤 장점이 있을까요? 만약 하나의 컴퓨터에서 문서를 저장/관리하는데 그 컴퓨터가 고장난다면, 해당 문서는 다시 볼 수 없게 될지도 모릅니다. 따라서 문서를 여러 장소에 나누어 보관한다면 위와 같은 상황이 발생해도 안전하게 문서를 복구할 수 있지요. 하지만 git의 분산 기능은 문서의 안정성만을 위한것이 아닙니다. git이 분산기능을 통해 구현하고자 하는 바는 바로 ‘협업’입니다.

예를 들어 1000페이지 분량의 논문이 있고, 이를 검수 및 수정하는 작업을 진행한다고 하겠습니다. 한 명이 하루에 검수 할 수 있는 양이 100페이지라 했을 때, 이 작업은 10일이 소요됩니다. 이를 5명이 나누어 진행한다면, 2일의 시간만이 소요될 겁니다.

또한, 5명 각자 동등하게 200페이지씩, 검수를 진행한다면 git을 쓰지 않아도 아무 문제가 없습니다. 다만 문서를 동등하게 분배하는 과정과 분배된 문서를 다시 하나의 문서로 합치는 불편함이 발생하겠네요! 그리고 동등한 200페이지라고 말은 하였지만, 작업의 양이 모두에게 공평하게 돌아가지 않았을 것입니다. 대부분의 문서는 처음과 끝부분에 목차와 색인 등이 있어서 분량이 적을 수도 있으니까요.

이렇듯 누군가는 조금 더 빠른 시간에 작업을 끝낼 수도 있고, 그 사람은 모든 작업이 끝날 때까지는 하나의 문서로 합치는 작업 또한 진행하지 못할 겁니다. 그 사람은 시간을 허투루 소모하고 있는 것이죠. 그렇다고 중간에 다른 사람이 작업하던 것을 다시 쪼개서 일을 하자니 그 비용이 더 들지도 모릅니다. 이렇듯 문서(작업)의 분배와 병합, 그리고 다른 사람의 작업 진행 정도를 파악하는 것이 협업의 가장 큰 걸림돌이라면 이를 손쉽게 만들어 주는 것이 git의 역할입니다!

git은 분산 기능을 통해 5명 모두가 하나의 문서를 동시에 편집할 수 있게 지원하고, 각자의 작업 내용을 기록으로 남겨 모두가 공유할 수 있습니다. 더 멋진 점은 동시 편집 중에 동일한 내용을 서로가 다르게 수정하였다면, 이를 자동으로 감지하여 `누구의 것으로 최종 병합할 것인가?`와 같은 기능을 제공하여 보다 손쉽게 협업을 진행할 수 있습니다.

git 기초 개념

git이 파일을 관리하는 단위는 “폴더(디렉토리)” 입니다. 특정 폴더를 저장소(repository)로 지정하면, 해당 폴더에 저장되는 파일과 하위 폴더들이 git이 관리하는 대상이 됩니다. 앞서 말씀드린 발표자료 예시처럼 하나의 파일만 이력관리를 하는 것이 아니라 여러 파일과 폴더를 묶어서 이력을 관리할 수 있습니다.

자 그럼 이제부터 git이 파일을 어떻게 추적하고 관리하는지 알아보도록 하겠습니다. git은 파일을 untracked, tracked, unstaged, staged 네 가지 상태로 관리합니다.

특정 폴더를 저장소(repository)로 지정하고 나면, 그 시점부터 해당 폴더에 생성(외부로부터 복사/이동 포함)되는 모든 파일들은 untracked 상태로 관리됩니다. untracked는 git이 “해당 파일은 이력관리 대상에서 제외된 파일이다.” 라고 생각하는 상태입니다. 따라서 untracked 상태의 파일 중, 이력관리를 하고싶은 파일이 있다면 git의 특정 명령어를 통해 tracked 상태로 변경해주어야 합니다(쉽게 말해, git에게 ‘앞으로 이 파일은 내가 이력을 관리할 파일이니까 변화를 잘 감시하고 있어!’ 라고 요청하는 것입니다).

이후, tracked로 변경된 파일은 staged 또는 unstaged의 상태만을 갖게 됩니다. tracked 상태의 파일이 수정이 되면 git은 이를 자동으로 감지하여 unstaged 상태로 변경시킵니다. unstaged 상태는 git이 해당 파일을 이력관리 대상으로 포함하고 있으나, 이력저장(commit) 행위를 할때는 제외되는 상태입니다. 이력저장(commit) 행위를 할때 저장되는 파일은 오직 staged 상태의 파일만 저장되는 점을 기억하시기 바랍니다.

다시 한 번 요약하자면,

  • untracked: git이 이력관리대상에서 제외한 파일

  • tracked: git이 이력관리대상으로 포함한 파일이며 다음과 같은 상태를 가진다.

    • staged: 이력저장(commit)을 할때 저장되는 파일

    • unstaged: git이 관리대상으로 포함한 파일이나 staged 상태가 아니므로 이력저장(commit)을 할때 저장 대상에서 제외되는 파일


앞서, git이 파일을 관리하는 네 가지 상태에 대해서만 말씀을 드렸는데요, 좀 더 중요한 개념이 있습니다. 바로 이력저장(commit)이라는 행위인데요. 이후 나오는 이력저장(commit) 행위에 대해서는 커밋 또는 commit이라고 통칭하겠습니다.

커밋을 설명하기 앞서, 혹시 나비효과 라는 영화를 아시나요? 그 영화에서 주인공은 자신이 쓴 일기를 통해 과거로 돌아갈 수 있습니다. 여기서 일기를 쓰는 행위가 바로 커밋입니다. git에서 커밋이란 그 당시 저장소의 폴더 및 파일 내용을 그대로 저장해 두는 행위이며, 당시 상황을 기억하기 위해 메모를 함께 기술합니다. 예를 들면 “A라는 파일에 B라는 내용을 추가했음”과 같이요. 그리고 나비효과 영화의 주인공 처럼 과거의 일기(커밋)를 보고 과거로 돌아갈 수 있습니다. 따라서 우리는 이러한 커밋을 통해 과거 시점으로 돌아가 삭제된 파일을 복구하거나, 과거로 부터 파일의 내용이 어떻게 변화되어 왔는지 추적 및 관리할 수 있습니다.

git 설치

그럼 이제부터 git을 본격적으로 사용하기 위해서 git을 설치해보도록 하겠습니다. git은 윈도우, 리눅스, 맥 등 대부분의 OS에서 설치하여 사용할 수 있게 개발되었지만, 이 글에서는 윈도우를 기준으로 설명 드리도록 하겠습니다.

윈도우에서 git을 사용하기 위한 다양한 프로그램이 존재합니다. 그 중 대표적인 것이 Git for Windows 입니다. 저는 이 프로그램을 사용하여 git을 설치해 보도록 하겠습니다.

먼저, 해당 사이트를 방문 하시어 프로그램을 다운받아 주세요. 다운로드가 완료되면 셋업파일을 더블클릭하여 설치를 진행합니다.저는 디폴트 옵션(무조건 Next)으로 설치를 진행하였습니다. 설치가 완료되면, 바탕화면이나 폴더 내에서 마우스 우클릭을 해봅니다.

[그림 1] Git 메뉴가 추가된 컨텍스트 메뉴



[그림 1]과 같이 컨텍스트 메뉴에 “Git GUI Here”와 “Git Bash Here”가 보이면 설치가 정상적으로 완료된 것입니다.

git 사용법

git을 사용하는 방법에는 두 가지가 있습니다. 바로 GUI 프로그램을 이용하거나 git 명령어를 이용하면 됩니다.

둘 중, 저는 git 명령어를 통해 사용법을 설명드릴 것입니다. 그 이유는 git GUI 프로그램은 다양한 이름으로 개발되어 있으며, 어떤 프로그램을 설치 하느냐에 따라서 사용법이 조금씩 다를 수 있기 때문입니다. 그리고 이런 GUI 프로그램들 또한 명령어를 기반으로 동작하기 때문에, git 명령어를 숙달하신다면 어떤 환경에서든 동일한 방법으로 git을 사용하실 수 있을 것입니다.

 

자, 그럼 지금부터 명령어를 통해 git의 사용법을 알아보도록 하겠습니다.

1. 저장소 생성

git을 사용하기 위해서 가장 먼저 선행되어야 하는 일은 저장소 생성하기 입니다.

git은 폴더(디렉토리) 단위로 저장소를 생성할 수 있습니다.

그럼, 지금부터 실습을 위해 애국가라는 저장소를 생성해보도록 하겠습니다.

첫번째로 내가 원하는 경로에 “애국가” 라는 폴더를 생성합니다.

그 다음, 해당 폴더를 마우스로 우클릭을 한 뒤, 표시되는 컨텍스트 메뉴에서 “Git Bash Here” 를 선택합니다.

[그림 2] 애국가 폴더로 이동 후, 마우스 우클릭 -> Git Bash Here



[그림 3] Git Bash Here CLI 명령어 창



마지막으로 [그림3]과 같은 CLI 창이 생성되었으면, 아래의 명령어를 입력합니다.

git init

“Initialized empty Git repository in …” 과 같은 출력이 나오면 정상적으로 저장소가 생성된 것입니다. 윈도우 탐색기로 해당 폴더를 보면, 숨김폴더로 .git이라는 폴더가 생성되어 있는 것을 확인하실 수 있습니다.

[그림4] git 저장소가 생성된 애국가 폴더

2. 파일의 생성

생성된 저장소에는 일반 폴더와 마찬가지로 파일을 생성, 수정, 삭제할 수 있습니다.

하지만 일반 폴더와 저장소의 차이점은 무엇일까요?

바로 저장소내에 생성된 파일은 git이 관리해준다는 점입니다.

저장소에 파일이 처음 생성되었을 경우, git은 해당 파일을 untracked 상태로 관리합니다.

정말 그런지 확인해 볼까요? 그럼 애국가 저장소내에 “애국가1절.txt” 이라는 텍스트 파일을 생성해 보도록 하겠습니다.

[그림 5] 애국가 저장소에 생성된 애국가1절.txt 파일 



파일이 생성되었다면 아래의 명령어로 파일의 상태를 조회할 수 있습니다.

git status

[그림 6] git status 명령어로 확인해본 애국가1절.txt


예상대로 untracked 상태로 나오네요. 그럼 “애국가1절.txt” 파일을 git의 버전관리 대상(tracked 상태)으로 만들어 보겠습니다.

파일의 상태를 tracked 상태로 변경하고 싶다면, 아래의 명령어를 사용하면 됩니다.

git add [untracked 상태의 파일명]

[그림 7] git add 명령어를 통한 파일 상태 변경


add 명령어를 통해 파일의 상태를 변경하였다면 status 명령어로 파일의 상태를 다시한번 확인해보시기 바랍니다. 아마도 [그림 7]과 같이 “애국가1절.txt” 파일이 초록색(tracked 상태)으로 변경되었을 겁니다.

3. 파일의 수정

이제 “애국가1절.txt”는 git의 이력관리 대상이 되었습니다. 그럼 이 상태에서 파일을 수정하면 어떻게 될까요? 현재는 아무 내용도 없는 “애국가1절.txt”파일에 애국가 1절 가사를 입력한 뒤 저장해 보겠습니다.

[그림 8] 애국가1절 추가 및 저장


status 명령어를 통해 상태를 살펴보니 unstaged 상태로 변경되었네요.

[그림 9] 파일 내용이 변경되어 unstaged 상태가 된 애국가1절.txt

4. 일기를 쓰자: 커밋

tracked 상태의 파일은 수정이 되면 git이 자동으로 감지하여 unstaged 상태로 변경시킵니다.

따라서 해당 파일은 커밋 대상에서 제외가 됩니다.

수정된 파일을 다시 커밋 대상으로 포함시키기 위해서는 앞서 untracked 파일을 tracked 파일로 변경시킬 때 사용하였던 add 명령어를 다시 사용하면 됩니다.

git add [unstaged 상태의 파일명]

[그림 10] git add 명령어를 통하여 다시 staged 상태로 된 애국가1절.txt

지금까지 애국가를 1절을 작성하는 고된 작업이 끝나고나니 이 상태를 보관하고 싶어졌습니다.

앞서 나비효과 영화로 예로 들었던, 지금 이 순간을 일기로 남겨서 나중에 과거로 시간여행을 할 수 있게 말이죠!

커밋은 git이 현재 추적(tracked)하고 있는 파일중 staged 상태의 파일만 골라서 일기로 남기는 행위입니다.

자! 그럼 아래의 명령어를 통해 일기를 남겨 보시죠~

git commit -m ‘오늘의 일기~ 날씨 맑음

애국가 1절 작성 했음, 매우 힘들었음.’

커밋을 할때는 -m 옵션을 반드시 명시 하셔야 됩니다. 해당 옵션은 일기 내용이라고 생각하시면 되는데요. 일주일전 내가 뭘했는지 기억하실 수 있나요? 네, 저같은 평범한 사람들은 엊그제 먹은 점심도 기억 안 나기 마련이니까 과거를 되짚어 보기 위해서는 -m 옵션으로 로그를 반드시 기록해주셔야 합니다. 꼼꼼하고 자세하게 기록할 수록 기억이 좀더 명확해지겠죠?

이렇게 commit 명령으로 저장된 현재 상태는 커밋아이디가 부여되고 이를 통해 다른 커밋과 구분할 수 있는데요. 아래의 명령어를 통해 확인하실 수 있습니다.

git log

[그림 11] git log 명령어로 커밋메세지와 commit id 확인


커밋아이디는 git이 중복되지 않게 생성 및 부여하므로 여러분은 신경 쓸 필요가 없습니다. 그리고 이 커밋아이디를 통해 우리는 과거로 돌아가는 마법을 부릴 수 있습니다.

5. 마법의 주문: 체크아웃

앞서 “애국가1절.txt” 문서를 생성하고 커밋을 했죠? 만약에 제가 전날 과음을 하여 실수로 어렵게 작성한 “애국가1절.txt”를 삭제하고 말았습니다. 그럼 다시 “애국가1절.txt”를 새로 작성해야 할까요? 아닙니다. 우리에게는 git이 있으니까요!

일단, 실험을 위해 저장소내의 “애국가1절.txt”를 삭제해 보도록 하겠습니다.

[그림 12] 사라진 애국가1절.txt


“애국가1절.txt” 파일이 사라지면 git은 어떻게 판단할까요? status 명령어로 확인해보겠습니다.

[그림 13] git status로 확인된 deleted 상태의 애국가1절.txt


[그림 13]과 같이 “애국가1절.txt”가 지워졌다고 하네요.

이 상태에서 “git add 애국가1절.txt” 명령어를 수행하고, commit을 하면 “애국가1절.txt” 파일이  사라진 상태를 커밋으로 남기게 됩니다.

해볼까요? “애국가1절.txt”가 사라진 시점을 커밋해 보도록 하겠습니다.

[그림 14] git add & commit 명령어를 통해 애국가1절.txt가 사라진 시점을 커밋


만약 앞으로도 “애국가1절.txt”가 필요없다고 하면 이상태를 유지하면서 작업하면 되겠죠? 하지만 실수로 인해 “애국가1절.txt”이 사라졌다고 가정하였으니 이를 복원해 보도록 하겠습니다.

“애국가1절.txt”를 복원하려면 과거로 돌아가야겠죠?

과거로 돌아가기 위해서 필요한 것은 checkout 명령어와 가고싶은 시점의 커밋아이디 입니다.

git checkout [커밋아이디]

돌아가고 싶은 커밋 시점을 알기 위해서 git log 명령어를 통해 커밋아이디를 확인해보도록 하겠습니다.

[그림 15] git log 명령어로 조회해본 커밋 기록들


git log 명령어로 조회해본 결과 저희는 두건의 커밋 기록이 있네요.

“애국가1절.txt” 문서가 삭제된 커밋과 1절을 위키피디아에서 작성하여 저장한 시점의 커밋이 있습니다. 제가 돌아가고 싶은 시점은 문서가 생성되고 저장된, 커밋아이디 ebf484...가 되겠네요.

git checkout [커밋아이디] 명령어를 쓰실 때, 꼭 커밋아이디 전체를 입력하지 않아도 됩니다.

앞부분의 몇자리만 입력하여도 겹치는 아이디가 없으면 git이 알아서 판단하여 해당 시점으로 파일 상태를 되돌립니다.

[그림 16] git checkout 명령어로 커밋 시점 되돌리기


git의 커밋 시점이 변경되었습니다. 그럼 윈도우 탐색기로 해당 폴더를 다시 볼까요?

[그림 17] git checkout 명령어를 통해 과거 커밋 시점으로 돌아가 파일이 원복된 모습



checkout 명령어를 통해 과거 커밋 시점으로 되돌아가니 파일이 그대로 존재합니다!

하지만 이것은 임시로 과거 시점으로 돌아가 “애국가1절.txt”가 복원된 것이지 현재 작업하고 있는 시점으로 되돌아간다면 다시 사라지게 될 것입니다. 따라서 과거 시점으로 돌아가 되살리고 싶은 파일을 확인하였다면, 다음과 같은 명령어로 과거 커밋시점의 파일을 현재 작업 시점으로 되살릴 수 있습니다.

git checkout [커밋아이디] [파일명]

위 명령어로 파일을 복원하기 앞서, 우리는 과거 커밋시점인 ebf484...에 있습니다.


그렇다면 과거 커밋으로 돌아가기 전인, 마지막 작업 시점으로 돌아가려면 어떻게 해야 할까요? 이때는 다음과 같은 명령어로 현재로 돌아갈 수 있습니다.

git checkout master

여기서 master는 git의 커밋아이디를 뜻하는 것은 아니고, 브랜치라는 개념인데요. 이 부분까지 설명드리자면 글의 분량이 너무너무 길어지기 때문에 다음에 자세히 다루도록 하겠습니다. 그냥 마지막으로 ‘작업하던 시점으로 돌아갈때는 git checkout master를 사용한다!’ 라고 기억해 두시기 바랍니다.

[그림 18] git checkout master 명령을 통해 마지막 작업 시점으로 복귀


마지막 작업 시점으로 돌아오고나니 받아들이고 싶지 않은 현실이 있습니다. “애국가1절.txt”가 다시 사라져 있습니다. 그렇다고 당황하지 마시고, 위에서 설명드린 git checkout <과거commit id> <복원하고픈 파일명> 으로 파일을 되살려 보겠습니다.

[그림 19] checkout <과거commit id> <복원하고픈 파일명> 명령어로 되살린 파일


위의 명령어를 수행하고 나니 “애국가1절.txt”가 복원되었습니다! git status 명령어로 파일 상태를 확인하니 unstaged네요. 그렇다면 git add 명령어로 파일을 staged 상태로 만든 뒤, 커밋한다면 지금 상태 또한 새로운  커밋으로 저장할 수 있겠습니다!

이렇듯, git은 파일의 백업 및 복구 뿐만아니라 과거 이력을 조회하고 재사용하는 등, 다양하게  활용될 수 있습니다.

마무리

지금까지 git에 대한 가장 기초적인 명령어와 개념에 대해 설명드렸는데요, 사실 git을 제대로 활용하려면 꽤 많이 공부해야 합니다. 이번 글에서 설명드린 git의 기능은 정말 빙산의 일각에 불과한 데요. 그만큼 제대로 공부하면 무궁무진하게 활용 가능한 것이 git입니다!

초기 진입장벽이 높아 초보자 분들께서는 사용할 엄두를 못내고 계신 분들도 많은데요. 이 글을 통해 조금이나마 장벽이 낮춰졌으면 하고, 조금 더 나아가 git에 대해서 호기심을 가지고 공부를 시작하셨으면 좋겠습니다!

1. 형상관리에 대해

 오늘은 소프트웨어 개발에서 기본이 되는 형상관리에 대해서 알려 드리겠습니다. 형상관리(CM : configuration management)라고 들어보셨나요? 소프트웨어 공학을 배우신 분들에게는 익숙하겠지만, 그렇지 않으신 분들에게는 매우 생소한 단어라 생각 됩니다. 이미 배우신 분들은 형상관리가 범위도 다양하고 복잡하다는 걸 알고 있을 텐데, 오늘은 그 중에 개발자들에게 익숙한 소프트웨어 형상관리, 다른 말로 하면 소스 버전 관리에 대해 알아 보도록 하겠습니다.


 소프트웨어 형상관리는 Software Configuration Management, 줄여서 SCM라는 단어를 쓰기도 하는데, SW개발 및 유지보수 과정에서 발생하는 소스코드, 문서, 인터페이스 등 각종 결과물에 대해 형상을 만들고, 이들 형상에 대한 변경을 체계적으로 관리, 제어하기 위한 활동입니다. 단순히 말하자면 프로젝트를 진행하면서 생성하는 소스코드를 CVS나 SVN, 또는 GIT와 같은 버전 관리 시스템을 이용하는 것을 말합니다.


 다수의 개발자가 프로젝트에서 동일한 기능을 동시에 개발한다고 할 때, 작성된 소스 코드와 변경사항을 확인하고, 수정하는 협업을 도와주는 시스템이라고 할 수 있습니다.


 참고로 공급망 관리를 지칭하는 Supply Chain Management(SCM)과 동일한 약어를 사용하니, 누가 SCM에 대해 물어본다면, 어떤 SCM을 말하는 것인지 확인을 하고 대답해 주세요. ^^


 그럼 오늘은 소프트웨어 형상관리에서 버전 관리 시스템을 왜 사용해야 하는지, 어떤 개념들이 있는지, 그리고 어떠한 시스템들이 있는지 알아보도록 하겠습니다.




2. 왜 버전 관리 시스템이 필요한가?

 프로그램을 만들다 보면, 잘못 만들어서 다시 소스코드를 이전 상태로 되돌릴 필요도 있고, 변경된 이력을 확인할 필요가 있습니다. 그리고 여러 명의 개발자들이 동시에 같은 소스코드를 개발하면서 발생하는 충돌에 대한 처리도 필요합니다. 이러한 것을 하기 위해 무엇이 필요할까요? 바로 버전 관리 시스템입니다.


 과거와 달리 현재의 소프트웨어는 더 복잡해지고, 더 쉽게 변경됩니다. 만약 소프트웨어 버전관리 시스템을 사용하지 않는다면, 다른 개발자가 무엇을 했는지 알 길이 없으며, 실수를 쉽게 되돌릴 수도 없습니다.


 버전 관리 시스템이 없던 과거에는, 다음과 같이 누구 책임인지 싸우느라 시간을 허비 했을지도 모릅니다.


 버전 관리가 필요한 이유를 정리하면 다음과 같습니다.


개발 하는 동안 소스 코드의 변경 사항을 보존하기 위해

버그 및 문제점이 발생했을 때 추적에 유용

과거 특정 시점의 소스 파일 및 디렉토리의 내용을 손쉽게 확인 가능

과거 특정 시점의 소스 파일로 손쉽게 되돌릴 수 있음


협동 작업을 가능하게 하기 위해

대부분의 프로젝트는 팀 단위이기 때문에 전체 팀원이 하나의 소스를 가지고 효율적으로 작업할 수 있는 도구가 필요함

인터넷을 이용한 전세계 개발자들이 협업을 하여 개발하는 오픈 소스 프로젝트에 필수

 


3. 버전 관리 시스템의 기본 개념

문제 #1: 협업하기


 두 명 이상의 사람들이 똑같은 소스코드를 같은 시간에 편집해야 한다면 어떻게 해야 할까요?


대안 1


누가 수정을 할지 순서를 정한다.


한 번에 한 사람만 작업을 할 수 있다.


규칙을 어떻게 지킬 수 있도록 할 수 있을까?


대안 2


작업을 각자 한 후 차이점을 찾아 수정한다.


차이점을 찾고 수정하기 위해 수많은 재 작업이 필요하다.


재 작업 시 소스코드가 손실 될 수 있다.


 


해결책


 버전 관리 시스템은 개발자들이 동일한 소스 코드를 동시에 수정하거나 수정된 내용을 쉽게 공유할 수 있는 기능을 제공합니다.


중앙 저장소(Repository)에 메인 소스 코드를 저장해 놓습니다.

여러 명의 개발자들은 각자 로컬 PC에 중앙 저장소에 저장되어 있는 소스 코드를 작업 디렉토리(Working Copy)에 사본을 복사해 소스 코드를 수정합니다.

개발자들이 소스 코드 수정을 끝낸 후, 소스 코드를 공유하기 위해서 중앙 저장소로 소스코드를 커밋(Commit) 합니다.

다른 개발자는 변경된 내용을 확인 하기 위해서 중앙 저장소의 소스를 작업 디렉토리로 갱신(Update) 되도록 명령을 수행합니다.



문제 #2: 수정 사항 되돌리기


 간혹 수정하던 소스 코드를 다음과 같은 이유로 이전 상태로 돌아갈 필요가 생깁니다.


개발을 시작한 후 시간이 지나, 잘못된 구현을 하고 있다는 것을 알게 되었을 때

이전 상태로 되돌리면서 모든 파일에 대한 변경 이력(History)를 유지하고 싶을 때

소스 코드가 언제, 무엇을, 그리고 누가 수정했는지 알고 싶을 때

->누군가 작성한 소스 코드를 이해하는 가장 좋은 방법은 작성한 사람에게 물어보는 것입니다.

 


해결책


 버전 관리 시스템은 개발자들이 수정한 소스 코드에 대한 리비전(Revision)을 관리합니다. 리비전은 수정 시간, 수정한 사람, 수정한 내용들을 포함하고 있어, 개발자들에게 편리한 정보를 제공하고 있습니다.


 또한 되돌리기(Roll back) 기능이 있어 특정 리비전 또는 특정 시간으로 소스코드를 되돌릴 수 있습니다.



위 두 가지 문제를 보면서 버전 관리 시스템의 기본적인 개념을 설명 드렸습니다. 그리고 위에서 나온 용어들을 정리하면 다음과 같습니다.


용어


설명


중앙 저장소(Repository)


원본 소스를 저장하고 있는 저장소를 의미합니다.


작업 디렉토리(Working Copy)


원본 저장소로부터 체크아웃을 통해 내려 받은 내 로컬 PC에 있는 작업 사본 디렉토리를 의미합니다.


커밋(Commit)


작업 디렉토리에서 변경, 추가 및 삭제된 파일을 원본 저장소인 서버에 적용하는 것을 말합니다.


갱신(Update)


체크아웃을 받은 작업 디렉토리를 원본 저장소의 가장 최신 커밋된 버전까지 업데이트하는 명령어입니다.


리비전(Revision)


소스 파일을 수정하여 커밋하게 되면 일정한 규칙에 의해 숫자가 증가합니다. 저장소에 저장된 각각의 파일 버전이라 할 수 있습니다.


되돌리기(Roll Back)


작업 디렉토리에 저장되어 있는 사본을 특정 리비전 또는 특정 시간으로 복원할 수 있도록 하는 명령어입니다.



 위 용어들은 다양한 버전 관리 시스템에서 다양한 용어로 대체되어 사용됩니다. 예를 들면 작업 디렉토리(working Copy)는 작업 공간(Workspace)라는 단어로, 커밋(Commit)은 체크인(Check-In)이라는 단어가 사용되기도 하니 버전 관리 시스템을 사용하기 전에 어떤 단어가 위의 기능들과 매핑 되는지 확인해야 합니다.




4. 버전 관리 시스템의 종류

 버전 관리 시스템은 상용과 비상용(오픈소스)로 구분 할 수 있습니다.


상용

IBM Rational ClearCase

Perforce

PTC Integrity

비상용(오픈소스)

Subversion(SVN)

CVS

Git

 위에 나열한 시스템 외에도 수많은 버전 관리 시스템이 있습니다. 버전 관리라는 동일한 목표를 가지고 있지만, 각각의 시스템들은 특색을 가지고 있어, 그 특색에 따라 툴을 사용하는 방법들이 상이합니다. 그리고 상용 프로그램들은 가격이 정말 비쌉니다. 프로그램 라이선스가 1년에 1명 사용하는데 수백만원을 넘기니 말이죠. 그리고 최근 오픈 소스 프로젝트의 대부분은 Git를 사용하고 있습니다. 참고로 예전에는 SVN을 주로 사용했습니다. 여러분이 오픈 소스에 관심 있으시면 Git-Hub(http://git-hub.com/) 사이트를 둘러 보시면 도움이 될 것 입니다.




5. 글을 마치며

 버전 관리 시스템은 아마추어 개발자와 전문 개발자를 구분하는 것 중에 하나라고 합니다. 프로젝트를 혼자서 하는 경우도 있고, 몇 명이 나누어서 진행하는 경우도 있습니다. 늘 일정에 쫓기다 보니 '바빠 죽겠는데 버전 관리까지 어떻게 해?'라고 생각하시는 분들도 있을 것입니다. 하지만 일주일 동안 온 힘을 다한 소스 코드를 실수로 날려 버린 경험을 가지신 분들은 버전 관리 및 소스 코드 백업의 필요성을 느끼실 것 입니다.




 소스 코드 버전 관리는 정말 유용합니다. 처음 익숙해 질 때 어려움은 있지만, 시간이 조금 더 지나면 버전 관리에 대한 보상을 금방 얻으실 수 있습니다. 요즘 사람들이 많이 쓰는 Git로 버전 관리를 시작해 보시겠어요?




출처: http://bsnippet.tistory.com/57 [snippet]

+ Recent posts