git rebase: 브랜치 이력을 확인하면서 병합합니다.


이전 블로그 포스팅에서 살펴본 병합과정은 사실 자주 실행하는 작업이 아닙니다. 실제git을 이용한 버전 고나리시스템의 작업흐름은 평소에는 여러개의 branch와 commit 내역을 만들고, 마지막에 작업내역을 확인하고 올바른 작업물만 병합하는 것입니다. 

 git의 특징 중 하나는 commit내역을 수정할수 있다는 것입니다. 하지만 수정할 수 있다고해서 이미 원격 저장소에 push가 끝난 commit내역을 수정하는 것은 특별한 상황이 아닌 이상 절대로 권장할만한 일이 아닙니다.


 push 하기전에 git merge명령을 이용해서 병합하면, 충돌해결 커밋이나, --no-ff로 만든 병합 commit을 남기게 됩니다 .이는 작업 흐름을 일관되게 파악하는데 깔끔하지 않습니다. 따라서 할 수 있다면 로컬 저장소에 있던 commit을 깔끔하게 정리해서 push하는것이 좋습니다.


 그런 정리를 할 수 있는것이바로 git rebase입니다. 여기서는 언제 git rebase를 사용하는것을 고려해야하는지, 그리고 commit내역을 깔끔하게 정리함으로써 얻을 수 있는 장점을 예와함께 살펴보도록 하겠습니다.



아래 그래프는 일반적으로 병합했을때의 모습입니다. 이전 블로그에서 작업했던 저장소의 모습과도 같습니다.


<일반적 작업 흐름의 그래프>




하지만 두개를 넘어서 세개 이상의 브랜치가 master 브랜치에 병합된다고 생각해보겠습니다. myBranch1을 만든 이후 master 브랜치에 어떤 commit내역이 생신 상태로 myBranch2, myBranch3를 만들어서 각각 commit을 했고, myBranch1에도 다른 commit 내역이 있는 상황입니다. 이를 차례대로 master 브랜치에 병합한다고 가정해봅시다.

<세개 이상의 브랜치 병합 시>

.


그럼 이것들을 합쳐야겠지요? 먼저 myBranch1을 master 브랜치와 병합니다.그리고 myBranch2를 maser와 병합합니다. commit 그래프가 꼬이기 시작합니다. 마지막으로 myBranch3을 병합합니다. 아래는 최종형태입니다.


프로젝트 멤버가 세명 이상이면 혹은 동시에 개발중이 기능이 여러개라면 branch가 세개 이상으로 생성되는 일은 매우 흔한 상황입니다. 그럴때마다 각자의 코드를 master브랜치에 반영하면 commit 내역 그래프가 매우 알아보기 어려울 것입니다. 실제로 작업한 내역을 git log --graph 명령을 실행하면, 계속 충돌을 해결해야하는 모습을 볼 수 있습니다. 하지만 git rebase 명령을 사용하면 이를 깔끔하게 정리할 수 있습니다.


실습을 위해 다음과 같이 구성해보도록 하겠습니다. myRebase라는 디렉토리를 만들고 다음과 같이 master와 myBranch123 브랜치들과 커밋내역을 만들도록 합시다.



branch             file               code               message

master         hello.py    print("Hello World")      Hello world

                                print("Hello World2")    Hello world2


myBranch1  hello.py     print("hello World")     Tell your World

                               print("Tell your world")  


myBranch2  hello.py    print("Hello World")     Tell His world

                              print("Hello World2")

  print("Tell His world")


myBranch3  hello.py   print("Hello World")     Tell Her world

                              print("Hello World2")

                             print("Tell Herworld")



$mkdir myRebase

$cd myRebase

$git init


$vim hello.py, 파일내용 추가합니다. print("Hello World")

$git add hello.py

$git commit -a -m "Hello world"


myBranch1을 땁니다.


 git branch myBranch1

$ vim hello.py      Tell your World

$ git add hello.py

$ git commit -a "Tell your World"


다시 master 브랜치로와서 hello world2 print 문 추가해주고 commit해줍시다.

$git commit -a -m "Hello world2"


자 다시 마스터 브랜치에서 브랜치를 땁니다. 2개를 만들어야하네요.

 git branch myBranch2

 git branch myBranch3

그리고 각각 브랜치를 이동하면서 Tell his world, tell her world를 hello.py에 추가하고 commit에도 같이 수정해줍시다.



이런 모양이 되겠지요?


먼저 myBranch1 브랜치부터 정리해보도록 하겠습니다.  master Branch앞으로 myBranch1 브랜치를 이동시키는 짓을 하려고합니다. 따라서 git checout myBranch1 명령을 쳐서, myBranch1으로 브랜치 이동을 합시다. 그리고 git rebase master 명령을 실행해봅니다.


당연히 충돌이 납니다. 이름도 REBASE가 붙은것으로 바뀐것을 확인하실 수 있으십니다.


rebase명령은 아래와 같이 세가지 옵션을 제공합니다.


git rebase --continue: 충돌 상태를 해결한 후 계속 작업을 진행할 수 있도록 해줍니다.

git rebase --skip: 병합 대상 브랜치의 내용으로 강제 병합을 실행합니다. 여기서 명령을 실행하면 master 브랜치를 강제로 병합한 상태가 됩니다. 또한 해당 브랜치에서는 다시 git rebase명령을 실행할 수 없게 됩니다. 

git rebase --abort: git rebase명령을 취소합니다. 다시 git rebase myBranch1명령을 실행할 수 있게 됩니다.


어쨌든 현재 브랜치는 다음과 같이 (myBranch1|REBASE 1/1) 의 상태임을 알 수 있습니다.

PJH@PJH-PC MINGW64 /d/blog/git/myRebase (myBranch1|REBASE 1/1)


그럼 충돌을 해결해보도록 하겠습니다. vim hello.py을 실행해서 충돌내용을 수정합니다. 그리고 git add hello.py 실행합니다. 또한, 마지막으로 아래와 같이 충돌 상태를 해결하는 rebase명령을 내립시다.


$ git rebase --continue


명령을 실행하면 master branch의 공통 부모까지의 myBranch1 Branch commit을 master branch의 뒤에 차례대로 적용합니다. 다음 아래의 그림과 같이 전체 작업 흐름의 위치가 이동한다고 생각해보시면 됩니다. myBranch1 rebase into master라는 것입니다. 현재 myBranch1을 master로 다시 설정하게 된다는 의미로 파악하시면 되겠습니다.

