[OSS] Git/GitHub 기본

2020. 7. 18. 13:07Git

실습 준비:

1) 깃허브 회원가입

2) 구름 io 회원가입

실습자료 링크 : bitly.kr/QaVcr4cS3pL

 

오픈소스 참여를 위한 Git / GitHub 기본

1 오픈소스 참여를 위한 Git/GitHub 기본실습 리얼리눅스 송태웅

docs.google.com


1.  Commit 이란?


2. Fork & clone

Git clone 
1. Fork 부터 진행.

# Commit 이란 : 소스파일의 변화분. 변화된 내용이 정리가 되어서 
# Fork : GitHub 상에서 복사를 하는 것. (Push 권한 없고, local 환경 사라질 수 도 있어서)
#( forked from pytorch/pytorch)
# Clone : 다운로드

# 복사를해서 다운로드 받는게 정석.
# 오픈소스 pytorch example 준비
git clone https://github.com/[본인 GitHub ID]/[받을 깃]pytorch-example.git [받을폴더명]
mv pytorch-example examples
cd examples/
# pytorch MNIST 테스트 폴더 확인하기
cd mnist
cat README.md
# Read me 를 읽으면 어떻게 실행하는지 알려줌
Cat README.md
# Basic MNIST Example

```bash
pip install -r requirements.txt
python main.py
# CUDA_VISIBLE_DEVICES=2 python main.py  # to specify GPU id to ex. 2  
```

3. 개발자가 오픈소스를 읽는 방법

소스코드가 변화된 History 가 많이 있다.

단순히 Compile 하는 것에 그치지 말자.

  • 오픈소스 코드를 파악해본다.
  • 누가 참여하고 누가 많이 기여했지?
git shortlog
# 해당 오픈소스에서 "누가 제일 개발을 많이할까 ?"
# 참고: nl 명령은 파일의 line number 명시 (순위표시용으로 사용)
$ git shortlog -sn | nl

git shortlog -h (help 명령어)
# git shortlog -s 옵션 이란 ? "개발자별 commit 개수 요약 "
$ git shortlog -h | grep summary
    -s, --summary         Suppress commit descriptions, only provides commit count  

# git shortlog -n 옵션이란 ? "개발자별 commit 개수 순위 정리"
$ git shortlog -h | grep number
    -n, --numbered        sort output according to the number of commits per author
Merge Commit , 합치느라 쌓인 빈 커밋 확인
git shortlog -sn --no-merges | nl | less
#(머지커밋이 쌓이는거. 합치느라 생긴 빈 커밋)
# 수정 내역을 살펴 볼때는 머지 커밋이 필요 없을 수도 있다.

 

3-1. 전체 수정 내역 개수로 확인하기

 

git log -p : 수정내역 보기
# 전체 소스파일 수정내역(commit) 자세히 보기
$ git log -p

 

수정내역 개수 세기
# 전체 소스파일 수정내역(commit) 개수 세기 
$ git log --oneline | wc -l

# (참고: wc -l 명령은 (파일) 라인수 개수 측정)  

 

수정내역 리스트
# 전체 소스파일 수정내역(commit) 리스트     
$ git log --oneline

# 참고: 'q' 키 눌러서 나가기

수정내역 확인하기
# 수정 내역 확인하기
$ git show [6c8e2ba] 
#          (CommitID) SHA1 Hash 값이다
'''
소스코드가 어떻게 변화 되었는지 확인
'''

# diff 변화된거
# 소스가 수정 될 떄 마다 diff

 수정한 파일 개수 세기
# 해당 commit의 수정한 파일 개수 확인
$ git show 6c8e2ba | grep "diff --git" | wc -l
4

 

머지커밋 (Merge pull request)

머지가 되었다 라고만 되어있지, 파일에 대한 수정 내역은 없음

 

 


- 특정 폴더/파일 기준 변경
$ git log --oneline -- mnist/
# online 뒤에 -- 옵션을 붙여주면 ,특정 파일이나 폴더 기준으로 commit(수정)내역을 확인할 수 있다

 

