본문 바로가기
Tools for Dev

GIT - Fast Version Control System

by leanu 2008. 11. 13.
=========================::: 당부의 한마디 :::============================
열심히 테스트하고 정리한 자료입니다. 서로 좋은 자료를 공유하고자 복사
방지를 걸어놓지 않았으니  마음껏  가져가셔도  좋습니다만,   짧은 덧글
한마디와 인용시 출처를  밝혀주셨으면  합니다.    내용 수정은 허락하지
않겠습니다.  반드시  댓글이나  이메일을 통하여 수정하고자 하는 부분을
알려주셨으면 좋겠습니다.
=======================================================================


Log

-------------------------------------------------------------------------

2010.02.22 git init-db 에 --bare 설명 추가



Introduction

-------------------------------------------------------------------------
프로그램 소스에 대한 Version 관리 툴로서, CVS와 비슷한 종류이다.
GIT는 강력한 기능들과 효율적인 자원활용성을 자랑한다.



Installation
-------------------------------------------------------------------------




설치는 위의 문서를 참조하도록 하고
문서에 나와있지 않은 주의사항이나 팁을 적고자 한다.

< Stage 1 > Create Template Repository

우선 Repository를 생성하기 전에 기본이 되는 Template Repository를 만든다. 이것을 생성하는 이유는 외부에서 Repository의 파일을 clone 하기 위해서는 적어도 하나의 파일과 그에 따른 commit이 한개 있어야 하기 때문이다. 이 폴더는 나중에 두고두고 쓸 것이므로 GIT의 프로젝트폴더가 담길 곳에 같이 넣어둔다. 우선 지금은 /git/를 모든 Repository의 루트로 가정한다.

:::::::::::::::::::::::::::::::::::::::::::::::::: [ 명령어 ]
        cd /git
        mkdir template            // Template Repository 생성
        git-init-db               // 초기화
        touch dummy               // 더미 파일 생성
        git add dummy
        git commit -m "Initialization"       // Add & Commit
        mv .git /git/template.git
        cd ..
        rm -rf /git/template
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::



< Stage 2 > Create Project Repository with template one

이제 본격적으로 Project Repository를 생성해보자. <Stage 1>에서 한번 생성한 Template Repository는 Stage 2에서 Project Repository 를 생성할 때 계속 이용할 것이다. 앞으로 프로젝트 이름은 git_usage_project로, 이 폴더에 업로드 할 수 있는 group id 는 git_usage_team 으로 가정하겠다. 각 유저별 그룹설정에 대해서는 아래의 참고를 확인하기 바란다.

:::::::::::::::::::::::::::::::::::::::::::::::::: [ 명령어 ]
        cd /git
        GIT_DIR=git_usage_project.git
        git --bare init-db --template=/git/template.git --shared=group
        chown -R root:git_usage_team git_usage_project.git
        chmod -R 770 git_usage_project.git
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

맨 마지막 라인은 해당 그룹과 생성한 user에게만 소스를 공개하겠다는 말이다. 만일 open source 로 운영할 것이면 777로, 자기만 하려면 700 을 사용하라.

git init-db 명령어에서 --bare는 repository 를 생성할때 bare형으로 만든다는 것을 선언한다는 것이고 --template 인자는 template 로 사용할 git repository 경로를 지정하는 것이며, --shared=group은 git의 내부 동작에 따른 생성파일들의 그룹 권한을 project.git 폴더의 그룹에게 준다는 의미이다. 만약 이를 지정해 주지 않으면 생성된 파일들은 -r--r--r--로 생성되어 다음 전송시 permission denied 오류를 발생시칼 것이다. 옵션을 적용한 후의 속성은 -rw-rw-r-- 가 되어 그룹의 전송시 아무런 문제를 발생시키지 않는다.

앞으로 자주 사용할 명령어이므로 셸로 만들어 놓으면 간편하다. 아래는 내가 git 프로젝트를 생성할때 쓰는 셸 프로그램 이다. (그룹이름이 잘못된경우 발생하는 에러는 못잡으니 알아서 잘 쓰시길 ㅋ)

====================================================================================

====================================================================================