즉 첫번째 git rebase명령을 실행했을때 작업흐름은 다음과 같습니다.

여기까지면 단순하게 myBranch1과 master 브랜치가 따로따로 있는 것에 불과하게 됩니다. master 브랜치는 파랑, myBranch1은 노랑으로 따로따로 있게 된 상태이죠. myBranch1의 base(기반, 밑부분)을 다시 re, 재설정한것과 같은 효과입니다. 병합해야만 비로소 master 브랜치에 myBranch1 브랜치가 반영이 되는것입니다. 지금 master브랜치에는 myBranch1에 반영했던 hello.py 내역이 없습니다. 정말 merge된건 아니라는 말인거죠. myBranch1이 master 브랜치에 rebase만 된것입니다.

 git rebase 명령을 실행하면 무조건 fast-forward가 가능하지만, 이런 경우 병합 commit을 남기는것도 좋습니다. git merge myBranch1 --no-ff라는 명령을 실행해 fast-forward를 하지말라는 옵션을 주어서(사실 no fast-forward는 일반적인 병합시에도 매우 좋습니다. 병합한 흔적을 명시적으로 commit 그래프에 남기는 셈이니깐요.)병합을 실행하면 다음 아래과 같은 그래프가 됩니다.



git merge 명령을 실행했을 때 작업 흐름은 아래와 같습니다.

따라서  아래와 같이 명령을 실행해 master 브랜치로 이동한 후, git merge myBranch1 --no-ff 명령을 실행해 최종 병합해줍니다.


$ git checkout master

$  git merge myBranch1 --no-ff


이제 cat hello.py 를 실행해보면 병합되어져서 master브랜치의 hello.py에 수정병합 내용이 반영된것까지 확인하실 수 있게됩니다.


이제 위의 그림과 같이 myBranch2, 3역시 병합을 해봅시다. 블로그에서 글올린 순서대로 진행하시면 어려움없이 하실 수 있을 것입니다.


그리고 마지막으로 commit graph를 살펴보겠습니다. 아래와 같이 명령을 실행합니다.

$ git log --graph

어느 시점에서 병합했는지 아래와 같이 알 수 있어서 깔끔하고 좋습니다.

아름답게 나오는것을 확인하실 수 있습니다.


git rebase - i: 커밋 내역 합하기 명령입니다.

 git rebase 명령에는 활용도가 높은 옵션 -i가 있답니다. i는 interactive의 약어입니다. 상호작용하면서 rebase할 commit을 선탁핼 수 있습니다. 지금부터 앞서 작업했던 최근 commit 내역 두개를 합쳐보겠습니다. 다음 아래와 같이 명령을 실행합니다.


$ git rebase -i HEAD~~


commit 메세지창이 뜨고, 어떤 접두어로 해야하는지 알려주는 창이 뜨는것을 확인하실 수 있습니다.


수정할때는 다음 원칙을 지켜야합니다.

- 남기는 commit 메시지 앞에는 접두어로 pick을 붙입니다.

- 없애는 commit 메세지앞에는 접두어로 fixup을 붙입니다.

- commit SHA-1 체크섬 값은 꼭 남겨두어야 합니다.

- 기존 commit 메시지를 새롭게 수정할 수는 없습니다.


아래와 같이 커밋 메세지를 수정했습니다.


$ pick SHA값 Tell his world      

$ fixup SHA값 tell her world


아래 그림을 보시면, Tell Her World"라는 commit 내역과 그 사이에 있었던 병합 commit 내역이 모두 Tell His World Commit에 포함된것을알 수 있습니다. 그리고 commit 샤값도 새롭게 바뀐것을 확인하실 수 있습니다. 정리하자면 여러개 commit 중에서 필요한 것을 고른 후에 새롭게 commit 하게 되는 것입니다. 그렇다고 파일내용이 바뀌고 그런게 전혀아닙니다. commit내역을 정리한것입니다. rebase한 내역들의 commit들을 보기좋게 바꾼거라 생각하시면 되겠습니다.


$ git log



$ git log --graph



앞서 git 명령어 블로그 포스팅에 이어서 시작하겠습니다.

이전 블로그 내용이 궁금하시면 다음 링크 (새창)선택하셔서 확인하시면 되겠습니다.



git revert: 공개된 commit의 변경 내역을 되돌립니다.

이미 공개된 commit 내역을 수정하는것은 매우 risk가 큽니다. 할 수는 있긴있으나 정말 웬만하면 하지마세요. 하지만 안전하게 변경내역을 되돌리는 방법이 있습니다. commit으로 발생한 변경 내역의 반대 commit을 하면됩니다. 다시말하자면, 추가했던 코드는 빼고, 지운 코드는 다시 추가하는 commit을 하는 것입니다. 이를 수행하는 명령어가 바로 git revert 입니다. 아래와 같이 사용합니다.


$ git revert 커밋SHA-1체크섬값


이 명령을 특정 지점의 commit SHA-1 체크섬 값을 입력하면 해당 지점까지 변경내역을 취소하게 됩니다. 먼저 가장 최근 commit 변경 내역을 되돌려 보겠습니다. 먼저 아래와 같이 명령을 칩니다.


$ git log -5


가장 최근것을 취소해보도록하게습니다. SHA값은 b92c이군요. 아래와 같이 명령 입력합니다.

$ git revert b92c

vim 창이 등장하면서 commit 메세지를 수정하게됩니다. 원래 '원래메세지' + revert가 추가된것을 확인하실 수 있습니다. 저는 그상태로 저장하고 끝냈습니다. 되돌리기가 완료되었습니다. 실제 파일 내용을 확인해보면 추가했던것이 사라진것을 확인하실 수 있어요.


그런데 정말 fact는 실제로 되돌리는것이아니라, 되돌리는 것같은 효과를 낸다는 것입니다. git revert를 실행한 시점부터, 대상 commit까지 변경내역을 거꾸로 적용하는 새로운 commit을 만드는 것입니다. 



 Com0 -> com1 -> com2 -> com3 -> com4 -> com5

com2, com3, com4를 지우고 싶어서 revert com2를 한경우 com5라는 commit이 생성되면서 com1로 되돌아 간것같은 효과가 납니다.


git commit -3을 하면, revert를 하기전의 commit 내역 역시 존재하는것을 확인하실 수 있습니다. 이미 공개된 commit 내역은 이런 안전한 방법으로 되돌려야 합니다.

.


