Skip to content

Latest commit

 

History

History
840 lines (751 loc) · 53.1 KB

File metadata and controls

840 lines (751 loc) · 53.1 KB

Git Explained

Git Explained

Git Introduction

Git Drill(1단계)

git 설치(brew)

git을 system에 설치, 간단히 brew로 설치

git init, git clone

git init으로 현재 폴더안에.git(repository)이란 폴더를 만든다. 처음에는 commit도 없고, branch도 없다. git clone URL에서 다른곳에 있는 .git폴더를 가져오는 것이다. git clone은 remote와 관련이 있기 때문에 3단계에서도 설명을 할 것이다.

git configure

이제 저장할 공간도 확보했기 때문에 저장 하면 된다. 그런데, 좀 해주어야 할게 있다. 저장은 commit이란 형태로 저장되는데, 여기에는 어떤 사용자가 저장했는지, 언제 했는지 같은 meta data가 들어간다. 그 meta data를 설정해야 한다. 사용자 이름,email주소를 적어주면 된다.

git ignore

.gitigonre파일에서 특정 파일을 commit에 포함시키지 않는다. commit을 지금 몰라도 나중에는 알게 된다. 배제할 파일 목록은 다음을 참고하면 된다. https://gitignore.io/

linked list

git drill(2단계)

원하는 파일로 commit 만들기.

그림으로 보면 다음과 같다.

./img/commit.png

commit 만들 때 유의할 점(2) - unstage하는 법

stage에 올려진 파일을 stage에서 내릴때 사용한다.

commit 만들 때 유의할 점(3) - commit취소

summary

git drill3

말하는 점 조직이란게 이런것이다. 새로운 조직원은 말단 조직원을 통해서만 들어올 수 있고, 그 윗선은 알수가 없다.

또 다른 예로, 노래테이프도 linked list로 볼 수 있다.

Linked list 설명

변형 linked list

변형 Linked list의 고찰

git data structure vs 변형 linked list

git의 용어

git drill4

흔한 질문

git commit

git commit –amend

git branch

git remote

git clone을 하게 되면 원격 URL은 origin이란 이름을 갖게 된다.

git clone

git checkout [head 이동명령어]

  1. git checkout commit: 이것의 의도는, 해당 commit의 내용을 확인하기 위해서다. Head가 해당 commit으로 이동하면서, 그 commit의 working directory를 복원하기 때문에 실제 그당시, 그 commit의 source를 볼수가 있다. 그런데, 여기서 수정은 할 수 없다. 왜냐? 수정을 하고 commit을 하면, 수정된 commit은 수정되기 이전의 commit을 가리킬 수는 있다. 하지만, 해당 linked list의 branch에선 이 새로운 commit으로 이동할 수가 없다. link가 없기 때문이다. 그러면, 이렇게 수정한 commit은 접근할수 없는 미아 commit이 되고 나중에 git garbage colloector에 의해 사라지게 된다. 그렇다면, 수정을 한 후 저장만 하고, commit을 안하면 그냥 갱신된 내용의 commit을 유지하지 않을까? 이것도 안된다.왜냐하면, commit의 내용이 수정되었다는 것은 content addressable한 commit의 특성상 새로운 commit이 되어 야만 한다. 그래서 수정을 하고 저장을 했다 하더라도 git은 동작을 전혀 할수가 없다. 왜냐, git status에 보면, commit에 변경사항이 생겼는데, 이를 처리하지 않아서 아무것도 할 수 없다고 말한다. 그러면 선택은 2가지다. 새로운 commit을 만들거나, unstage하는 경우다. 새로운 commit을 만드는 것은 방금전에 설명한 이유로 안되고, 2번째는 unstage하는 것이기 때문에 commit이 수정되기 전의 상태로 되돌려진다. 즉 수정이 아예 안된다.

    ./img/checkout1.png

  2. git checkout branch: 이것의 의도는 해당 branch가 가리키는 commit으로 working directory가 복원되고, 수정도 할 수 있고, 새로운 commit을 만드는 것도 가능하다. content-addressable하기 때문에 수정이나, 새로운 commit을 만드는 거나 동일한 일이다. 이전에 설명했듯이, linked list는 하나의 주머니로 봐도 되고, 또한 주머니의 입구는 branch로 비유할수도 있다고했다. 여러 주머니가 있을 경우, 특정 주머니를 선택해야 하는데, 좀 더 정확히는 특정주머니의 입구를 선택해야 한다. 왜냐면, 그래야 commit을 담을 수 있기 때문이다. git checkout은 특정주머니의 입구를 선택하는것이다. 그림으로 보고, 설명한다면, Head를 branch로 움직이는 명령어를 git checkout으로 말할 수 있다. Head를 branch로 움직이는건 일반적이고, 정상적인 동작이다. 특정 commit으로 이동도 가능하지만, 그러나 그런 이동은 위에서 말한바대로 source를 보기위한 목적이다. 수정은 추천되지 않고 바람직하지 않다. 왜냐? history가 깨질 위험이 있기 때문이다. history가 깨진다는 것은 여러 사용자가 공유하는 git이 동기화하는데 문제가 생길 수 있다. 그래서 git에선 commit으로 head를 이동해서 수정하는 것을 허용 하지 않는다.

