Git 사용법

기본 사용법

깃 기초 개념

깃(git) 프로젝트는 물리적으로 깃 디렉토리 .git와 작업 디렉토리로 구분됩니다. 깃 디렉토리는 깃 커밋한 것들의 데이터베이스를 저장하고 중간 단계인 stage 상태를 저장하는 곳입니다. 작업 디렉토리는 깃 디렉토리로부터 파일들을 복사해서 실제로 우리가 작업하는 파일들이 있는 공간을 말합니다. 일반적으로 작업 디렉토리 안에(?) 깃 디렉토리가 위치하고 있습니다.

작업 디렉토리에서 새로운 파일을 만들었으면 그 파일을 stage 상태로 만들고 그것을 커밋해서 데이터베이스에 저장합니다. 스테이지 상태로 만드는 명령어는 git add이고 커밋하는 명령어는 git commit 입니다.

커밋된 파일을 수정하면 그 파일은 modified 파일이 됩니다.

깃 프로젝트 만들기

  1. 관리자에게 아이디와 이름을 이메일로 보냅니다.
  2. 관리자가 보낸 이메일을 받아 링크된 주소로 가서 패스워드를 수정합니다.
  3. 보낸 아이디와 수정된 패스워드를 이용해서 로그인합니다.
  4. 상단의 플러스 기호를 눌러 새로운 프로젝트를 생성합니다.
  5. 만들어진 새로운 프로젝트 화면 왼쪽 매뉴 중 Settings > General을 누릅니다.
  6. 오른쪽에서 Permissions를 클릭하여 Repository 항목 > View and edit files in this project 항목 > Only project members를 선택한 후 밑에 Save changes를 누릅니다.

깃 처음 사용

다음은 윈도우즈 시스템에 관한 내용입니다.

로컬에서 깃을 처음 사용하는 사용자라면 사용자 이름과 이메일을 로컬 깃 시스템에 글로벌로 등록해야 합니다. 깃 명령창에서 다음과 같이 입력합니다.

git config --global user.name "Kildong, Hong"
git config --global user.email "kildonghong@gmail.com"

그리고 원격저장소에 처음 접속을 실행하면 원격저장소의 아이디와 암호를 물어봅니다. 아이디와 암호는 원격저장소에 등록된 아이디와 암호입니다. 이것은 최초 한번만 물어봅니다. 이 정보는 윈도우즈 시스템에 저장됩니다. 제어판 > Windows 자격 증명 > 일반 자격 증명에 저장됩니다.

로컬에서 클론하기

원격저장소에 있는 프로젝트를 clone을 이용해서 로컬에 복사할 수 있습니다.

프로젝트 만들기

로컬 컴퓨터에서 깃 프로젝트를 먼저 만들고 원격 서버에 커밋하는 방법을 설명합니다.

깃 명령창 이용

깃 명령창 또는 깃 쉘에서 다음과 같이 깃 프로젝트를 만듭니다.

$ git example

그러면 example 이라는 폴더가 하나 만들어지며 그 안에는 .git 폴더가 새롭게 만들어지며 example이라는 새로운 깃 프로젝트가 만들어집니다.

example 폴더로 이동합니다.

$ cd example

새로운 파일을 하나 만듭니다.

$ touch sample.txt

상태를 확인합니다.

$ git status

커밋하기 전 단계인 add를 합니다.

$ git add sample.txt

다시 한번 상태를 확인해봅니다.

$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   sample.txt

add를 취소하고 싶으면 다음과 같이 합니다.

$ git rm --cached sample.txt
rm 'sample.txt'

그러면 처음 상태로 돌아옵니다.

$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        sample.txt

nothing added to commit but untracked files present (use "git add" to track)

다시 한번 add를 합니다.

$ git add sample.txt

새로운 파일을 하나 더 만듭니다.

$ touch sample.js

스테이징 된 파일 sample.txt를 커밋합니다.

$ git commit -m "new txt file commit"
[master (root-commit) c8c9933] new txt file commit
 1 file changed, 1 insertion(+)
 create mode 100644 sample.txt

sample.js 파일을 add한 후 commit을 해봅니다.

$ git add sample.js
$ git commit -m "init commit" sample.js
[master d23009d] commit sample.js
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 sample.js

sample.js 파일을 수정을 해봅니다.

$ vim sample.js

다음과 같은 문장을 넣고 저장을 해봅니다.

console.log("Hello");

그리고 status를 확인해봅니다.