<참고0> 프로젝트명.git 를 만드는 이유 : 실제로 git에서는 파일형태로 관리하는게 아니라 object별로 모든 파일 및 디렉토리를 관리한다. 이 모든 정보는 .git폴더에 있는데, 만약 서버에서 .git 폴더 이외에 파일들을 따로 또 관리하게 되는경우 파일을 2중으로 보관하는 비효율성과 더불어 .git에서 수정한 내용들을 파일시스템으로 적용시켜야 하는 불필요한 동작을 수반하게 된다. 서버에서는 프로젝트명.git 만으로 관리하는 것을 추천한다. 이것을 bare repository 라고 한다. (option : git --bare ...)


<참고1> 여러개의 프로젝트를 서로 다른 사람이 관리하는 경우 대부분 git 나 git_root 디렉토리를 만들고 그 하위 디렉토리로서 프로젝트 Repository를 생성하게 되는데, 기억해야할 점은 이 git라는 폴더는 소유자와 그룹명이 모두 root 여야한다. (아래의 명령어로 적용시킬 수 있다.)

chown root /git  
chgrp root /git

왜냐하면 하위로 생성한 프로젝트가 /git/ 의 소유자나 소유 그룹명과 다를경우 프로젝트 Repository 에 대한 권한이 있음에도 불구하고 파일 I/O 과정에서 Permission Denied 문제가 발생할 수 있기 때문이다.


<참고2> 폴더에 여러 그룹 권한 주기 : 만약 root 그룹과 group1에게 test폴더 소유권한을 주고싶으면 아래와 같이 주면 된다.

chown -R root:group1 test

<참고3> 한 유저를 여러 그룹에 속하게 하기.

Unix 계열 운영체제는 아래의 두 파일을 통하여 유저와 그룹정보를 얻어온다.

/etc/passwd : 유저 정보
/etc/group  : 그룹 정보

따라서 한 유저를 여러그룹에 속하게 하려면 /etc/group 을 열어서 수정하면 된다.

(예) ydh 라는 유저를 group1, group2, group3 에 속하게 하고 싶으면 /etc/group 을 열어서 각각을 추가시키면 된다.

::::::::::::::::::::::::::::::::::::::::::[ /etc/group ]:::::
          ....
          group1:x:530:user1, user2, ydh
          ....
          group2:x:533:user1, ydh
          ....
          group3:x:540:user2, ydh
          ...
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


Tips
-------------------------------------------------------------------------
1. GIT Repository에 등록한 파일을 삭제하거나 옮기는 경우 'rm' 'mv' 대신 'git-rm' 'git-mv'를 사용한다.

     git commit 을 통해 등록한 파일들은 GIT내에서 그 구조도 저장되어 있다. 만약 rm 이나 mv를 이용하여 기존의 등록한 파일들을 옮기고 add 및 commit 을 하는경우 GIT는 파일이 삭제되거나 옮겨진 줄 모른다. 이렇게 되는경우 다음번에 pull을 하는경우 지워진 디렉토리나 파일이 다시 되살아나고, mv를 한경우에는 옮기기 전 디렉토리나 파일이 다시 생성된다. 따라서 등록되지 않은 것들을 제외한 모든 파일이나 디렉토리를 지우고 옮기고자 한다면 git-rm 과 git-mv를 통하여 하면 된다. (이를 인지하지 못한다면 꽤나 귀찮은 일들이 많아질 것이다. 하루바삐 몸으로 익히자.)

2. branch로 분기하여 작업을 하자.

     자잘한 작업후에 commit 을 하게 되면 굉장히 지저분한 log를 보게 될 것이다. 따라서 일정 단위의 작업(예를 들면, 하나의 cpp파일의 일부를 만든다던가.. 암튼 조그마한 작업) 들은 branch 를 나누어서 한다. branch 생성 및 전환은 다음과 같다. 그리고 현재 속한 branch 가 어디있는지 확인하는 것은 git branch를 입력하면 브랜치명 앞에 붙은 별로 알수 있다.

    $ git branch test                   (test라는 branch 를 만들었다)

    $ git branch                        (현재 master라는 branch에 있음을 알 수있다)
    * master
      test

    $ git checkout test                 (branch를 change 한다)

    $ git branch                        (현재 branch 는 test로 바뀌어 있다)
      master
    * test