-특정 날짜 기준 변경
# 2020년 1월 부터 2020년 6월 30일까지 소스 수정내역(commit) 리스트 확인  
$ git log --oneline --after=2020-01-01 --before=2020-06-30

 

-최초커밋 볼 때 : --reverse option을 넣어준다.
# 소스파일 수정내역(commit) 옛날것부터 살펴보기  
$ git log --reverse

4. 오픈소스 개발 참여 준비를 위한 Git 설정

  •  노트북을 쓰면서 계정이 2개 이상인 경우 계정 충돌이 생길 수 있다.
  •  이럴 때는 캐싱데이터(미리 읽어놓은 데이터) 를 제거
# GitHub ID/PW 캐싱데이터 삭제 (삭제시 문제없음)
# 다른(사람) GitHub 계정과의 충돌방지
$ git config --global --unset credential.helper
$ git config --system --unset credential.helper

# GitHub 계정 이메일 주소 및 본인영문이름
# 차후 소스코드 파일수정 내역(commit) 저자(author)정보  
$ git config --global user.email "본인메일적으세요"
$ git config --global user.name "본인이름적으세요"

 

  •  커밋을 한다는것은 수정한 것이고. 저자 정보를 남겨야함. 그래서 필요.
# Git commit(소스파일 수정내역) message(설명글) 수정할 기본 편집기 설정 
# 원하는 편집기 설정가능 (vim, emacs, nano, notepad 등)
$ git config --global core.editor nano

# nano 편집기 사용시 설치 필요
$ sudo apt install -y nano

 

# Git 설정 내용 확인하기
# 참고: Git 설정수정은 이전 실습명령 동일하게 입력시 수정  
$ git config --list

 


5. Commit 작업 

5-1. Branch 생성

- Branch란?
:같은 폴더 다른 세상. 개발을 하다 보면 내가 하던 작업을 안전하게 백업.

# 오픈소스 프로젝트 폴더로 이동
$ cd /workspace/pytorch/examples/

# Branch 생성
# 작업내용을 대표하는 키워드로 Branch 명 생성추전  
$ git checkout -b fix-mnist  
# "같은 폴더 다른세상" 브랜치 테스트
$ touch hello.txt

# 새롭게 생성한 fix-mnist 브랜치에서
# 새로운 파일 hello.txt 수정내역(commit) 만들기
$ git add hello.txt
$ git commit -m "test: add hello.txt file"  
  • Checkout >> add >> commit
# 브랜치를 master 브랜치로 변경
$ git checkout master

# 같은 폴더내 파일 내용확인하기
# hello.txt 파일 존재여부 확인
$ ls

# 브랜치 fix-mnist 로 변경 후
# hello.txt 파일 존재여부 확인
$ git checkout fix-mnist

# 다시 master 브랜치로 변경후 확인
$ git checkout master
$ ls 
  • Git 이 SVN 보다 브랜치 전환이 빠름

5-2. Brach 삭제

# Branch 삭제  
$ git branch -D fix-mnist     

6. 상태 확인하기

git status
On branch master  # 현재 브랜치
Your branch is up to date with 'origin/master'.  

# Commit 상태
nothing to commit, working tree clean  
  • nothing to commit : 수정할 것이 없다. == 역사관리가 잘 되어있고 클린한 상태.

7. 소스파일 수정

  • 먼저 파일 수정을 한다.
#변경후
git diff

 