$ git status
On branch master
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:   sample.js

no changes added to commit (use "git add" and/or "git commit -a")

깃 명령창에서 기존 프로젝트 폴더를 깃 프로젝트로로 만들기

깃 명령창에서 기존의 프로젝트 폴더 이름이 existing_proj라고 하고 그 안에는 이미 web 디렉토리와 app.js 파일이 있다고 가정합니다.

\---existing_proj
    |   app.js
    |
    \---web

existing_proj 디렉토리로 이동합니다.

$ cd existing_proj

거기서 git init을 하면됩니다.

$ git init

status를 확인해봅니다.

$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        app.js

nothing added to commit but untracked files present (use "git add" to track)

web 폴더 안에 아무런 파일이 없기 때문에 status에 표시되지가 않습니다.

깃랩 서버 이용

  1. 깃랩 서버에서 프로젝트를 만든다. 다음과 같은 도움말을 참조합니다.
    Command line instructions
    Git global setup
    git config --global user.name "Yoon, Daeki"
    git config --global user.email "dowellware@gmail.com"
    
    Create a new repository
    git clone http://compmath.korea.ac.kr/gitlab/깃랩그룹/프로젝트이름.git
    cd labor-management
    touch README.md
    git add README.md
    git commit -m "add README"
    git push -u origin master
    
    Existing folder
    cd existing_folder
    git init
    git remote add origin http://compmath.korea.ac.kr/gitlab/깃랩그룹/프로젝트이름.git
    git add .
    git commit -m "Initial commit"
    git push -u origin master
    
    Existing Git repository
    cd existing_repo
    git remote rename origin old-origin
    git remote add origin http://compmath.korea.ac.kr/gitlab/깃랩그룹/프로젝트이름.git
    git push -u origin --all
    git push -u origin --tags
    
  2. 로컬에서 이미 프로젝트를 만들었다면 프로젝트 디렉토리로 이동합니다.

    >cd 프로젝트_디렉토리_이름
    
  3. 로컬 프로젝트 디렉토리에서 다음과 같이 입력합니다.

    git init
    git remote add origin https://compmath.korea.ac.kr/gitlab/깃랩그룹/프로젝트이름.git
    git add .
    git commit -m "Initial commit"
    git push -u origin master
    

origin은 원격저장소를 부르는 이름입니다. 다음에 나오는 url이 원격저장소에 저장될 곳입니다.

TortoiseGit 이용

  1. 토토이즈깃을 설치한다.
  2. 앞에서 만든 프로젝트 사이트에 가서 주소를 복사한다.
  3. 첵아웃할 적당한 폴더를 선택한다.
  4. 첵아웃할 폴더의 빈공간을 오른쪽 클릭하여 Git Clone을 선택한다.
  5. URL 항목에 프로젝트 주소를 붙여 넣는다. Ok를 클릭하여 첵아웃한다.

자격증명 갱신

암호가 잘못 저장되었거나 변경되었을 때 윈도즈 깃 암호는 제어판 > 모든 제어판 항목 > 자격 증명 관리자에 저장되어 있다. 따라서 여기서 삭제하고 다시 접속해야 한다.

커밋

  1. 로컬에서 파일을 수정한다.
  2. 수정된 디렉토리를 오른쪽 클릭하여 Git Commit > Origin을 클릭한다.
  3. 아이디와 이메일을 요구하면 적어 넣는다.
  4. 메시지(Message)란에 간단하게 적는다.
  5. Commit(커밋)을 누른다.
  6. Push를 누른다.
  7. Ok를 눌러 원격 서버에 저장을 한다.
  8. Close를 누른다.

SSH 접속

리눅스에서 ssh 접속을 이용하는 방법이다.

  1. 깃랩에 공용키를 등록한다.

  2. 클라이언트에서 다음과 같이 접속한다.

    $ git clone 깃프로젝트주소
    

    깃프로젝트주소는 git@서버주소:testuser/testproject.git와 같이 git로 시작한다.

  3. 만일 서버가 SSH 접속 포트를 22000으로 변경했으면 ~/.ssh/config 파일에 다음과 같이 넣고 클론을 한다.

    Host  서버주소
          Port 22000
    

    서버주소에는 서버주소를 넣는다.

에러 처리

다음과 같이 413 request entity too large 413 에러가 나고 /var/log/nginx/error.log 파일에 client intended to send too large body 라는 메시지가 뜨면 /etc/nginx/nginx.conf 파일 server 구역에 다음을 넣는다.