git reset: 이전 작업 결과를 저장한 상태로 되돌립니다.


git reset 명령은 어떤 특정 commit을 사용하지않게 되어 다시 되돌릴떄 사용합니다. git revert명령이 이전 commit을 남겨두는 명령이었다면 git reset명령은 이전 commit을 남기지않고 새로운 commit을 남긴다는 차이가 있습니다. git reset명령은 현재 commit인 HEAD의 위치, 인덱스, 작업하는 저장소 디렉터리 등도 함께 되돌릴리를 선택하기 위한 모드를 지정할 수 있습니다. 아래의 표를 참고하시면 되겠습니다.


git reset 명령 모드

 모드

의미 

HEAD 위치 

인덱스 

저장소 디렉토리 

 hard

완전히 되돌립니다. 

변경 

변경 

변경 

mixed 

인덱스 상태를되돌림. 모드를 지정하지 않았을때의 기본값입니다. 

변경 

변경 

변경 안함 

soft 

커밋만 되돌립니다. 

변경 

변경 안함 

변경 안함 


인덱스는 실제 commit 전 변경 내역을 담는 준비 영역입니다. git add 명령을 실행했을 때 이영억으로 이동하게 됩니다. 저장소 디렉토리는 실제 파일이 담겨있는 작업영역을 의미한답니다.



git reset 명령 옵션

 ^ 혹은~

~ 은 커밋내역 하나를 의미합니다. 표시한 수 만큼 커밋을 되돌립니다. 하나면 최종 커밋내역일 것이고 두개면 최종 커밋내역과 바로 전 커밋 내역이 됩니다.

 ORIG_HAED

 git reset명령을 실행했을 때 지운 커밋 내역을 보관합니다. 해당 명령을 통해 git reset 명령으로 지운 커밋을 되돌릴 수 있습니다.

 

 


최근 commit의 세번째 commit까지, 그리고 commit만 되돌려보기 위해 soft모드를 사용하겠습니다. git log -5명령 실행해서 최근 다섯개의 commit내역을 확인합니다. 그리고 아래와 같이 명령을 실행합니다.


~은 커밋내역 하나를 의미한다고 했습니다.

$ git reset --soft HEAD~~~

명령을 수행하고 아무 결과가 나타나지않습니다. 하지만 git log -3 명령을 실행해보면 가장 최근 commit이 바뀐것도 확인하실 수 있습니다. 또한 cat hello.py명령을 실행해보면 실제로 파일 내용이 바뀐것이 아님을 알 수 있습니다.


아래와 같이 명령을 쳐서 reset으로 날린 commit을 다시 원래 상태로 되돌리겠습니다.


$ git reset --hard ORIG_HEAD

위와 같이 명령을 치시고 다시 git log -5를 하면 commit내역이 돌아온것을 확인하실 수 있습니다.


음 커밋은 reset되었는데 commit이랑 다르게 파일은 그대로 보관되는것을 확인하실 수 있었죠? 이제는 hard모드로 진행해보도록 하겠습니다.


$ git reset --hard HEAD~~~

현재 HEAD의 위치를 알려줍니다. 

$ cat hello.py

파일 내용이 바뀐것을 알 수 있습니다.

$ git log -3 

역시 커밋내역이 위와 동일하게 사라졌음을 알 수 있습니다. 커밋과 함께 파일내역 수정된것도 반영되어 되돌아갔음을 확인하실 수 있습니다.


자 다시 되돌립시다.

$ git reset --hard ORIG_HEAD


git checkout head -- filename : 특정파일을 최종 commit 시점으로 되돌립니다.

이번에는 파일 하나를 대상으로 변경 내역을 통째로 원래대로(변경직전의 최종커밋시점으로) 되돌릴떄 사용할 수 있는 유용한 명령을 보도록 하겠습니다.


$ git checkout HEAD -- 파일이름

위 명령을 실행하면 파일이름 파일의 내용이 최종 commit 시점으로 되돌아 가게됩니다 "--"는 포함하는 것이 좋습니다. git checkout 명령에 뒤따라 오는 것이 파일이라는 것을 확실하게 해주는 것이라는 표시입니다. 만약 --가 없다면, 파일 이름이 브랜치 이름과 같을 경우 해당 브랜치로 checkout하거나, 특정 commit 시점으로 저장소 전체가 되돌아 갈 수 있습니다.


아래서부터는 README.md 파일을 다루겠습니다. vim README.md 명령 실행하고 파일에 수정사항을 둡니다. git checkout HEAD TEST 라고 쓰겠습니다.

그리고 아래와 같이 실행합니다. 아래와 같이 명령을 실행하면 인덱스에 변경 내역을 저장하게 됩니다.

$ git add README.md

git status명령을 실행해보면 commit할 내역이 있다고 알려줍니다. 이제 아래와 같은 명열을 실행합니다. 음 아무런 표시가 안뜨는군요


$ git checkout HEAD -- README.md


자 아래와 같은 명령을 수행해서 확인해보겠습니다.

$ cat README.md

원래대로 돌아갔음을 확인하실 수 있습니다.

아래와 같이 명령을 치면 또한 commit할 내역이 없음을 확인할수있습니다.

$ git status


git checkout -- 파일이름 명령은 git add 파일이름 명령을 실행한 후 추가 수정사항이 있을때 [$ git add 파일이름] 명령을 실행한 상태로 되돌리는 명령입니다. HEAD가 빠져있음을 확인하세요~!


git reset역시 파일하나를 되돌릴 수 있는것처럼 설명되어있는데요. 하지만 다른점이있습니다. git reset명령은 hard모드가 아니라면 저장소 디렉터리의 파일 내용은 명령을 실행한 시점 그대로 남습니다. git reset명령으로 되돌린다음 필요한 부분만 수정작업하고 다시 commit할 수 있습니다. 하지만 git checkout은 파일을 완전하게 대상 commit 시점으로 되돌립니다. 파일 내용이 대상 commit시점으로 완전하게 되돌아 가는것입니다. 즉 git reset명령의 hard모드를 실행한것처럼 index와 작업전부를 되돌리게 됩니다. 




Git을 사용할때 알아두면 유용한 명령어들이 있습니다. 아래와 같이 정리하였습니다. 참고해주세요.


git tag, 커밋을 참조하기 쉽도록 알기쉬운 이름을 붙입니다.

git commit --amend 같은 브랜치 상에 있는 최종 커밋을 취소하고 새로운 내요을 추가하거나 설명을 덧붙인 커밋을 할 수 있습니다.