git diff 내용
diff --git a/mnist/main.py b/mnist/main.py
index 7d7899d..1bee55c 100644
--- a/mnist/main.py
+++ b/mnist/main.py
@@ -77,7 +77,7 @@ def main():
     parser.add_argument('--test-batch-size', type=int, default=1000, metavar='N',  
                         help='input batch size for testing (default: 1000)')
     parser.add_argument('--epochs', type=int, default=14, metavar='N',
-                        help='number of epochs to train (default: 10)')
+                        help='number of epochs to train (default: 14)')
     parser.add_argument('--lr', type=float, default=1.0, metavar='LR',
                         help='learning rate (default: 1.0)')
     parser.add_argument('--gamma', type=float, default=0.7, metavar='M',

8. 소스파일 수정 후 커밋하기

# 소스 수정내역(commit) 만들기 준비
$ git add mnist/main.py
# Commit 할 준비완료 상태 확인
$ git status
'''
On branch fix-mnist
Changes to be committed:  // to be committed 는 아직 변경이 안되었다는 것을 말함.
  (use "git reset HEAD <file>..." to unstage)  

        modified:   mnist/main.py
'''
# Git commit(수정내역) 만들고
# commit을 만든 이유 작성:
# help 내용 안에 잘못된 default 값 수정했다는 설명 적기
$ git commit -m "Correct typo in default value within help"  

# 내가 작성한 commit 확인하기
$ git show

# 참고: 'q' 키 누르고 나가기

  • add >> commit

9. Push 하기

  • Push : Commit  한것 을 Fork에 제출 하기
# 나의 작업 브랜치 fix-mnist 확인하기
$ git branch

# 내가 작성한 2개의 commit 을
# 나의 Fork 저장소 GitHub 에 업로드해서 
# 내가만든 수정내역(commit) 제출(pull-request) 준비하기  
$ git push origin fix-mnist
#[fix-mnist] 제가 만든 브랜치 입니다. 자기가 만든 브랜치에 push 합니다

  • ID/PW를 입력하고 Push

10. Pull Request 하기

  • Pull-request :  땡겨오는 것을 요청. 게시판에 올라감
    - github만의 기능
    - 코드를 제출 하는 것은 깃허브를 거쳐서 제출
Fork한 자신의 Github에서 New Pull Request 생성

  • origin : 백업만 하는 것 (fork 한 곳에)
  • upstream : 공식에 업로드 하는거

11. Git 명령어

git 상태 확인하기
# 수정한 파일 확인하기
$ git status

 


수정 내용 확인
# 수정한 내용 확인하기 
$ git diff
diff --git a/mnist/main.py b/mnist/main.py
index 166231a..6a9607a 100644
--- a/mnist/main.py
+++ b/mnist/main.py
@@ -6,7 +6,7 @@ import torch.nn.functional as F  
 import torch.optim as optim
 from torchvision import datasets, transforms
 from torch.optim.lr_scheduler import StepLR
-
+import json

 class Net(nn.Module):
     def __init__(self):

잠깐 임시 저장 하는 방법 (Stach : 밀어버리지 않음) (저장함)
# 수정한 내용 잠시 저장(stash) 하기
$ git stash

# 현재 소스폴더 상태 확인하기: 아무 수정분 없음을 확인 
$ git status

# 잠시 저장(stash)해둔 내용 복구
$ git stash pop

# 복구된 수정한 파일 확인하기
$ git status


파일 복구하기
# 파일 수정한 내용 최신역사를 기준으로 복구하기
# checkout 의미 local git 저장소 에서 "가져오다 / 대출받다" 의미   
$ git checkout -- mnist/main.py

# 최신역사 기준으로 파일내용 복구 후 내용 확인
$ git diff
$ nano mnist/main.py

  • .git이 역사도서관이야
  • checkout 하면 도서관에서 책 빌리는거.
  • Check out : 최신 역사를 기준으로 가져온다 (밀어버림)

Commit Add 취소하기

git reset 하면 add로 commit 하기 전에 준비를 추가한 것을 지워버린다. (취소하기)

git reset


Commit 삭제하기

- 준비단계

# 수정한 내용 기준으로 commit 할 준비하기  
$ git add mnist/main.py

# commit 만들기
$ git commit -m "Add import json"

# 생성한 commit 정보 확인하기
$ git show
$ git log --oneline -1

- 삭제단계

# commit 정보 삭제하기
# 참고: HEAD~1 은 가장 위에서 첫번째 내용을 삭제한다는 의미  
$ git reset --hard HEAD~1

# 삭제 후 가장 최신 commit 확인하기
$ git log --oneline -1

 


License Signature 적기 (서명)
  • Signed-off-by는 내가 License를 이해하고 했다 라는 서명(인증)
  • Author랑 다른 겁니다. 법적인 문제에 휘말렸을때.
# 수정한 내용 기준으로 commit 할 준비하기  
$ git add mnist/main.py

# commit 만들기
# -s 옵션 포함시 라이센스 서명을 의미하는 Signed-off-by 내용을  
# commit message 안에 포함하게 된다.
$ git commit -sm "Add import requests"

# commit message 안에 Signed-off-by 확인
$ git show

 


Commit 수정하기 amend
  • 수정을 하는데, commit을 더 올리고 싶지 않을 때. 최신 history 상태에서 수정을 한다.

준비단계

 

# 최신 commit 수정이전 commit ID 확인하기
$ git log --oneline -1
106d167 (HEAD -> fix-mnist) Add import requests  

# 수정한 내용 commit 할 준비 하기
$ git add mnist/main.py

 

Amend 단계

# 최신 commit 수정하기
$ git commit --amend

# 최신 commit 수정 이후 commit ID 확인하기
$ git log --oneline -1
9786c82 (HEAD -> fix-mnist) Add import requests
  • Add >> Amend

Upstream 설정 / 오픈소스 작업소
  • 리모트가 2개 있는거.
  • 오리진 뿐만 아니라 업스트림도 같이 잇는거. 중요한거죠.
  • Origin : 포크를 뜬거
  • Upstream : 오픈소스작업
# 오픈소스 공식 GitHub 프로젝트 URL
# upstream 으로 등록 하기
$ git remote add upstream https://github.com/taeung/pytorch-example

# origin: 나의 Fork 저장소 GitHub URL
# upstream: 오픈소스 공식 GitHub URL (또는 팀프로젝트 URL)
$ git remote -v
origin  https://github.com/gentlelinuxer/pytorch-example.git (fetch  
origin  https://github.com/gentlelinuxer/pytorch-example.git (push)
upstream        https://github.com/taeung/pytorch-example (fetch)
upstream        https://github.com/taeung/pytorch-example (push)


 

Rebase : Base 교체하기, Base Update

 

  • Fork를 다시 뜨고 하는게 아니라, 베이스를 교체해주는걸로 할 수 있음 (ReBase)
    (다른사람꺼가 먼저 Merge가 되는 바람에. base만 다시 교체해라)
# 공식 upstream 저장소에서 최신 commit history 가져오기    
$ git fetch upstream master

# 최신 commit history 기준으로 베이스 갱신 (rebase)
$ git rebase upstream/master

# Fork 한 저장소(GitHub)도 수정하기 (PR 자동 갱신) 
$ git push --force origin fix-mnist

  • 업스트림을 가져오면 /가 들어간것이 명칭임.
  • 'upstream/master' 라는 로컬 branch가 생성됨.

 

1. 이 때 첫번째로 하는 것은 fetch 입니다.

Fetch + Merge == Pull

Pull은 하는 순간 바로 Merge가 된다.

Fetch와 Pull의 차이점

  • Fetch
 - 단순히 원격 저장소의 내용을 확인만 하고 로컬 데이터와 병합은 하고 싶지 않을 경우 사용
 - 원격 저장소의 최신 이력 화인 가능
  • Merge

 

- 원격 저장소의 변경사항을 가져와 로컬에 병합한다.

 

 

2. force push : 뿌리(base) 가 바뀌는 경우.
(force push의 경우 pull-request가 자동으로 갱신된다.  PR 내용은 똑같지만, 베이스가 달라졌기 때문에.)


 

Rebase 해서 Commit 수정하기

[하는이유]

  • Amend는 가장 최신 Commit만 수정이 가능하다
  • 이전의  Commit을 수정하기 위함

[감고 풀기]

1. rewind : 임시적으로 되감고 

2. amend : commit 살살 녹여내고

3. continue : 감은것을 풀고

 

[준비하기]

# Rebase 실습할 GitHub 저장소 소스폴더 다운받고 이동
$ cd /workspace
$ git clone https://github.com/taeung/git-training 
$ cd git-training

[Rebase하기]

: rebase할 commit의 pick 을 edit으로 수정
# 참고: --root 대신 최신 commit 기준으로 HEAD~10 10개중에서 선택도 가능하다 

# 가장 오래된 commit 두번째로 되감기 
# 두번째로 가장 오래된 commit 의 "pick" 글자를 "edit" 으로 수정하기
# nano 편집기 저장: ctrl + o 
# nano 편집기 나가기: ctrl + x
$ git rebase -i --root

# 참고: --root 대신 최신 commit 기준으로 HEAD~10 10개중에서 선택도 가능하다 

[Rebase 확인]

# 되감기(rewind) 한 commit 리스트 확인하기
$ git log --oneline

# rebase interactive 상태 (되감은 상태) 확인
$ git status

[Commit 수정 - Amend]

# hello.txt 빈파일 생성 및 commit 준비
$ touch hello.txt.
$ git add hello.txt

# commit message 를 수정하기
# Add knapsack problem PDF and hello.txt
$ git commit --amend
# ammend는 수정하는 것.

[Continue : 풀기]

# 되감은 내용 풀기(continue)
$ git rebase --continue

# commit 수정 결과 확인하기
$ git log --oneline

# 2번째로 오래된 commit 에 해당되는 commit ID로  
# commit 내용 확인하기
$ git show "[commit ID]"

 


오픈소스 버전 비교하기

: 최신버전과 이전버전에서 파일명 및 파일의 경로가 다를 수 있다.

- 준비하기

# C/C++ 프로그램 함수호출 추적 오픈소스
# uftrace 프로젝트 다운로드
$ cd workspace/
$ git clone https://github.com/namhyung/uftrace  

# uftrace 폴더로 이동
$ cd uftrace/

- 버전 가져오기

# uftrace 버전 리스트 (태그) 가져오기
$ git fetch --tags

# uftrace 버전 확인
$ git tag

- 버전 변경하기

# v0.8 버전 (과거시점) 으로 현재 폴더 변경하기
$ git reset --hard v0.8

- 해당 버전에서 파일 보기

# 현재 폴더 에서 cmd-*.c 관련 파일 확인
# uftrace 의 서브명령인 record, replay 등에 대한 소스 파일 확인
$ ls
CONTRIBUTING.md  Makefile.include  arch         cmd-info.c    cmd-replay.c  doc            scripts    utils
COPYING          NEWS              check-deps   cmd-live.c    cmd-report.c  libmcount      tests
INSTALL.md       README.md         cmd-dump.c   cmd-record.c  cmd-script.c  libtraceevent  uftrace.c
Makefile         TODO              cmd-graph.c  cmd-recv.c    configure     misc           uftrace.h   

- 최신 버전의 파일 보기

# 다시 원본 GitHub 프로젝트 내용으로 현재 폴더 변경하기
$ git reset --hard origin/master

# cmds 폴더에서 uftrace 의 서브명령인 record, replay 등에 대한 소스 파일 확인
# 현재에는 cmds 폴더 내부에서 따로 소스파일을 관리하고 있다.
$ ls cmds
dump.c  graph.c  info.c  live.c  record.c  recv.c  replay.c  report.c  script.c  tui.c

 


특정 소스파일에서 line 기준으로 Commit 찾기
# 해당 소스파일을 누가 수정했고 언제 수정했는지
# 소스 라인 기준으로 commit 정보를 찾아 낼 수 있다.

$ git blame cmds/record.c
...
edf805aad cmd-record.c  (Taeung Song   2018-04-16 15:00:12 +0900  102)
edf805aad cmd-record.c  (Taeung Song   2018-04-16 15:00:12 +0900  103)  if (opts->nop) { 
...

# 103 번째 라인은 누가 수정했고 언제 수정했는지 왜 수정했는지
# commit 정보를 확인 할 수 있다. (참고: blame은 최신 commit 기준으로 보여준다)
$ git show edf805aad

'Git' 카테고리의 다른 글

[OSS] Git/GitHub 고급 실습  (0) 2020.07.18
[OSS] Git/GitHub 기본  (0) 2020.07.18