client_max_body_size 20M;

브랜치 만들기

Git의 브랜치는 커밋 사이를 가볍게 이동할 수 있는 어떤 포인터 같은 것입니다. 기본적으로 Git은 master 브랜치를 만듭니다. 처음 커밋하면 이 master 브랜치가 생성된 커밋을 가리킵니다. 이후 커밋을 만들면 master 브랜치는 자동으로 가장 마지막 커밋을 가리킵니다. [1]

Note

Git 버전 관리 시스템에서 “master” 브랜치는 특별하지 않습니다. 다른 브랜치와 다른 것이 없습니다. 다만 모든 저장소에서 “master” 브랜치가 존재하는 이유는 git init 명령으로 초기화할 때 자동으로 만들어진 이 브랜치를 애써 다른 이름으로 변경하지 않기 때문입니다.

마스터 브랜치로부터 새로운 브랜치를 만들어보겠습니다.

  1. 현재 마스터 브랜치 상태에 있는지 확인합니다.
    > git status
    
  2. 새로운 브랜치를 만듭니다.
    > git branch new_branch_name
    
  3. 마스터를 새로운 브랜치로 첵아웃합니다.
    > git checkout new_branch_name
    
  4. VS Code에서 폴더를 열면 맨 왼쪽 아래에 바뀐 브랜치 이름이 보입니다.

원격에 있는 브렌치 가져오기

git fetch

또는 vscode에서 ctrl + shift + p를 눌러 git: fetch를 실행하면 됩니다.

서버의 추적 브랜치와 로컬 브랜치와 상태를 -vv 옵션을 이용해서 살펴볼 수 있습니다.

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] forgot the brackets
  master    1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
  testing   5ea463a trying something new

위의 결과를 보면 iss53 브랜치는 origin/iss53 리모트 브랜치를 추적하고 있다는 것을 알 수 있고 ahead 표시를 통해 로컬 브랜치가 커밋 2개 앞서 있다(리모트 브랜치에는 없는 커밋이 로컬에는 존재)는 것을 알 수 있습니다. master 브랜치는 origin/master 브랜치를 추적하고 있으며 두 브랜치가 가리키는 커밋 내용이 같은 상태입니다. 로컬 브랜치 중 serverfix 브랜치는 server-fix-good 이라는 teamone 리모트 서버의 브랜치를 추적하고 있으며 커밋 3개 앞서 있으며 동시에 커밋 1개로 뒤쳐져 있습니다. 이 말은 serverfix 브랜치에 서버로 보내지 않은 커밋이 3개, 서버의 브랜치에서 아직 로컬 브랜치로 머지하지 않은 커밋이 1개 있다는 말입니다. 마지막 testing 브랜치는 추적하는 브랜치가 없는 상태입니다.

여기서 중요한 점은 명령을 실행했을 때 나타나는 결과는 모두 마지막으로 서버에서 데이터를 가져온(fetch) 시점을 바탕으로 계산한다는 점입니다. 단순히 이 명령만으로는 서버의 최신 데이터를 반영하지는 않으며 로컬에 저장된 서버의 캐시 데이터를 사용합니다. 현재 시점에서 진짜 최신 데이터로 추적 상황을 알아보려면 먼저 서버로부터 최신 데이터를 받아온 후에 추적 상황을 확인해야 합니다. 아래처럼 두 명령을 이어서 사용하는 것이 적당하다 하겠습니다. [2]

$ git fetch --all; git branch -vv
pull

git pull 명령은 대부분 git fetch 명령을 실행하고 나서 자동으로 git merge 명령을 수행하는 것 뿐입니다. 바로 앞 절에서 살펴본 대로 clone 이나 checkout 명령을 실행하여 추적 브랜치가 설정되면 git pull 명령은 서버로부터 데이터를 가져와서 현재 로컬 브랜치와 서버의 추적 브랜치를 merge 합니다.

일반적으로 fetchmerge 명령을 명시적으로 사용하는 것이 pull 명령으로 한번에 두 작업을 하는 것보다 낫습니다.

원격 저장소로 올리기

새로 만들어진 브랜치 serverfix를 원격저장소로 보냅니다.

$ git push origin serverfix

Merge하기

다른 testing 브랜치를 마스터 브랜치와 머지를 하는 것입니다.

마스터 브랜치로 이동합니다.

$ git checkout master

testing 브랜치와 머지를 합니다.

$ git merge testing