git revert  이전에 작성한 commit을 삭제합니다. 그런데 특정 commit의 내용을 지우는 새로운 commit을 만들어 지운내역을 모든 사람이 알 수 있게 합니다.

git reset 어떤 commit을 버리고 이전의 특정버전으로 다시 되돌릴때 사용합니다. git revert와 다른점은 지운 커밋내역을 남기지 않는다는 점입니다. 

git checkout HEAD --filename 아직 commit하지 않은 변경 내역을 취소합니다. 

git rebase  git merge처럼 병합할때 사용합니다. 하지만 branch가 많을 경우 branch 이력을 확인하면서 병합합니다.

git rebase -i  서로다른 두 개의 commit 내역을 합칩니다.



git tag: 특정 commit을 참조하는 이름 붙이기

git tag 명령은 저장소의 commit에 tag를 붙이는 명령입니다. 


가장 최근commit에 tag를 붙이고 싶다면 간단하게 다음 명령을 실행하면됩니다.

$ git tag 태그이름


저는 1.0 버전이라는 태그를 붙이겠습니다.

$ git tag 1.0

그리고 로그와 함꼐 태그를 보겠습니다.


$ git log --decorate -1 


tag와 commit SHA-l 체크섬 값을 같이보려면 아래와 같이 칩니다.

$ git show-ref --tags 



특정 commit에 tag 붙이는 방법.

먼저 SHA-1 체크섬값을 알아야 합니다. 여기에서는 최근 커밋 바로 애라의 커밋에 태그를 붙이겠습니다.

아래와 같이 명령어를 실행합니다.


$ git log -2

이전의 commit의 SHA값 8591 앞자리를 기억합니다.


그 이후 아래와 같이 엔터칩니다.

$ git tag 0.9 8591

그이후 또 아래와 같이 명령을 실행합니다.

$ git show-ref --tags 

태그가 붙여진것을 확인하실 수 있습니다.


git tag 명령으로는 'light weight' tag만을 생성하게 됩니다. 누가, 언제 붙였는지 젼혀 알 수 없습니다.

tag 그자체에 대한 기록은 이름외에 아무것도 없는 상태입니다.


하지만 "annotated"태그는 누가 언제 태그를 붙였는지 기록하고, 추가 메세지 까지 저장합니다.

로그를 살펴보면서 태그들을 보다가 해당 태그 시점에 태그에 대한 의문이 생기면 누구에게 질문해야하는지 한번에 알수있게 됩니다.

또한, 커밋과 다른 시점에 붙은 버전 태그가 있다면, 언제 해당버전이 배포되었는지 알수있기도 합니다.


이번에는 annotated 태그를 붙여보겠습니다.


$ git log -3

3번째전거의 SHA 앞자리를 확인합니다. 

그 이후 아래와 같이 명령을 치고 엔터를 칩니다.


$ git tag -a 0.8 68eb


이렇게 명령을 실행하면 vi 편집기가 싱행되는것을 확인하실 수 있습니다. 기록할 메세지를 입력하고 저장하면 tag 붙이이기가 완료되게 됩니다.


$git show 태그이름


git show 태그이름 명령을 실행해 확인하면, 아까와는 달리 누가 언제 어떤 메시지를 입력해 태그를 붙였는지 확인하실 수 있습니다.


$ git show 0.8


git commit --amend: 마지막 commit 수정하기


마지막 commit message를 수정하는 명령은 간단합니다.

$ git commit --amend

위의 명령을 실행하면 마지막 commit과 commit하지 않는 상태에 있는 변경내역이 서로 합쳐진 새커밋을  만들게 됩니다. 만약 아무런 변경내역을 만들지 않고 명령어를 실행하면 커밋 메시지만 변경하게 되는것과 같은 효과를 낼 수 있습니다.