./img/gitcheckout.png

git log

git reset [branch 이동]

git merge

2가지 경우가 있다. 이것을 2 way merge(fast-forward), 3 way merge가 있다.

2 way merge

3 way merge

summary

git rebase

summary

git push

1번의 경우는, URL을 다른이름으로 기술하지 않는한, origin이라는 이름을 갖는다. 그리고 remote branch는 origin/master가 된다. remote git의 URL을 다른 이름으로 mapping하지 않고, branch도 다른이름으로 mapping하지 않으면, default name이 origin과 master이다.

2번의 경우는, git url이 가리키는 git에 이름을 부여하는 것이다. 이 경우 실제 remote git commits을 가져올려면 git fetch같은 명령어를 써야 한다.

둘다, origin/master라는 server의 특정 branch를 가리키는 branch가 생기는데, 이 branch는 움직일수 없다. 마치 bookmark처럼 움직일수가 없다. branch를 움직이는 경우는, git commit으로 새로운 commit을 만들거나, git reset으로 특정 commit으로 이동하거나, git rebase로 이동 시킬수 있는데, 이 모든게 안된다는 것이다. 가장 중요한건 아무래도 그 branch를 우리가 commit을 저장하는 linked list로 사용할 수 없다고 이해하는게 가장 편하다.

john과 호열이 git clone해서 특정 server에 있는 git을 local로 가져왔다고 가정하자.

./img/push1.png

clone을 하면 server의 linked list를 가져오게 된다. origin/master라는 server의 branch가 보여진다. 그리고 master라는 또다른 local linked list가 자동적으로 만들어진다. origin/master는 server와 동기화 될때 갱신되고, local master는 우리가 작업하는 branch라고 보면 된다. 간단한 예로, John이 새로운 commit을 만들어서 server에 반영했다고 하자.

./img/push2.png

별 문제가 없다. 이제 호열이 B라는 commit을 만들고 push해보자.

./img/push3.png

에러가 난다. 호열은 push를 할 수 없다. 호열이 origin/master라는 server의 linked list의 head에 commit을 붙일려고 하지만, 할수없다. 왜냐면,음…호열은 origin/master branch는 Node를 삽입할 수 있는 linked list란 주머니의 입구라고 생각해서 push했는데, john이 이미 push를 해서, head가 이동했다. 호열이 생각한 server의 master는 이동을 했기 때문에 삽입이 불가능해진것이다. linked list의 삽입은 branch, 즉 head에서만 가능한데, head가 옛날 head였던 것이다. 위에서 말했듯이 linked list는 head가 아닌 다른곳에서의 삽입은 불가능하다. 여튼 이런 일은 매우 빈번하게 발생한다. 10명의 개발자, 100명의 개발자가 일을 한다면,서버에 계속해서 commit을 올리고, 이 commit이 삽입된 순간, server의 branch는 이동을 한다. local에서 참조하는 server의 branch는 옛날 데이터 삽입구다. 그래서 commit을 올릴수가 없게 된것이다. 그래서 항상 push하기 전에 server의 git을 pulling or fetch해서 입구를 확인한다음에 push를 해야 하는 것이다.

git pull