만일 testing 브랜치와 master 브랜치의 파일이 충돌이 일어나면 수동으로 해결을 해야 합니다. 수동으로 해결하는 도구는 다음 메시지 중에 있는 도구 중에서 고르면 됩니다.

$ git mergetool

This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge   araxis bc codecompare emerge vimdiff
No files need merging

리모트 브랜치 삭제

동료와 협업하기 위해 리모트 브랜치를 만들었다가 작업을 마치고 master 브랜치로 Merge 했다. 협업하는 데 사용했던 그 리모트 브랜치는 이제 더 이상 필요하지 않기에 삭제할 수 있다. git push 명령에 --delete 옵션을 사용하여 리모트 브랜치를 삭제할 수 있다. serverfix 라는 리모트 브랜치를 삭제하려면 아래와 같이 실행한다.

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

위 명령을 실행하면 서버에서 브랜치(즉 커밋을 가리키는 포인터) 하나가 사라진다. 서버에서 가비지 컬렉터가 동작하지 않는 한 데이터는 사라지지 않기 때문에 종종 의도치 않게 삭제한 경우에도 커밋한 데이터를 살릴 수 있다.

Visual Studio Code

vscode에서 새로운 프로젝트 만들어 깃에 커밋하기 전에 .gitignore 파일을 반드시 작성하고 node_modules 같은 폴더는 커밋하지 않도록 해야합니다.

미러링

외장하드에 미러링

포터블 깃 프로그램을 다운받아 압축해제하여 외장하드 d에 복사합니다.

d:\Programs\PortableGit

외장하드 d 드라이브에 Git 디렉토리와 mirrors 디렉토리를 만든다.

>d:
>mkdir Git
>cd Git
>mkdir mirrors

mirrors 디렉토리에 원격저장소 https://compmath.korea.ac.kr/gitlab/research/customer-manage.git를 미러링합니다.

>cd mirrors
>..\..\Programs\PortableGit\bin\git.exe clone --mirror https://compmath.korea.ac.kr/gitlab/research/customer-manage.git

새로운 업데이트가 있으면 원격저장소에서 가져옵니다.

>cd customer-manage
>git fetch origin

자동으로 원격저장소 미러링

gitRepos.txt
<DIR> mirrors
multi_mirrors.py
미러링방법.txt

getRepos.txt 파일은 다음과 같습니다.

https://compmath.korea.ac.kr/gitlab/research/customer-manage.git
https://compmath.korea.ac.kr/gitlab/research/customer_manage_mobile.git
https://compmath.korea.ac.kr/gitlab/dyoon/krank.git
https://compmath.korea.ac.kr/gitlab/react-native/gps-example.git
https://compmath.korea.ac.kr/gitlab/react-native/learning-rn.git
https://compmath.korea.ac.kr/gitlab/react-native/labor-management.git
https://compmath.korea.ac.kr/gitlab/web-programming/labor-management.git
https://compmath.korea.ac.kr/gitlab/dyoon/shuttle-dining.git
https://compmath.korea.ac.kr/gitlab/web-programming/cat-blog.git
https://compmath.korea.ac.kr/gitlab/web-programming/shuttle-korail.git
https://compmath.korea.ac.kr/gitlab/html-css/html-css-6step-ebisucom.git
https://compmath.korea.ac.kr/gitlab/courses/industrial-math/summer-2018/customer-management.git

multi_mirrors.py 파일은 다음과 같습니다.

import os
import glob

cmd_loc = '..\\..\\Programs\PortableGit\\bin\\git.exe'
existing_repos = [f for f in os.listdir('mirrors')]
git_cmd = os.path.abspath(cmd_loc)

with open('gitRepos.txt', 'r') as f:
  repos = f.read().splitlines()
  for repo in repos:
    _, file = os.path.split(repo)

    if (file not in existing_repos):
      print('mirroring the repo ' + file + ' ...')
      cmd = 'cd mirrors && ' + git_cmd + ' clone --mirror ' + repo
      #print(cmd)
      os.system(cmd)
    else:
      print(file + ' is already existing. now updating.')
      cmd = 'cd mirrors\\' + file + ' && ' + git_cmd + ' fetch origin'
      print(cmd)
      os.system(cmd)

참조 사이트

[1]깃 브랜치란 무엇인가? https://git-scm.com/book/ko/v2/Git-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80
[2]깃 브랜치와 리모트 브랜치 https://git-scm.com/book/ko/v2/Git-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EB%A6%AC%EB%AA%A8%ED%8A%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98