한번 일부러 hello.py 파일을 변경해보겠습니다. (vi 편집기창을 열어서 it's git commit --amend 라고 변경사항늘 만들어 놓겠습니다.)


변경 내역을 추가하기위해서 아래와 같이 명령을 실행합니다.

$git commit --amend


다시 commit 메시지를 입력하는 편집기가 등장합니다. 변경 내역이 있었으므로, 기존 commit message였던

conflict resolved github뒤에 by jinss 라는 커밋메시지를 추가한후 저장하겠습니다.


저는 이상태에서(변경내역이 없는상태)에서 commit message만 바꿔보겠습니다.

$git commit --amend 명령을 다시 실행합니다.

그리고 뒤에 by pjh를 붙였습니다.


그리고 아래와 같이 명령을 실행해봅니다.

$git log -1


좀더 설명드리자면, git commit --amend는 최종 commit을 수정하는 것이 아니라, 최종 commit을 대체하는 새로운 commit 을 만드는 것입니다.

명려을 실행하기전과 후의 commit의 sha값을 비교해보면 바껴있는것을 확인하실 수 있습니다. 또한 최종commit에서 추가되어 새로운 commit이 나오는게 아니라 마지막 commit에서 메세지값이 바껴진 새로운 commit이 대체되는것을 확인하실 수 있습니다. 물론 파일에서 변경사항이 있었다면, 그변경사항(파일)과 메세지까지 바뀐게 commit에 반영되어 SHA값이 새로 commit 되는거죠.


git log -5를 해봐도 마지막 commit을 계속 덧붙혀으나 위에는 최종 commit에서 덧붙혀진게 하나만 나오고 또한, 그전 마지막에있었던 commit의 SHA값이 달라짐을 확인하실 수 있습니다.


$ git log -5

여기서 git commit --amend를 쳐서 저장하고 다시 git log -5 를 쳐면 맨마지막 commit의 sha값이 변경됨을 확인하실 수 있습니다.


$ git commit --amend

$ git log -3




'개발 Support > GIT' 카테고리의 다른 글

git rebase, git rebase -i  (0) 2017.07.16
git revert, reset, checkout head -- filename  (0) 2017.07.15
원격저장소와 GIT  (0) 2017.07.15
원격저장소와 GitHub  (0) 2017.07.09
로컬 저장소 git 기본 및 실습  (1) 2017.07.09


들어가기 앞서.

 분산버전 롼리시스템은 다른사람과의 협업을 염두에두고 만들어진 툴입니다. 결국 원격저장소와 로컬 저장소 사이를 얼마나 효율적으로 관리하느냐가 관건입니다. Git에서는 원격저장소와 소통하기 위한 기능을 제공하고있습니다.



GIT 명령어를 알아봅시다.


git clone:   원격 저장소의 모든 내용을 로컬저장소에 복사합니다.

git remote: 로컬저장소를 특정 원격 저장소와 연결합니다.

git push:    로컬 저장소의 내용을 보내거나 로컬 저장소의 변경사항을 원격 저장소로 보냅니다.

git fetch:    로컬저장소와 원격 저장소의 변경사항이 다를때 이를 대조하고 git merge 명령어와 함께 최신 데이터를 반영하거나 충돌문제등을 해결합니다.

git pull:      git remote 명령을 통해 서로 연결된 원격저장소의 최신내용을 로컬 저장소로 가져오면서 병합합니다. gir push와 반대 성격의 명령입니다. 




Git Clone: 원격저장소의 내용을 로컬 저장소로 가져옵니다.


클론을 정의하자면 다음과 같습니다.

1. 내가 생성한 원격 저장소를 내컴퓨터와 연결해서 데이터를 복사하는 작업.

2. 포크한 원격 저장소를 내 컴퓨터와 연결해서 데이터를 복사하는 작업.


앞선 포스팅에서 만들었던 http 주소를 가져옵니다.


그리고 앞서 블로그에서 설치했던 GIT BASH를 실행 해주십다. 

$ mkdir git_remote

$ cd git_remote

그리고 clone 명령을 해서 땡겨옵니다.

$ git clone https://github.com/pjh2174/myTistoryExam.git


$ cd myTistoryExam

$ git status


status 명령을 치면, 현재 아무것도 커밋되어있지않고, clean한 디렉토리임을 알 수 있습니다.



Git remote: 로컬저장소와 원격저장소를 연결합니다.

앞부분에선 cloen을 통해 생성했던 원격저장소를 로컬저장소로 파일을 복사했습니다. 하지만 뭔가 모순된점이 있을 수 도 있는데요.

만약 유저가 이미 로컬에서 작업했던 내용이 있는 상태였다면, 원격저장소에있는걸 clone할필요없이 바로 연결해서 올려야하는 절차가 필요할 수도있습니니다. 그렇기때문에 일단 깃허브에서 원격 저장소를 임의로 생성해봅니다.

$ git remote add origin https://github.com/pjh2174/myRemoteExam.git

저는 이전블로그에 hello.py 가있는 브랜치로 접근하여 위의 명령어를 쳤습니다.

원격 저장소와 연결되었는지 호가인하려면 아래와 같이 명령을 치도록합니다.


$ git remote -v



git push: 로컬 작업 내역을 원격 저장소에 올립니다.


이제 원격저장소와 로컬 저장소가 연결되었습니다. 이젠 원격저장소에 자신의 결과물을 업로드 해야할 차례입니다. git push라는 명령어를 사용하면 수월하게 진행하실 수 있습니다.


$git push


음 거절당하게 될겁니다. 어느 원격 저장소로 발행할 것인지, 로컬의 어느 브랜치에 푸시할 것인지 명시하지 않았기 때문입니다.


$git push origin --all 


명령어를 자세히 분석해보겠습니다.

$ git push 원격저장소별칭 로컬브랜치이름 

위에서 실행한 -all은 origin 저장소에 로컬의 모든 브랜치를 푸시하는겁니다. git은 원격 저장소에 로컬 저장소의 브랜치와 같은 이름의 브랜치가 있다면 해당 브랜치를 변경하고 없다면 새브랜치를 원격 저장소에 만듭니다. 단 주의할점은, 같은 이름의 브랜치가 있는데 서로의 내역이 다르다면 푸시를 거부하게 됩니다. 


아무튼 명령을 수행하면 깃허브 로그인창이뜨게되고, 아이디와 비번을 입력합니다. 성공적으로 업로드가 수행되어집니다.

성공적으로 올라온것을 확인하실 수 있습니다.



원격저장소에 파일을 하나 추가한후 다시 내용을 푸시해보도록하겠습니다.


$ cat >> README.md

remote repository of myRemoteExam

$ git add README.md

$ git commit -m "remote repository add a README.md files"


자 다시한번 push해보겠습니다. 원격저장소 별칭(origin)과 master 브랜치에 push push 해보겠습니다.

$ git push origin master


역시 깃허브에 반영된것을 확인하실 수 있습니다. 추가된모습을 보실수 있으세요.


혹은 README.md 파일을 다른 브랜치에도 추가하고 싶다면, 로컬저장소에서 git push origin master 명령을 실행하기전에

로컬 저장소를 병합한 후, git push origin -all 형태로 명령을 실행하셔도 됩니다.

.



git fetch와 git pull: 원격저장소와 로컬 저장소의 간격 메꿉니다.


원격 저장소의 commit내역들을 Local 저장소로 가져와 병합하는 방법은 git fetch와 git pull  크게 두가지가 있습니다.

git pull 명령은 원격 저장소의 정보를 가져오면 자동으로 로컬 브랜치에 병합까지 수행하는 것입니다. 자동으로 병합되기때문에 어떤 점들이 변했는지 알아보기가 힘들 수 있습니다. 그러므로 git fetch를 사용하길 권고합니다.


git fetch와 git pull을 이용해보기위해 실습순서를 아래와 같이 진행할 것입니다.


1. 원격저장소, github에서 파일 수정합니다.

2. 로컬저장소에서도 같은파일 수정합니다.

3. push 시도와 실패합니다.

4. fetch 실시합니다.

5. 병합시도합니다.

6. 푸시 재시도를 할것입니다.

7. 원격저장소에서 제대로되었는지 확인할 것입니다.



github로 가서, hello.py 파일을 변경합니다. (원격저장소에서 commit 한다는 의미입니다.)



자이제 로컬저장소에서도 hello.py를 수정해봅시다.

그리고 아래와 같이 로컬에서 커밋해버립니다.

$ git commit -a -m "hello.py modified in local"


그리고 push를 원격저장소에 해봅니다.

$ git push origin master       master 로컬 브랜치의 내용을 origin 원격저장소에 push하겠다.


하지만 오류를 내면서 git pull 명령을 힌트로 알려줍니다만 별로 유용하지않습니다.


우리는 git fetch를 사용할것입니다.


$ git fetch

$ git status

뭐 큰이상 없는것같습니다.


$ git branch -a 

위의 명령을 치면 현재 어떤 브랜치가 있는지 알 수 있습니다. 모든 로컬저장소와 원격 저장소의 브랜치정보를 볼 수 있습니다.


$ git merge origin/master

위의 명령을 치면, 충돌이 발생했다고 출력합니다.


이제 충돌을 해결해봅시다.

git diff 브랜치이름 명령을 이용해봅시다. git diff는 로컬저장소의 브랜치와 원격 브랜치 저장소 사이에 어떤 차이점이 있는지 미리 알아보는 명령입니다.

만약 git pull명령을 이용했다면 페치와 병합을 자동으로 수행해버려서 어떤 변경사항이있는지 알기가 매우어려워집니다.

그리고 이제 로컬에서 원하는 방향으로 다시 수정해봅시다. conflict을 해결하는 방향으로요!.


그리고 다음 명령과 같이 커밋합니다.

$ git commit -a -m "conflict resolved github"
$ git push origin master


이제 제대로 병합된것을 확인하실수있습니다.


또한, insights -> graphs -> Network를 누르시면, 지금까지 작업과정을 확인하실 수 있습니다.



만약 위의 과정에서  git pull origin master 이런식으로 명령어를 쳤다면, 변경내용을 가져오고 자동으로 병합해버립니다. 그러므로 그상태에서 git commit 과 git merge명령을 실행해도 이미 작업할 것이 없다는 메세지를 확인하실 수 있습니다.



추천드리자면, fetch를 통해 원격저장소의 커밋을 가져오고 로컬저장소에서 이를 확인한 다음 수동으로 병합하는 방법을 가장 추천드립니다.


포스팅에 앞서.

드디어 Git을 로컬뿐만 아니라 원격에서 사용해야할 차례입니다. 원래 Local에서만 git을 이용한다면 의미가 반감되는 정도입니다. 그러니 원격 저장소를 사용할 수 있도록 해야합니다.  github에 계정을 만들고 사용하는 방법을 포스팅 하도록 하겠습니다.



OverView.

Github 이용 이점은 다음과 같습니다.

 - 전세계에서 진행되는 오픈 소스프로젝트가 많이 모여있어 이에 참여하고 기여할 수 있는 기회가 있습니다.

 - 개발자는 Github를 이용해 자신이 작성했던 코드 그자체를 즉시적으로 제공할 수 있습니다.

 - IT개발자 뿐만 아니라 디자이너, 기획자등 모두 협업할 수 있습니다.




GitHub 가입하기.

https://github.com

sign up for github 선택하여 회원가입합니다. 음 모두 free로 선택해서 가입하시면 되겠습니다.

모든 이메일 인증과 절차를 끝내고 sign in 한 화면입니다. 



원격 저장소 생성.

원격저장소는 외부에서 접속하여 저장하는 저장소입니다. 앞선 포스팅에서는 로컬에서 git으로 작업했다면 이제는 원격 저장소에도 저장하여 다수 개발자들과 협업을 해야합니다.



Github의 기능 소개입니다.

Fork: 다른 사람의 저장소를 복사하는 기능입니다.

Pull Request: 포크한 저장소를 수정해 다시 원본 저장소에 병합해달라는 요청을 보내 사용자 사이의 상호작요을 일으킬 수 있습니다.

Issues: 저장소 안에서 사용자들 사이의 문제를 논의하는 기능입니다. 

Wiki: 저장소와 관련된 체계적인 기록을 남기는 기능입니다.


사용자들끼리, 서로의 원격 저장소를 읽거나 쓸 수 있어서, 깃허브에서 오픈소스 프로젝트가 활발하게 이루어진답니다.



그러면 실습에 쓰이는 새로운 원격 저장소를 github에서 생성해보도록 하겠습니다.


[New repository]를 선택합니다.

Owner: 사용자 아이디가 표시됩니다.

Repository name: 저장소 이름입니다.

Description: 원격저장소 역할을 설명합니다.

public/private: 저장소 공개 비공개 설정입니다.

Add .gitignore: 프로젝트에 포함되지않을 파일목록을 만들 때 사용합니다.

Add a license: 어떤 라이센스에 속할지 선택합니다.


다음과 같이 설정하고 생성했습니다.




GitHub 원격 저장소의 구조.

오른쪽 상단의 메뉴들에 대한 설명입니다.


Watch: 원격저장ㅅ의 활동내역을 사용자에게 알려줍니다.

Star: 즐겨찾기 기능이라 생각하시면됩니다.

Fork: 해당 원격저장소를 fork 합니다. 얼마나 많은 사람들이 fork했는지 수가 나타납니다.




저장소 메뉴들을 살펴보겠습니다. 


Code: 해당 원격저장소의 루트 디렉토리로 이동합니다.

issues: 주요 이슈사항을 기재한후 관리합니다.

Pull Requests: 전체 목록을 모아서 보여줍니다. 목록마다 댓글 형태로 토론할 수 있습니다. 왼쪽에있는 숫자는 현재 요청이 온 리퀘스트를 받아들일것인지에 대한 논의가 몇개인지 알려주는것입니다.

Wiki: 공유할 정보나 개발문서, 참고자료등을 작성하기 위한 기능입니다. 

pulse: 해당 원격저장소의 최근 변경 내역을 확인할 수 있습니다. 

Graphs: 공헌자의 공헌내역, 커밋 반영 수 등 활동내역을 그래프화해서 확인할 수 있습니다.

Setting: 해당 저장소 관리자면, 각종 설정을 변경 할 수 있습니다.

HTTPS Clone URL: 원격 저장소를 clone할 때 사용하는 주소정보를 알려줍니다. 

Clone Desktop: 깃허브 전용 클라이엍느 프로그램을 사용할 때 클론할 떄 클릭하면 됩니다.

Download ZIP: 원격 저장소의 전체파일을 하나의 압축 파일형태로 다운로드 받을 수 있습니다.



GitHub 사용자 유형.


사용자 유형 

특징 

저장소 관리자 

 원격 저장소 읽기 및 쓰기 가능. 협업자 초대와 소유권 이전가능합니다.

협업자 

 원격 저장소 읽기 및 쓰기 기능을 할 수 있습니다.

일반 사용자 

 원격 저장소 읽기만 가능합니다. 쓰기 권한이 없으므로 포크를 하여 작업 해야합니다.


다음 포스팅엔 직접 원격 저장소에 접근하여 올려보고 수정해보록 하는 실습을 가지도록 하겠습니다. 

감사합니다.

로컬환경에서 혼자 Git을 사용한다는 가정아래 git의 명령어를 보도록 하겠습니다. 일단 로컬에서 기초를 먼저 다지시면 원격저장소에 저장하는것은 크게 어렵지않게 느끼시게 될것입니다. 기본을 다지다 생각하시고 해당 포스팅 보시면 되겠습니다.


하기와 같은 시나리오 대로 진해앱도록 하겠습니다.

- 로컬 저장소 생성

- 저장소에 파일 생성 및 추가

- 추가된 파일의 수정

- 기본 브랜치에 영향을 끼치지않는 브랜치 생성

- 브랜치 병합

- 충돌 해결

- 저장소 기록 보기


시나리오를 살펴보니, 브랜치간의 병합하고 충돌과정을 해결하는게 딱봐도 어려워 보이네요. 차근차근 풀어가보도록 하겠습니다.


용어정리를 먼저하겟습니다.


Checkout: 현재 작업공간으로 해당 브랜치를 가져온다.

Commit: 프로젝트에서 의미가 있는 최소한의 단위입니다. 의미를 가질 수 있게되는 시기라면 커밋을 하는게 좋습니다.


앞서 포스팅했던, 글을 참고하여 git bash를 실행하도록 합니다.


1. git init 저장소 생성

Git저장소로 사용할 디렉터리를 만들어봅니다.


> mkdir my_work   //디렉토리를 새로 생성합니다.

> cd my_work        // 디렉토리 이동을 합니다.

> git init               //  저장소 초기화를 진행합니다.


현재 작업중인 브랜치가 master가 된것도 확인하실 수 잇습니다.



2. git add, git commit

파이썬 파일 Hello world를 출력하는 프로그램을 작성하도록 하겠습니다. 파이썬이 설치안되어있으시다면 일반 텍스트파일로 진행하셔도 무난합니다. 실전과 같은 느낌으로하려고 파이썬 을 선택했기 때문입니다. 정말 윈도우에서 파이썬을 설치하고싶으시다면, 해당링크 선택하여 설치하시고 오시면 되겠습니다. 


저는 hello.py 파일을 생성해서 print("hello world") 라고 코드를 작성하여 저장했습니다.


hello world가 출력되는것을 확인하실 수 있습니다.

자 이제 저장소 상태를 확인해봅시다.


> git stauts

아래과 같은 메세지가 출력됩니다.

추적하지 않은 파일이 저장소에 있다고 알려줍니다. 이를 추적하려면 git add를 사용하며 된다고 하네요. 소원대로 사용해줍시다.


> git add hello.py


그이후에 다시 쳐봅니다.

> git status


새로운 파일 hello.py가 추가되었다고 뜨는것을 확인하실 수 있습니다.

이제 commit을 해보겠습니다.


> git commit


앗 유져 이메일과 사용자이름을 먼저 설정하고 진행하라고 하는군요. 저처럼 설정안하신분은 설정하고 다시 진행하도록 합니다.


> git config --global user.email "이메일"

> git config --global user.name "이름"


다시 깃 커밋을 날려줍니다.

> git commit


커밋 메세지를 작성하는 화면이 나옵니다. 아마 VIM이 실행되었을 것입니다. I키를 눌러 첫번째 줄에 여러분들의 커맨트를 다시면 되겠습니다.

그이후 ESC를 누르고 :wq룰 입력후 enter를 쳐서 빠져나옵니다. 그러면 커밋이 완료된것입니다.

화면을 빠져나오면, 마스터 브랜치에 어떠한 변화가 생겼는지 출력되는 커멘트들을 확인하실 수 있습니다.


.


3. git branch, git checkout

현재 작업하고있는 브랜치를 확인하는 커맨드는 다음과 같습니다.

> git branch

master 브랜치를 확인하실 수 있습니다.


브랜치 생성은 다음과 같습니다.

> git branch myBranch 


>git branch

master 브랜치, myBranch 를 확인하실수있습니다. 또한 *글자가있는데, 이는 지금 작업중인 브랜치를 표시합니다.


이제 브랜치를 이동해보겠습니다.

>git checkout myBranch


> git branch


해당 브랜치에서 hello.py를 수정해보겠습니다.

>vim hello.py


printf("Hello world") 코드아래, print("Tell me hello") 코드 작성합니다. 저장후 나옵시다. 여기까지가, myBranch에서 hello.py파일을 수정한 상태입니다.



4. git commit -a

현재의 상태를 보겠습니다.

>git status

hello.py 가 수정되었다고 하네요.

이제는 git add 혹은 git commit -a 를 커멘드를 날려라고 하네요. -a옵션은 변경된 저장소 파일모두를 커밋하는 옵션입니다.


> git commit -a 

역시, vim 이뜨면서 커멘트를 달아라고합니다. 적당한 커멘트를 달고 나옵니다. 


그리고 다시 상태를 확인해봅니다.

> git status

myBranch 에 커밋할게 없다고 뜨는것을 확인하실 수 있습니다.


커밋할때 vim이 열려서 따로 추가하고 나오는게 번거로울 수 있는데 그럴때는 아래와 같이 명령어를 치면 되겠습니다.


> git commit -m "커밋할 메세지를 여기에 작성"


5. git merge: master 브랜치와 병합

그럼 이제 다시 master 브랜치로 체크아웃 하겠습니다.


> git checkout master

> python hello.py 

헬로 월드만 뜨는것을 확인하실 수 있습니다.


그리고 이제 브랜치 병합을 실시하겠습니다.


>git merge myBranch

myBranch에 추가한 print("Tell me hello")가 제대로 뜨는지 확인해보겠습니다.


>python hello.py

제대로 출력되는것을 확인하실 수 있습니다. 혹은, cat hello.py 를 입력하시면, myBranch에서 추가한 구문이 병합되어 master 브랜치의 hello.py에 반영된것을 확인하실 수 있습니다. 


6. 각 브랜치의 독립성 확인

병합전 독립성을 확인해보겠습니다.

현재 master 브랜치에서 hello.py마지막에 print("tell his world") 를 추가합니다.


그리고 커밋을 합니다.

>git commit -a    //a옵션은 수정된 파일 모두 커밋입니다.


마스터 브랜치에 커밋 완료했으면 다시 브랜치를 이동하겠습니다.


>git checkout myBranch

>vim hello.py

여기까지 실행했으면 hello.py에는 master 브랜치에서 반영했던 내용이 반영안된것을 확인하실 수 있습니다.

여기선 print("Tell Her world") 를 추가하고 저장하겠습니다.


그리고 해당 브랜치에서 커밋하겠습니다.

>git commit -a 


자 그럼 hello.py가 master 브랜치와 myBranch에서 독립적으로 작성된것을 확인하실 수 있습니다.



7. .gitignore 불필요한 파일 및 폴더 무시

보통 개발을할때 빌드파일 로그파일 기타 잡파일들이 프로젝트 폴더에 포함되는경우가 있습니다. 이런파일들을 commit하게되면 브랜치에는 쓸데없는 파일들이 차고 넘치겠지요. 이런것들을 방지하고자 commit할때 제외시켜주도록 도와주는 파일이 .gitignore파일이 되겠습니다.


>touch .gitignore

빈파일의 .gitignore 파일을 생성합니다.


직접 작성하기엔 저희에겐 시간이없습니다. 그래서 해당사이트에서 도움을 받도록 하겠습니다.

https://www.gitignore.io/

파이썬과 사용중인 운영체제 윈도우스를 선택했습니다. IDE도 입력하시면 됩니다. 아무튼 create하면 파일을 생성해주는데 이걸 .gitignore 파일에 넣으시면 되겠습니다. 저는 메모장으로 그냥 넣었어요.


그리고 다시 

> git status


항상 파일을 새로생성했으면add를 먼저 해주시고 그이후부터 commit을 해주셔야 합니다. add를 통해서 추적을 시작하겠다는것을 전달하는 것이지요.


>git add .gitignore

>git commit -m "added ignorefile"


이제 윈도우, 파이썬으로 작업하실때 불필요한 파일이 저장소에 커밋되는것을 방지하실 수 있습니다.


8. 충돌해결

마스터 브랜치로 이동하여 myBranch와 병합을 시도해보록 하겠습니다.


>git checkout master

>git merge myBranch

cat hello.py

해당 master 브랜치가 merging 이라고 표시가 나오네요. 또한, hello.py 파일을 보면 myBranch에서 작성했던 내용이랑 달랐기때문에 충돌이 되었고 해당파일에 충돌 표시가 보이는것을 확인하실 수 있습니다.


충돌이 났으니 개발자가 직접 풀어야겠죠? 해당 hello.py를 열어서 충돌난 부분을 수정해서 적절하게 합쳐줍시다.

그리고 커밋해봅시다. 

참고로, 이번엔 add로 추적할 대상을 선택안했기때문에 git commit 이 아닌 git commit -a 를 쓰면됩니다.


> git commit -a -m "conflict resolved!"


충돌을 해결하니 master 브랜치도 merging이없어진것을 확인하실 수 있습니다.

충돌을 해결하였습니다.



9. git log 기록보기

> git log --graph

SHA값, 커밋한 사용자, 시각, 메세지등을 확인하실 수 있습니다. 브랜치가 생성되고, 분기되고 merge까지 되는것을 시각적으로 보실 수 도 있습니다.



> git log --stat

각 커밋에서 수정된 파일의 통계정보를 보여줍니다.

안녕하세요 진쓰예요. 형상관리툴하면 가장먼저 생각나는툴은 역시 깃(GIT)이라고 할 수 있습니다.

깃은 리누스 토발스가 개발한 형상관리툴로서, 압도적인 처리속도로 인해서 전세계 개발자 대다수가 사용하는 아주 강력한 툴이라고 할 수 있습니다.


git 포스팅을 시작하는 이유는, 실제 제가 일하고 있는 현업에서 점점 git을 사용하는 추세로 바뀌고 있기 때문입니다. 그러면 그전엔 어떤 형상관리 툴을 썼느냐 하면 p4(perforce)라는 형상관리툴을 이용했습니다. 윈도우 Base의 gui환경을 제공했기 때문에 사용하기 편리했습니다. 그러나 대세에 따라가려면 git을 써야겠죠? 또한, 현업을하면서 퍼포스가 가지는 한계에 부딪혔기때문에 결국 git을 공식 사용하기로 선포하였다고합니다. 부서에서 진행한 git 세미나를 들었었는데요. 실습없이 진행하다보니 그냥 감만 잡은 상태입니다. 그래서 블로그를 진행해보면서 직접 실습도해보면서 개인적으로 공부도 해보고 여러분들에게 공유도하면 좋을 것 같아서 해당 git 포스팅을 하기로 마음먹었습니다.


보통 리눅스 환경에서 git을 많이 사용할텐데요.윈도우에서도 설치하고 이용해보도록 윈도우 git 설치 포스팅 시작하겠습니다.



먼저 공식사이트로 이동해서 git을 다운받도록 합시다.

https://git-scm.com

 

공식사이트로 이동하셨으면 아래화면중 Downloads를 선택합니다.


Downloads를 선택하시고 Windows를 선택하시면, 해당하는 PC에맞는 Bit의 인스톨러를 자동 다운로드하게 됩니다.

 

다운로드가 다되면 설치를 진행하시면 됩니다.

저같은경우는 전부 default로 설정된대로 설치를 진행하였습니다.

이렇게 하시면, git 환경변수도 설치과정중에 자동으로 할당되게됩니다.

 

 

설치를 다 끝내시면, 윈도우 시작에 git bash를 검색하면 다음과 같은 아이콘을 확인하실 수 있게 됩니다.

 

그리고 실행하시면 다음과 같은 bash 창이 열리는것을 확인하실수 있습니다.

 

 

설치되었으면  git이 제대로 설치되었는지 확인해봐야겠죠? 개발자들은 이런 확인과정을 꼼꼼히 해주셔야 합니다.

 

 

사용자 이름과 이메일을 입력하려면 다음 명령을 커멘드라인에 입력하고 실행합니다. git에서 커밋할때마다 기록하는 사용자 이름과

메일 주소를 설정하는 명령입니다.

 

명령을 실행해도 특별한 메세지가 출력되지는 않습니다. 하지만 이제 Git을 사용할 준비가 되었습니다.

혼자 개발이아닌 다수의 개발자들과 협업을 할 수도 있게 되었고, 또한 github사이트에 공유하여 open source 프로젝트도 진행하실 수 있는 환경을 구축하게 되었습니다.

 

 

감사합니다. 부디 Git을 잘 다루는 개발자가 되어 형상관리를 예쁘고 멋지게 해봐요.

다음 포스팅 부터 git을 이용한 실습 예제들을 소개하도록 하겠습니다.

+ Recent posts