주의할 점은 branch switch를 할 경우, commit된 파일리스트를 가지고 switch가 이루어지기 때문에 switch 전에 commit을 하지않은 파일들은 switch후에 그대로 남아있게 된다. 따라서 반드시 아직 등록되어 있지 않은 파일이 있는지 확인한 후 아무 이상이 없을때 이동을 해야한다. (git status 를 이용하면 된다. 참고로 git branch -a 하면 숨겨저있는 branch인 origin/HEAD 와 origin/master를 볼수 있는데, origin은 git clone으로 repository 내용을 받아온 경우 이곳에 담기게 된다. )

     branch작업이 끝나고 본래의 master 와 통합하기 위해 merge 단계를 수행하게 되는데, 이때 무턱대고 merge를 하게 된다면 파일간 conflict가 발생하게 된다. 그래서 차이점이 어떤건지 아래의 명령어를 통해 하나하나 확인한 다음에 수정해서 넣도록 한다.

     $ git log --stat test..master       (test 와 master의 차이가 있는 파일 목록만 본다.)

     $ got log -p test..master           (test 와 master의 차이가 있는 파일의 내용들을 본다.)

    


Error Recovering Tip
-------------------------------------------------------------------------

<< Error 1 >> git push 명령후 다음과 같은 에러 메시지를 받은 경우

     ! [rejected]        master -> master (non-fast forward)

   1. 원인 : 현재 작업하고 있는 Repository가 서버에 있는 Repository보다 오래된 내용이다. Push 를 하게 되면 서버에 있는 최신 내용은 날라가고 현재 작업한 내용만 적용이 되는 문제가 발생할 수 있기 때문에 에러가 발생하게 된것이다.

   2. 해결방법

       1) 강제 삽입하기 (추천하지 않음) : git push --force
       2) 최신내용을 Local에 적용한 후 올리기 : git pull 명령을 이용하면 기존 작업한
          내용에 최신 내용을 덧붙이게 된다. 만약 덧붙이는 과정에서 conflict가 발생한
          경우, 그 안에 어느 부분이 conflict가 발생했는지가 나오기 때문에 잘 확인해
          서 소스를 수정한 후 다시 올리면 된다.


<< Error 2 >> git push 명령 후 다음과 같은 에러가 발생한 경우

error: Object 5ae9947eadfd651788caa9b3b6757d375eebad84 is a commit, not a blob

error: pack-objects died with strange error

unpack eof before pack header was fully read

ng refs/heads/master n/a (unpacker error)

error: failed to push to 'yourid@projectAddress:/project.git'

   1. 원인 : 파일 삭제시 rm 만을 이용했다. 그리고 특정 GIT 명령어를 잘못 사용하여 index가 꼬였다. push 를 할때에는 로컬의 정보를 패키징 해서 서버로 보내게 되는데, 패키징 작업중에 꼬인 index를 발견한 경우 패키징을 멈추고 에러를 발생시킨다. (index 와 tree 에는 남아있기 때문에 실제로 pull을 다시 해보면 삭제된 파일이 생성된다)


   2. 해결방법 :

      작업한 파일들을 다른곳에 치워두고 local repository를 싸그리 날린다.
      git clone을 이용하여 서버의 내용을 복사한 후에 작업한 파일들을 넣고
      commit 하면 완료.

   (p.s) GIT 프로젝트 내의 모든 삭제작업(파일이든 폴더이든)은
           git rm 파일명            이나
           git rm -r 디렉토리       를 사용한다.


<< Error 3 >> git pull 명령후 다음과 같은 에러가 발생한 경우

     You asked me to pull without telling me which branch you
     want to merge with, and 'branch.master.merge' in
     your configuration file does not tell me either.  Please
     name which branch you want to merge on the command line and
     try again (e.g. 'git pull <repository> <refspec>').
     See git-pull(1) for details on the refspec.

     If you often merge with the same branch, you may want to
     configure the following variables in your configuration
     file:

         branch.master.remote = <nickname>
         branch.master.merge = <remote-ref>
         remote.<nickname>.url = <url>
         remote.<nickname>.fetch = <refspec>

     See git-config(1) for details.



References
-------------------------------------------------------------------------
GIT Official site : http://git.or.cz/

SUBversion : http://www.pyrasis.com/main/Subversion-HOWTO (GIT 와 비슷한 버전관리툴)


'Tools for Dev' 카테고리의 다른 글

Excel 에서 유용한 팁  (0) 2008.12.18
Simple GIT Usage  (0) 2008.11.24
boost::shared_ptr  (0) 2008.10.08
boost::asio 를 이용한 asyncronous communication 클래스  (0) 2008.10.07
boost asio - 수정중  (0) 2008.10.01

댓글