git reflog

git tag

git drill5

git repository

./img/basiclinkedlist.png

./img/basiclinkedlist2.png

./img/basiclinkedlist3.png

repository의 본질을 얘기하면서 최초 commit은 모든 repository내의 branch가 가지고 있다는 것을 강조했다. 왜냐면 우리가 사용할 remote repository, local repository는 모두 하나의 뿌리로부터 파생된 branch를 갖는다. 단 한개의 뿌리를 갖는 tree처럼… 그렇기 때문에, 우리가 git remote add origin1 url, git remote add origin2 url … 이런식으로 여러 remote에 있는 repository를 내 local repository를 가져온다고 해도, 실제는 해당 remote repository는 같은 뿌리를 갖는다. 물론 내 local repository조차도 그렇다.

예를 들어서, 삼성전자의 repository가 있고, LG전자의 repository가 있다고 하자. 내가 local repostiory에서 그 2개의 repository를 가져올 수 없다. 하나는 clone하고 다른 하나는 fetch를 해도 안된다. warning이 발생한다. 그 이유로 최초 commit이 다르다. common commit이 없다. 만일 최초 commit이 같다면, 우리는 하나의 .git폴더에서 관리할 수 있게 된다. 그런데, 이 2개의 repository는 서로의 .git폴더를 가지고 있고, 서로 다른 2개의 working directory를 가져야한다. 그런데 우리의 local repository는 단1개의 working directory와 단 1개의 repository다. 그 repository에서 삼성전자는 clone했고, Lg전자는 fetch로 가져올려고 해도 서로다른 repository이기 때문에 1개의 local repository에 담을 수가 없는 것이다. 반면에 commit이 같다면, 우리는 10개의 repository,100개의 repository가 있다해도, 1개의 repository에 담을 수 있다. 물론 branch의 수는 늘어날 것이다. 이것을 그림으로 표시해 보겠다.

./img/repo1.png

./img/repo2.png

위에 처럼 뿌리가 같기 때문에 하나의 local repository에서 관리가 가능한 것이다. 뿌리가 같지 않으면 다른 repository를 현재 작업중인 local repository에 가져오질 못한다. 또 다른 예로, 자신이 local repository에서 자신만의 project를 개발하고 있는데, github에서 어떤 비슷한 project를 발견해서 이를 git clone이나, git fetch로 가져와서 내 repository에서 작업하고 싶다. 가능할까? 당연히 안된다는 것이다.

git 원격저장소와 관련한 용어들

1. Upstream, Downstream

2. remote branch,tracking branch,local branch

git clone의 경우

git fetch의 경우

설명

위 그림에서 오른쪽에 보면, origin/master, origin/issue33가 보인다. 이것을 remote branch라고 부른다. remote란 단어가 좀 혼란스럽게 만든다. remote branch라고 하면 server에 있는 branch를 생각한다. 물론 그것을 가리키는 것도 맞고, local repository에 있는, origin/master, origin/issue33같은 branch도 remote branch가 맞기 때문이다. 실제 local repository의 remote branch(origin/master)를 진짜 원격지 branch로 보고(생각하고) 작업을 한다.왜냐면, origin/master라는 것은 실제 server와 동기화된 branch이기 때문이다. 그래서 인터넷이 연결 안되어 있는 상태에서도 git을 사용할 수 있다고 하는 것이다. 왜냐면 어차피 인터넷을 연결하고 있어서도 실시간 동기화를 하는게 아니기 때문이다. git fetch나 git pull로 동기화를 하기전까지는 local의 remote branch를 보고 작업을 하기 때문에 인터넷이 연결되지 않은 상태로, 원래 작업을 하는 것이다. git pull과 git fetch를 하기전까진 어차피 offline작업일뿐이다.

tracking branch

올리기 위해서 필요한거다.

./img/cloneterm.png

이제 좀 더 자세하게, git push, git fetch, git pull을 살펴볼 것이다.

git clone

git fetch

git pull

git push는 git pull과 반대 과정이다. git pull 과정을 그림으로 그려보겠다.

./img/gitpull1.png

git push

git push 과정을 그림으로 그리면 다음과 같다.

./img/gitpush1.png

git drill6

git을 왜 사용하는가?