GPG sign off (서명 설정)


키 생성 및 export

#설치
apt install gpg2

# 생성 gpg 2.1 버전 이상부터 있는 옵션 full
gpg --full-gen-key # algorithm, bits, expire date, password를 순서대로 설정

# 생성 키 확인
gpg --list-secret-keys --keyid-format LONG <your_email>

sec   rsa4096/30F2B65B9246B6CA 2017-08-18 [SC]
      D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
uid                   [ultimate] Mr. Robot <your_email>
ssb   rsa4096/B7ABC0813E4028C0 2017-08-18 [E]

# 30F2B65B9246B6CA를 복사

# key export (ASCII-Armor 포멧의 gpg public key)
gpg --armor --export 30F2B65B9246B6CA

Gitlab과 Github 설정

Gitlab
export로 나온 --BEGIN부터 --END까지 전체를 복사한 후 gitlab -> preference -> GPG Kyes에 복사해서 붙여넣는다.

Github
SSH and GPG keys 설정에 삽입

Git 설정 (signed commit을 위한)

export때 사용했던 GPG Key ID를 입력 합니다. gpg --list-secret-keys --keyid-format LONG <your_email>명령어로 확인 가능

$ git config --global user.signingkey 30F2B65B9246B6CA

커밋 수행

git commit -S -s -m "commit message"
#-s는 단순 sign-off, 커밋 메시지에 sign-off 이력 삽입
#-S는 gpg sign-off

GPG 서명된 커밋 확인

git log --show-signature -1

세부 설정

매번 하기 귀찮으면 git config --global commit.gpgsign true 설정으로 -S 옵션 제거 가능.

비밀번호 입력 주기 재설정 (GPG 2.1 이상 버전)
~/.gnupg/gpg-agent.conf에 아래 내용 추가. 약 8시간 동안 키 입력을 받지 않음.

default-cache-ttl 28800
max-cache-ttl 28800

GPG 버전 설정
git config --global gpg.program gpg2

설정 확인
git config --global -l
스크린샷 2021-03-26 오전 11.21.40

Troubleshooting

error: gpg failed to sign the data

커밋시 아래 오류가 발생하면

error: gpg failed to sign the data
fatal: failed to write commit object

export GPG_TTY=$(tty)를 ~/.bashrc에 추가하고 source ~/.bashrc하여 적용

gpg: signing failed: Inappropriate ioctl for device오류도 동일하게 해결 가능.

스택오버플로우: https://stackoverflow.com/questions/39494631/gpg-failed-to-sign-the-data-fatal-failed-to-write-commit-object-git-2-10-0/42265848#42265848

key gen시 entropy 부분에서 넘어가지 않음

gpg --gen-key시 아래 메시지에서 더이상 넘어 가지 않을 경우. 유틸을 설치한다.
적절한 마우스 움직임이나 디스크 사용으로 entropy를 증가시켜 임의성을 증가시키면 원래는 난수 기반 키가 나와야 하지만 멈춤(hangs)도 자주 발생한다.

We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy.

apt install rng-tools
service rngd start

스택오버플로우: https://serverfault.com/questions/471412/gpg-gen-key-hangs-at-gaining-enough-entropy-on-centos-6

IntelliJ IDE 관련

https://blog.kshgroup.kr/intellij-signed-commit-gpg-error/

참고자료

git difftool 사용법


git mergetool로 병합을 수행할 시 conflict문제가 발생하면 아래와 같이 해결한다.

git difftool 설정

git config --global diff.tool vimdiff
git config --global difftool.prompt false
git config --global alias.d difftool

vimdiff 사용법

리눅스에서 두 파일을 비교하는 명령어인 vimdiff의 간단한 사용법을 말씀 드리겠습니다.
기본적으로 vimdiff는 vim에서 화면을 분할하고, 두 파일을 열었을 상태와 같다고 보시면 됩니다.
추가적으로 좋은 점은 서로 다른 부분을 표시해주는 부분이죠.
두 파일을 비교하고, 병합하는데 사용할 수 있습니다.

우선 분할된 창에서 다른 창으로 이동하는 명령은 Ctrl + w + w입니다.

차이점이 있는 부분으로 이동하는 명령은 ] + c  [ + c 입니다.
] + c는 현재 위치에서 아래쪽으로 탐색하며,
[ + c는 현재 위치에서 위쪽으로 탐색을 진행합니다.

수정을 원하는 부분을 찾았으면 복사를 해야겠지요.
d + o는 현재 위치에 반대쪽 창의 내용을 복사해 옵니다.
d + p는 현재 위치의 내용을 반대쪽 창에 복사합니다.

vimdiff는 동일한 부분은 생략하여 보여줍니다.
이를 펼치기 위해서는 z + o 또는 z + space를 누르면 됩니다.
반대로 접기 위해서는 z + c를 누르면 됩니다.

마지막으로, 한쪽 창의 내용을 편집하다보면 차이점을 나타내는 표시가 없어질 경우가 있습니다.
이때 :diffupdate를 누르시면 다시 비교하여, 차이점을 표시해 줍니다.

참고 자료

https://www.rosipov.com/blog/use-vimdiff-as-git-mergetool/


GIT tip 정리


충돌 회피

git push 충돌 회피

# git pull시 현재 commit하지 않은 것 때문에 충돌이 발생하면 아래와 같이 stash를 이용해서 임시저장 할 수 있다.
git stash
git stash list
git pull
git stash pop

submodule

가장 처음 실행 했을 때

git submodule update --init --recursive

지속적인 업데이트

git submodule update --recursive

상태 확인

git submodule status

변경 사항 있을 때 강제로 원래대로 돌리기

git submodule update -f --init --recursive

Git stash

branch를 변경할 때 임시로 파일을 저장하는 수단.

# 임시 저장
git stash
# 임시저장 리스트 확인
git stash list
# 임시저장 적용하고 바로 stage 상태로 만듬
git stash apply --index
# 임시저장 제거, hash를 지정하지 않으면 가장 최근 것을 제거함.
git stash drop
# 적용하면서 바로 제거함
git stash pop

파일 삭제

git rm

working directory의 실제 파일을 삭제하는 것이다.
그리고 commit을 해야 한다.

git rm --cached

Staging Area (git index)에서만 제거하고 Working directory에 있는 파일은 지우지 않고 남겨둘 수 있다.
다시 말해서 하드 디스크에 있는 파일은 그대로 두고 Git만 추적하지 않게 한다.

이것은 .gitignore파일에 추가하는것을 빼먹었거나 대용량 로그 파일이나 컴파일된 파일 .a파일 같은 것을 실수로 추가 했을 때 쓴다.

$ git rm --cached readme.txt

#여러게 삭제
$ git rm log/\*.log

rm.txt 파일 생성해서 하기
*명령으로는 이름 매칭이 안될 수도 있다.

  • git status > rm.txt형식으로 list를 만들고 파일명을 다듬은 다음
  • cat rm.txt | xargs git rm --cached으로 해당 txt에 있는것을 staging area에서 제거 한다.

git log

  • checkout 하고 log가 안보이면 git log --all
  • git reflog

특정 파일 변화 로그 찾기

  • git log -p -- ./vta/tutorials/resnet.py
    파일 이름 바뀐것 까지 참조하면서 모두 보이기
  • git log --follow -p --

HEAD detached at

checkoutsha1 hash코드로 하게 되면 자동으로 HEAD가 설정 되지 않는다.
branch 이름으로 할 경우 이런 문제가 발생하지 않지만 그냥 할 경우 발생하게 된다.

commit message를 잃어 버릴 수도 있기 때문에 HEAD 설정을 다시 해주는 것이 좋다.

  • merge를 이용한 방법
    git commit -m "....."
    git branch my-temporary-work
    git checkout master
    git merge my-temporary-work

git diff

기본 설정 포멧

git diff [--options] <commit> <commit> [--] [<path>...]

지금 커밋과 뒤로 두 단계 커밋의 main.c에 대한 비교 커멘드는 아래 3개 모두 동일한 기능을 한다.

$ git diff HEAD^^ HEAD main.c
$ git diff HEAD^^..HEAD -- main.c
$ git diff HEAD~2 HEAD -- main.c

remote하고의 비교

git fetch origin #pull과 다르게 local repo.와 merge하지 않음. 이력만 받아옴.
git diff master origin/master

특정 파일만 보고 싶은 경우

git ls-files | grep .java | xargs git diff

간단히 파일 변화만 보기 --state

$ git diff --stat 2ed6ec *.R

 2018_03_09_NB_SVM_RF_MLP.R       | 314 +++++++++++++++++++++++++++++++
 Class Imbalance.R                |  90 +++++++++
 FeatureSelectionWithRFE.R        |  59 ++++++
 FileWriter.R                     |  93 ++++++++++
 evaluationModel.R                |  38 ++++
 graph.R                          | 188 +++++++++++++++++++
 jsonESLABCollector.R             | 116 ++++++------
 jsonToDataFrame.R                | 385 +++++++++++++++++++++++++++++++++++++++
 jsonToSingleDataFrame.R          | 208 +++++++++++++++++++++
 phone_status_anlysis.R           |  41 ++++-
 post_matchig_with_arrival_time.R | 277 ++++++++++++++++++++++++++++
 refinedAutoLabels.R              | 158 ++++++++++++++++
 12 files changed, 1905 insertions(+), 62 deletions(-)

git 무식하게 완전 초기화

rm -rf .git

git init
git add .
git commit - m "initial commit"

git remote add origin <github-uri>
git push -u --force origin --all

단 위 방법은 submodule이 있을 경우 문제가 발생한다.
그 때는 rebase를 이용해서 정공법으로 해결해야 한다.

Branch 관련

Branch 삭제

#local delete
git branch -d <branch_name>

#remote delete
git push <remote_name> :<branch_name>

Branch 이름 변경

# Local에 있는 branch 이름 변경하기
git branch -m oldbranch newbranch

# Remote에 존재하는 oldbranch 삭제하기
git push origin :oldbranch

# newbranch push 하기
git push origin newbranch

파일 복원

파일 변경 사항 알아내기

특정 파일 변동 사항 검색

git log -- UNLOCKED_Analysis.R

해당 로그 확인

$ git show --stat f27a8d
commit f27a8d01f6fa828d4e38919823fb1ddb462136b6
Author: Jemin Lee <leejaymin@cnu.ac.kr>
Date:   Tue Nov 8 23:50:22 2016 +0900

    change file name

 README.md                                  | 17 +++++++++++++++++
 jsonToDataFrame.R                          |  9 +++++++++
 phone_status_anlysis.R                     |  1 +
 UNLOCKED_Analysis.R => refinedAutoLabels.R |  4 +++-
 4 files changed, 30 insertions(+), 1 deletion(-)

위와 같이 UNLOCKED_Analysis.R파일이 refinedAutoLabels.R로 변경된 것을 알 수 있다.
갑자기 파일이 사라져서 log를 통해서 확인해본 예제이다.

개별파일 원복

git checkout -- <파일> : 워킹트리의 수정된 파일을 index에 있는 것으로 원복
git checkout HEAD -- <파일명> : 워킹트리의 수정된 파일을 HEAD에 있는 것으로 원복(이 경우 --는 생략가능)
git checkout FETCH_HEAD -- <파일명> : 워킹트리의 수정된 파일의 내용을 FETCH_HEAD에 있는 것으로 원복? merge?(이 경우 --는 생략가능)

index 추가 취소

git reset -- <파일명> : 해당 파일을 index에 추가한 것을 취소(unstage). 워킹트리의 변경내용은 보존됨. (--mixed 가 default)
git reset HEAD <파일명> : 위와 동일

특정 commit message에서 복원
$ git checkout ec76bc~1 allData.RData

commit 취소

  • git reset HEAD^ : 최종 커밋을 취소. 워킹트리는 보존됨. (커밋은 했으나 push하지 않은 경우 유용)
  • git reset HEAD~2 : 마지막 2개의 커밋을 취소. 워킹트리는 보존됨.

hard, soft, mixed 차이점

  • git reset --hard HEAD~2
    • 마지막 2개의 커밋을 취소. stage와 워킹트리 모두 원상 복구. 즉 모든 상태가 복구됨.
  • --soft:
    • stage에 올라간 상태로 변경이력이 복구됨
  • --mixed;
    • 워킹트리에만 변경사항이 남아있음. 커밋은 완전 초기화

revert 방식
reset 계열은 결국 커밋을 조작 하기 때문에 혼자 사용하는 branch에서 사용하는것이 적당하다.
여럿이 사용하는 branch라면 revert를 이용해서 이력을 rollback한 내용들도 commit으로 남기는 것이 좋다.

  • git revert HEAD : HEAD에서 변경한 내역을 취소하는 새로운 커밋 발행(undo commit). (커밋을 이미 push 해버린 경우 유용)
    • 취소 커밋 범위 설정 가: git revert [hash1]..[hashN]

워킹트리 전체 원복

git reset --hard HEAD : 워킹트리 전체를 마지막 커밋 상태로 되돌림. 마지막 커밋이후의 워킹트리와 index의 수정사항 모두 사라짐.
(변경을 커밋하지 않았다면 유용)
git checkout HEAD . : ??? 워킹트리의 모든 수정된 파일의 내용을 HEAD로 원복.
git checkout -f : 변경된 파일들을 HEAD로 모두 원복(아직 커밋하지 않은 워킹트리와 index 의 수정사항 모두 사라짐. 신규추가 파일 제외)

* 참조 : reset 옵션

--soft : index 보존, 워킹트리 보존. 즉 모두 보존.
--mixed : index 취소, 워킹트리만 보존 (기본 옵션)
--hard : index 취소, 워킹트리 취소. 즉 모두 취소.

* untracked 파일 제거

git clean -f
git clean -f -d : 디렉토리까지 제거

Git tracked file 용량 파악 하기

git count-objects -vH

100MB 이상 파일 push 하기

100MB이상의 파일을 push 할 경우 아래와 같은 error 메시지를 나타낸다.

remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: Trace: a021e64e835a3163bc978f98da55335e
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File huge_files.zip is 151.37 MB; this exceeds GitHubs file size limit of 100.00 MB

large file system (lfs)를 설치하고 이를 이용해서 commit & push를 한다.

brew install git-lfs
git lfs install # you only need to run this once per user account
git lfs track "*.psd" # Git LFS selects the file types you would like.
git add .gitattributes # make sure .gitattributes is tracked.

git add file.psd
git commit -m "Add design file"
git push origin master

트랙킹 파일 리스트 확인: git lfs ls-files

Reference site

민감 파일 이력에서 자동 찾아 제거 (sensitive data remove in entire history)

.gitignore설정을 하지 않아 password와 같은 정보가 들어 있는 config 파일이 commit push 되었을 때 변경이력에서 이러한 부분을 제거하는 방법을 다룬다.

그냥 untacked시키는 방법은 git rm --cached를 사용하면 되나 저장소 history안에 해당 파일 변경 내역이 그대로 남기 때문에 문제는 계속된다.

해결방법으로는
git filter-branchBFG Repo-Cleaner를 이용한 방법 있다.

BFG Repo-Cleaner를 이용한 방법을 다룬다.

java -jar bfg-1.13.0.jar --delete-files <지울 파일 이름>
java -jar bfg-1.13.0.jar --replace-text <지울 파일 이름>
# 원격 저장소에 강제로 반영
git push origin --force --all

Git commit 메시지들 정리하기

Squash all commits (Pull Request 이후에 처리)

git checkout <branch-name>
git rebase -i master # interactive mode
# vim 화면에서 pick이 선택이고 s가 squash 한다는 의미가 된다.
# 그 다음 새로운 commit log를 작성하게 된다.


git push origin branch-name --force

PR이 다수 반영된 upstream 내용을 origin과 local에 반영하기

아래는 여러 방법들 중 하나의 것이다.

git checkout master
git fetch upstream
git rebase upstream/master
git push -f origin master

기존 local branch 삭제

git branch -d <branch name>

참고자료
공식 홈피: https://help.github.com/en/articles/removing-sensitive-data-from-a-repository
BFG: https://rtyley.github.io/bfg-repo-cleaner/

Gitlab, Merge-request fetch 방법

vi ~/.gitconfig
# 추가
[alias]
    mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' -

# fetch and checkout.
# specify mr number in the last
git mr origin 5

또는
git fetch origin merge-requests/58/head:relay_mr

참고자료

참고자료

2.2 Git의 기초 - 수정하고 저장소에 저장하기

자동으로 commit 위치 찾아서 Git으로 지운 파일 복원하기


버전관리 시스템을 쓰는 이유중 하나가 실수로 지워진 파일을 복원하거나
예전에 필요 없다고 지운 파일을 손쉽게 복원하기 위해서이다.

문제는 commit이 많이 누적 됬다면 해당 파일이 존재하는 위치를 찾는것은 꽤나 귀찮은 일이 된다.
이러한 부분 쉽게 검색으로 해결하는 방법을 다룬다.

특정 경로에 관련된 commit을 찾는 명령어
맨 처음부터 HEAD까지 전부 검색한다는 의미이다.
git rev-list -n 1 HEAD -- <file_path>

git rev-list -n 1 HEAD -- ./0.Basic

f75de024ee267c765d8abfea460ac5f5c506b015

해당 commit 바로 이전으로 checkout하는 방법 caret^을 넣으면 된다.
git checkout <deleting_commit>^ -- <file_path>

git checkout f75de0^ -- ./0.Basic

# 정상적으로 복원됨
jemin@jemin-desktop:~/ESLAB_ML/jemin/TensorFlowLecture$ git status
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.
커밋할 변경 사항:
  (스테이지 해제하려면 "git reset HEAD <파일>..."을 사용하십시오)

        새 파일:       0.Basic/Basic_usageOfConstant.py
        새 파일:       0.Basic/Basic_usageOfPlaceholder.py
        새 파일:       0.Basic/Basic_usageOfVariables.py
        새 파일:       0.Basic/TensorFlow Basic of concept.ipynb
        새 파일:       0.Basic/__init__.py
        새 파일:       0.Basic/basic.py
        새 파일:       0.Basic/hellowTensorFlow.py

특정 파일 1개만 하고 싶을 경우
git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"


Git config 설정 (계정설정)


기본 개념

Git을 설치하고 나면 Git의 사용 환경을 적절하게 설정해 주어야 한다. 한 번만 설정하면 된다. 설정한 내용은 Git을 업그레이드해도 유지된다. 언제든지 다시 바꿀 수 있는 명령어가 있다.

  • git config라는 도구로 설정 내용을 확인하고 변경할 수 있다. Git은 이 설정에 따라 동작한다. 이때 사용하는 설정 파일은 세 가지나 된다.
  • /etc/gitconfig 파일: 시스템의 모든 사용자와 모든 저장소에 적용되는 설정이다. git config --system 옵션으로 이 파일을 읽고 쓸 수 있다.
  • ~/.gitconfig 파일: 특정 사용자에게만 적용되는 설정이다. git config --global 옵션으로 이 파일을 읽고 쓸 수 있다. .git/config: 이 파일은 Git 디렉토리에 있고 특정 저장소(혹은 현재 작업 중인 프로젝트)에만 적용된다. 각 설정은 역순으로 우선시 된다. 그래서 .git/config가 /etc/gitconfig보다 우선한다.

윈도용 Git은 $HOME 디렉토리(%USERPROFILE% 환경변수)에 있는 .gitconfig 파일을 찾는다. 보통 C:\Documents and Settings\$USER 또는 C:\Users\$USER 이다(윈도우에서는 $USER 대신 %USERNAME%를 사용한다). 그리고 msysGit도 /etc/gitconfig를 가지고 있다. 경로는 MSys 루트에 따른 상대 경로다. 인스톨러로 msysGit을 설치할 때 설치 경로를 선택할 수 있다.

계정 설정

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

프로젝트 마다 다른 Email을 사용하고 싶으면 --global 옵션을 제거하면 된다.

설정 확인

$ git config --list
user.name=Scott Chacon
user.email=schacon@gmail.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto


Github에 100Mb이상 파일 올리는 방법 (오류 해결)


필자의경우 Bitbucket에서 사용하던 Project를 Github로 옴기려고 하다보니 이와 같은 에러가 발생 했다. Github의 경우 개당 파일은 100MB제한이고 있지만 전체 용량 제한은 없다.
Bitbucket은 개당 파일의 제한은 없지만 전체용량이 2GB이상이 안되는 제한사항이 존재 한다.

Github의 경우 50Mb는 Warning을 표시하며, 100Mb부터는 Error를 나타낸다.
따라서 이 이상의 파일을 Push하려하면 아래와 같은 에러를 발생 시킨다.
Github Policy

에러

root@ubuntu:~/python_source/AutoTestingModule# git push github --all
Username: 
Password: 
Counting objects: 40223, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (26581/26581), done.
Writing objects: 100% (40223/40223), 582.06 MiB | 7.94 MiB/s, done.
Total 40223 (delta 12516), reused 40162 (delta 12503)
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
remote: error: Trace: b052327128727acb5dc9e1fed5cdbb8f
remote: error: See http://git.io/iEPt8g for more information.
remote: error: File TestingResult.tar.gz is 111.47 MB; this exceeds GitHub's file size limit of 100.00 MB
root@ubuntu:~/python_source/AutoTestingModule# git log b05232
fatal: ambiguous argument 'b05232': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

위 에러 메시지는 HEAD에는 100MB 이상의 파일은 없다.
즉 최근 commit이나 현재 Directory에는 100MB 이상의 파일이 존재하지 않는다. 
하지만 이전 Commit에서라도 100MB이상의 파일이 존재한다면 이러한 에어를 발생 시킨다.
필자의 경우도 TestingResult.tar.gz의 경우 이전에 만들어 두었던 BackUp 파일 하나가 변경이력에 들어가서 문제가된 것이다.

해결방법

경고 메시지에도 나와 있듯이 몇가지 해주면 쉽게 해결이 가능하다.

1.git-lfs 이용

https://git-lfs.github.com/

2. BFG Repo-Cleaner 적용

https://rtyley.github.io/bfg-repo-cleaner/

필자의 경우 그냥 필요없는 파일이라 이전 이력을 뒤져서 제거하는 방법을 선택 했다.
위 공식 사이트에 가서 bfg-x.x.x.jar파일을 다운받고 아래처럼 실행하자.

실행 결과

root@ubuntu:~/python_source/AutoTestingModule# java -jar bfg-1.12.12.jar --strip-blobs-bigger-than 100M

Using repo : /root/python_source/AutoTestingModule/.git

Scanning packfile for large blobs: 40169
Scanning packfile for large blobs completed in 1,435 ms.
Found 1 blob ids for large blobs - biggest=116880364 smallest=116880364
Total size (unpacked)=116880364
Found 36035 objects to protect
Found 7 commit-pointing refs : HEAD, refs/heads/GUI, refs/heads/MultiRun, ...

Protected commits
-----------------

These are your protected commits, and so their contents will NOT be altered:

 * commit 034d2b0b (protected by 'HEAD')

Cleaning
--------

Found 52 commits
Cleaning commits:       100% (52/52)
Cleaning commits completed in 406 ms.

Updating 6 Refs
---------------

    Ref                            Before     After   
    --------------------------------------------------
    refs/heads/GUI               | bfec4c11 | ebffb517
    refs/heads/MultiRun          | 968de654 | d0fd0d5f
    refs/heads/master            | 034d2b0b | abe6ecc0
    refs/remotes/origin/GUI      | bfec4c11 | ebffb517
    refs/remotes/origin/MultiRun | 968de654 | d0fd0d5f
    refs/remotes/origin/master   | 034d2b0b | abe6ecc0

Updating references:    100% (6/6)
...Ref update completed in 262 ms.

Commit Tree-Dirt History
------------------------

    Earliest                                      Latest
    |                                                  |
    ......................DDDDDDDDmmmmmm.mmmmmmmmmmmmmmm

    D = dirty commits (file tree fixed)
    m = modified commits (commit message or parents changed)
    . = clean commits (no changes to file tree)

                            Before     After   
    -------------------------------------------
    First modified commit | 7a6c355c | c9286236
    Last dirty commit     | cb054c2b | 25d98799

Deleted files
-------------

    Filename               Git id             
    ------------------------------------------
    TestingResult.tar.gz | 4153149d (111.5 MB)


In total, 37 object ids were changed. Full details are logged here:

    /root/python_source/AutoTestingModule.bfg-report/2016-08-09/00-21-29

BFG run is complete! When ready, run: git reflog expire --expire=now --all && git gc --prune=now --aggressive


Has the BFG saved you time?  Support the BFG on BountySource:  https://j.mp/fund-bfg

위와 같이 이전 commit에서 빠르게 해당 파일을 찾아서 제거하고 commit메시지를 자동으로 바꾼것을 알 수 있다. 정말 편리한 유틸리티인것 같다.

이제 다시 Github repository에 PUSH를 시도해 보자.

root@ubuntu:~/python_source/AutoTestingModule# git push github --all
Username: 
Password: 
Counting objects: 40223, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (26589/26589), done.
Writing objects: 100% (40223/40223), 471.01 MiB | 8.80 MiB/s, done.
Total 40223 (delta 12516), reused 40126 (delta 12494)
To https://github.com/leejaymin/QDroid.git
 * [new branch]      GUI -> GUI
 * [new branch]      MultiRun -> MultiRun
 * [new branch]      master -> master
root@ubuntu:~/python_source/AutoTestingModule# 

참고문헌


Github Page로 개인 홈페이지 제작, Private Git 얻기


Private 공짜로 얻기

아랴의 링크에서 학생이라면 Github를 약 2년간 공짜로 Private 하게 사용할 수 있다.
지원 할 때는 반드시 University E-mail을 사용해서 지원 해야 한다.
https://education.github.com/pack

목적과 사유를 적어서 보내면 빠르면 2틀 늦어도 15일 이내로 아래와 같은 답장을 받을 수 있다.

목적과 사유는 길게 적을 필요 없다.
필자의 경우 한 3~4줄 영어로 적은것 같다.

GitHub에 로그인해서 Account를 확인해보면 아래와 같은 상태로 변경된 것을 알 수 있다.

2년간 지원해주고 unlimited private repositories를 보장한다.
2년이 지나고 또 메일을 보내면 해주는 것 같다.

Github page 제작

github pages란 static site hosting service를 말한다.

Github pages는 개인홈피, 조직 홈피 또는 project 페이지를 위해서 직접적으로 GitHub repository를 이용해서 디자인 되어 진다.

  • 2016년 6월 이후에 만들어진 page는 github.io domain으로 시작하게 된다.
  • 신용카드 정보 등의 senstive information은 허용하지 않는다.
  • page는 1달에 100,000 요청과 100GB 이하의 트래픽을 허용 한다.
  • 개인 repository의 용량은 1GB 미만을 허용 한다.
  • private repository라도 page자체는 public으로 접근이 가능 하다.

github page의 종류는 크게 두가지 이다.

  • personal page 제작
  • project page 제작

perosnal page 생성 방법

  1. 저장소 생성 반드시 <계정>.github.io 이름으로 생성 한다.

계정이 leejaymin라면, leejaymin.github.io으로 생성 해야한다.
계정 이름은 leejaymin인데 저장소 이름을 jemin.github.io이라고 하면 안된다.
github.io 이것도 전부 저장소 이름 만들때 넣어줘야한다.
당연하겠지만, 이러한 제약으로 인해서 perosnal page는 계정당 1개 뿐이 못만드는것이다.
따라서 project 마다 static web page를 생성하기 위해서는 따른 방법이 존재한다.

  1. 아래의 커맨드를 수행
git clone https://github.com/username/username.github.io
cd username.github.io
~$echo "Hello World" > index.html
git add --all
~$git commit -m "Initial commit"
~$git push -u origin master

http://username.github.io <-- 주소로 접속해보자. 당연히 username은 본인 계정이다.

404 not found같은 것이 뜨면 repository 이름이 잘못된 것이니 수정하면 된다.
setting으로 가서 저장소 이름을 변경하자.

정상적으로 잘 했다면 setting에 아래처럼 주소가 나와야한다.
주의사항을 보면 page는 저장소가 private 이어도 공개된다는 말이 나온다.
개인정보가 유출 되지 않도록 주의 하자.

마크다운으로 html 작업해서 index.html로 commit 후 push하면 심플한 이력 페이지가 된다.
최종 페이지: https://leejaymin.github.io/


나의 경우 보통 아래의 것들을 무시한다.


third party native library의 경우 .so를 무시하면 안된다.


NDK로써 본인이 직접 빌드하는거라면 무시하고 그렇지 않다면 모두 이력을 tracking 해야 한다.


# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# built native files (uncomment if you build your own)
# *.o
# *.so

# generated files
bin/
gen/

# Ignore gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Eclipse Metadata
.metadata/

# Mac OS X clutter
*.DS_Store

# Windows clutter
Thumbs.db

# Intellij IDEA (see https://intellij-support.jetbrains.com/entries/23393067)
.idea/workspace.xml
.idea/tasks.xml
.idea/datasources.xml
.idea/dataSources.ids


만약 build file들이 tracking system에 등록 되었다면 아래의 명령어를 이용해서 제거하자.

해당 명령어는 실제 파일 시스템에서는 제거하지 않고 tracking에서만 제거하는 방법이다.


git rm --cached 


더 쉬운 방법은 모두 제거하고 다시 하는 것이다.


git rm --cached -r . 


.gitignore 파일 생성

git add .






저장소 통채로 복사하기 (bit-bucket to GitHub)


참고자료

git clone --mirror: to clone every references (commit, tags, branches)

git push --mirror: to push everything


git clone --mirror https://bitbucket.org/exampleuser/repository-to-mirror.git

# Make a bare mirrored clone of the repository

cd repository-to-mirror.git

git remote set-url --push origin https://github.com/exampleuser/mirrored

# Set the push location to your mirror

git push --mirror


완전이 제거하고 이동 시키는 방법

// Reference: http://www.blackdogfoundry.com/blog/moving-repository-from-bitbucket-to-github/

// See also: http://www.paulund.co.uk/change-url-of-git-repository

$ cd $HOME/Code/repo-directory

$ git remote rename origin bitbucket

$ git remote add origin https://github.com/mandiwise/awesome-new-repo.git

$ git push origin master

$ git remote rm bitbucket


가장 간단한 방법은 아래와 같이 Github 기능을 이용하는 것이다.

1) Create a new empty repository in GitHub (without readme or licesne, you can add them before) and the following screen will show

2) Inside to import code option you paste your bitbucket URL's repo



Git: 두개의 Commit 사이에서 변경된 코드 수 알기


--stat 옵션을 사용 하면 된다.


git diff --stat <commit-ish> <commit-ish>



좀 더 복잡한 방법

http://stackoverflow.com/questions/2528111/how-can-i-calculate-the-number-of-lines-changed-between-two-commits-in-git


Git 간편 사용법: Click

Naver Blog: Click



맨 처음 시작



# set up git on your machine if you have not already.
$ mkdir /path/to/your/project
$ cd /path/to/your/project
$ git init
$ git remote add origin https://leejaymin@bitbucket.org/leejaymin/power-aware-notification-project.git

# Create your first file, commit, and push
$ echo "jemin lee" >> contributors.txt
$ git add contributors.txt
$ git commit -m 'Initial commit with contributors'
$ git push -u origin master




기존 프로젝트가 존재하는 경우



만약 기존에 있던 원격 저장소를 복제한 것이 아니라면, 원격 서버의 주소를 git에게 알려줘야 한다.

git remote add origin [저장소 URL]


로컬의 변경 내용은 현재 HEAD에만 있다. 이것을 원격 서버에 반영 시킨다. 

git push -u origin master

Note: 특정 branch로 반영을 원할 경우, master 대신에 해당 이름(ex: GUI)를 써야한다.


모든것을 반영하는 방법

git push -u origin --all # pushes up the repo add its refs for the first time

git push -u origin --tags # pushes up any tags



그런데, not fast forwarding 오류가 나면,

원격 저장소 내용을 로컬 저장소에 반영할 때 씀.

-> git pull origin master // 이것으로 동기화 한다.


강제로 push 하는 방법: Click

-> git push -f



Branch



Staging (Index)에 추가된것 초기화 하기: Site

git reset HEAD <file> 

git reset HEAD




원격 저장소를 이용하여 작업하기

 

이번에는 원격 저장소의 프로젝트와 상호작용하는 방법을 다루게 될 것이다.

 

어떠한 형태의 원격 저장소가 있는가?

어떻게 원격 저장소 복사본을 생성하는가?

어떻게 원격 저장소의 변경 사항을 가져와 최신 상태로 유지하는가?

어떻게 자신의 변경 사항을 푸싱하여 원격 저장소에 공유하는가?

어떻게 원격 브랜치와 작업하는가?

어떻게 새로운 원격 저장소를 추가 하는가?

 

□ 네트워크 프로토콜

 

Git는 SSH, git, HTTP/HTTPS 이렇게 3개의 프로토콜로 원격 저장소와 통신을 하게 된다.

 

□ SSH(Secure Shell)

git@github.com/tswicegood/mysite-chp6.git

 

git는 사용자 명이다.

github.com은 서버이름이다.

맨마지막은 저장소의 경로를 의미한다.

 

□ git

속도를 위해서 설계되어진 전용 프로토콜이다.

주로 read only로 저장소를 공유할 때 사용 한다.

하지만 네트워크 9418번 port를 사용하기 때문에 방화벽으로 인해서 막히는 현상이 자주 발생 한다.

 

git://github.com/tswicegood/mysite-chp6.git

 

SSH와 가장큰 차이점은 git가 사용자 아이디가 아니라, 그냥 git 프로토콜을 나타내는 접두어 git일 뿐이라는 것이다. 즉 임의의 사용자의 접근을 허용한다는 의미이다. 따라서 읽기전용만 된다는 것이다.

 

□ HTTP/HTTPS

최후의 수단이다. 따라서 느리고, 네트워크에 부담도 많이 준다.

하지만 방화벽 문제는 거의 발생시키지 않는다. well-known port를 사용하기 때문이다.

 

http[s]://github.com/tswicegood/mysite-chp6.git

 

□ 원격 저장소 복제하기

 

git clone [저장소 주소]

 

복제 명령어 clone을 통해서 생성된 복사본은 git init으로 직접 생성한 저장소처럼 동작 한다.

 

 

변경이력을 최신으로 만들기

 

방법 1) 아직 미완성

git fetch // branch의 이력을 최신으로 업데이트한다.

 

fetch를 실행하면 지역 저장소의 원격 브랜치가 갱신된다. 즉 -r이나 -a를 해서 보면 목록이 갱신된것을 볼 수 있다. 하지만 이때, 지역 브랜치에 가져온 원격 브랜치의 변경 사항들은 merge 되지 않는다. 즉 변강사항들이 반영되지 않는다는 말이다.

 

git branch -r // r option은 remote branch의 목록을 보는것이다.

 

아직 불안전한 방법이다.

 

방법 2) 완성된 방법

 

git remote //원격 저장소의 별칭을 알아낸다.

git remote show [원격 저장소 별칭] // 원격 저장소의 별칭에 대한 주소와 remote branch의 정보를 알아온다.

git pull [원격저장소 별칭] // 원격 저장소의 별칭을 이용해서 변경이력을 가져와 현재 브랜치와 합병한다. 

git remote add [원격 저장소 별칭] [원격저장소 full address] // 원격 저장소의 풀주소(git://, ssh://, http[s]://)를 해당 별칭으로 등록 한다.

 

그러닌까 pull은 원격저장소의 내용을 현재 branch로 합병 시켜버린다.

 

만약 원격 저장소의 이름이 origin/next라고하면

git pull origin next 이렇게해야한다.

'/'를 쓰면 안된다.

 

pull을 반영 시킬 현재 브랜치를 설절하고 싶다면 <참조>를 이용한다.

git pull origin next:current_next // current_next라는 현재 지역 저장소의 브랜치에 원격 저장소의 next 브랜치의 내용을 합병 시킨다.

 

즉, git pull이란 아래의 명령어를 사용한 효과와 동일하다.

git fetch orgin

git merge origin/next

 

 

변경 사항 푸싱하기

 

git push

매개 변수 없이 실행하면, origin 저장소에 푸싱한다고 생간한다. 또한 지역 저장소의 현재 브랜치를 원격의 같은 이름의 브랜치에 푸싱한다고 여긴다. 이때, 원격 저장소에 같은 이름의 브랜치가 존재해야한다.

 

git push <저장소> <참조>

사용 형태는 pull과 비슷하다. pull을 이해했다면 모든것을 반대로만 생각해주면 쉽게 사용 할 수 있다.

 

 

□ Git 이력 이용하기

 

이력을 보는 방법은 git이다.

 

> git log -p -1

 

-p 옵션은 코드가 변경된 부분까지 보여 주는 것이다.

-1 옵션은 변견이력의 수를 표시해 주는 것이다.

 

 

□ 리비전 범위 지정하기

 

변경이력을 확일 때 범위를 지정해서 해당 기간에 맞는 변경 이력만을 찾아 주는 기능이다.

 

 

> git log --since="5 hours" // 지난 5다섯 시간 동안의 커밋만 볼 때 사용 한다.

> git log --before="5 hours" // 5시간 이전에 변경한 그러닌까 오래전의 변경 이력을 본다.

 

점(.)과 하이픈(-)를 사용해서도 날짜를 입력 할 수 있다.

 

예) "오래된-리비전..최신-리비전"의 형식으로 범위를 지정할 수도 있다.

 

이 밖에도 많은 조합 들이 존재 한다.

 

□ 버전 간의 차이점 자세히 보기

 

그냥 git difff를 사용할 경우 작업 복사본과 저장소 간의 차이를 볼 수 있게 된다.

 

git diff 18f822e // 특정 리비전과의 비교이다,

git diff --stat 1.0 // 통계적으로 특정 TAG와의 차이를 보여 준다.

 

태그를 하나만 지정할 경우 비교 대상은 무조건 HEAD가 된다.

 

 

□ 누구의 책임인지 찾기

 

git blame은 파일의 각 줄앞에 커밋명, 커밋한 사람, 시간 정보를 추가해서 보여 준다.

 

다음은 hello.html 파일에 대한 git blame 출력의 처음 두줄이다.

 

>git  blame index.html

^d5fde6e (Jemin Lee 2012-06-03 00:58:42 -0700  1) <html>
a67525a7 (Jemin Lee 2012-06-03 01:53:19 -0700  2) <head>
a67525a7 (Jemin Lee 2012-06-03 01:53:19 -0700  3) <title>Hello World in Git</tit
8b2a7580 (Jemin Lee 2012-06-03 04:26:53 -0700  4) <meta name="description" conte
a67525a7 (Jemin Lee 2012-06-03 01:53:19 -0700  5) </head>
a67525a7 (Jemin Lee 2012-06-03 01:53:19 -0700  6)
^d5fde6e (Jemin Lee 2012-06-03 00:58:42 -0700  7) <body>
^d5fde6e (Jemin Lee 2012-06-03 00:58:42 -0700  8) <h1>Hello World!</h1>
8d1f9954 (Jemin Lee 2012-06-03 04:21:20 -0700  9) <ul>
8d1f9954 (Jemin Lee 2012-06-03 04:21:20 -0700 10)       <li><a href="bio.html">B
8d1f9954 (Jemin Lee 2012-06-03 04:21:20 -0700 11) </ul>
^d5fde6e (Jemin Lee 2012-06-03 00:58:42 -0700 12) </body>
a67525a7 (Jemin Lee 2012-06-03 01:53:19 -0700 13)
^d5fde6e (Jemin Lee 2012-06-03 00:58:42 -0700 14) </html>
^d5fde6e (Jemin Lee 2012-06-03 00:58:42 -0700 15)

 

^(캐럿)이 문작 존재하는 것은 해당 커밋이 저장소에서 첫 번째 임을 의미한다.

□ 브랜치 이해하고 활용하기

 

기본적으로는 하나의 브랜치 즉 마스터 브랜치만 사용해도 버전관리 시스템이 제공하는 모든 이점을 얻을 수 있다.

Git을 사용하면 이력을 추적하고 다른 개발자와 협업할 수 있다. 또한, 갑자기 중요한 파일이 지워지는 상황도 대처 할 수 있다.

 

하지만 이정도로 Git을 사용한다면 마치 경주용 자동차를 타고 출퇴근을 하는것과 같다.

 

이 번에 다룰 내용은 아래와

  • 새로운 브랜치 생성하기
  • 브랜치 간의 변경 사항 합치기
  • 충돌 다루기
  • 브랜치 삭제하기
  • 브랜치명 변경하기
  • 릴리스 브랜치 다루기

 

>git branch -m master mymaster

 

-m의 매개변수는 이동을 의미한다. 결국 master라는 메인 브랜치를 mymaster로 변경 하겠다는 의미를 가진다.

 

Git에서의 브랜치는 큰 비용을 지불하지 않아도 되는 가벼운 구조를 가진다.

즉, 다른 버전 관리에서는 모든 파일을 새로운 디렉터리로 복사하지만, GIt에서는 해당 브랜치가 만들어진 시점부터 적용된 Commit만을 추적하기위해 파일을 생성 한다.

 

 

브랜치를 생성 하는 시점

  • 실험적인 변경 사항 추가시
  • 새로운 기능을 추가하고 싶을때
  • 버그를 수정하고 싶을때

이렇게 브랜치를 생성하고 언제든지 Merge할 수 있기 때문에 추후에 복잡해질 여지는 없다. 또한 변경이력 또한 쉽게 통합 되어진다. 따라서 주저하지말고 필요하다고 생각되면 브랜치를 생성해야 한다.

 

 

□ 브랜치 생성

 

> git branch new

> git branch

* master

  new

 

*는 현재 작업 트리 디렉터리를 나타내는 것이다.

즉 checkout을 하게 되면 현재 작업 트리로 설정 하는 것이 된다.

 

 

브랜치 생성과 동시에 Checkout 하는 방법

> git checkout -b alternate master // 3번째 파라매터인 master는 복사해야할 브랜치 명이다. 즉 이렇게 직접적으로 설정할 경우, 지정한 브랜치로부터 새로운 브랜치를 생성하게 된다.

 

 

□ 브랜치 간의 변경 사항 합치기

 

합치기는 다음 3가지로 구분된다.

  • Straight Merge: 하나의 브랜치와 다른 브랜치의 변경 이력 전체를 합치는 방법이다.
  • Squashed Commit: 한 브랜치의 이력을 압축하여 다른 브랜치의 최신 커밋 하나로 만드는 방법이다.
  • Cherry-picking: 다른 브랜치에서 하나의 커밋을 가져와서 현재 브랜치에 적용하는 방법이다.

Straight Merge : 바로 합치기

git add about.html // 새로운 파일 생성

about.html에 내용 입력 // 새로운 파일에 내용 입력

git commit -m "add the skeleton of an about page"  // commit하기 log를 입력해서

git checkout master // merge하기전에 합병이 되어질 브랜치로 이동

git merge alternate // master와 alternate를 merge한다.

 

 

Squashed Commit : 커밋합치기

Git이 브랜치 하나의 모든 이력을 압축하여 다른 브랜치에 하나의 커밋으로 만들기에 커밋 합치기라고 한다. 커밋 합치기를 할 때는 유의해야 한다.

 

커밋 합치기는 이것저것 실험해 봐야 하는 새로운 기능을 만들거나 버그를 수정할 때 유용하다. 실험한 내용은 추적하지 않아도 되므로 커밋할 필요가 없다. 즉 마지막 결과만 필요할 뿐이다.

 

git checkout -b contact master // master 브랜치에서 contact 브랜치를 생성하고 체크아웃 한다.

contract.html 생성

git add contract.html // 파일 추가 (스테이징)

git commit -m "add contract file with email" // commit한다.

contract.html에 새로운 내용 추가

git commit -m "add secondary email" -a // 모든 변경사항을 commit한다. (-a 매개변수의 의미)

 

//이제 Squashed Commit을 해서 2개의 변경이력을 하나의 이력으로 통합해서 master 브랜치에 merge를 해보자.

git checkout master

git merge --squash contact // --squash 매개변수를 지정한다. 지정한 브랜치의 모든 커밋을 하나의 커밋으로 밀어 넣는다.

 

여기서 중요한점은 그냥 merge는 스테이징 되지않고 바로 적용되었지만 --squash 매개변수를 사용해서 커밋 합치기를 할경우 스테이징 단계를 거친다. 따라서 그것을 확인해보면

 

git status // Chages to be committed 라는 메시지를 볼 수 있다.

 

git commit -m "add contract page" -m "has primary and secondary email" // 이렇게하면 하나의 변경이력으로 통합되는것을 알 수 있다.

git log -2 // 변경 이력이 통합 되었음을 알 수 있다.

 

Cherry-picking: 선택하여 합치기

 

전체를 합치는게 아니라, 부분적으로 합칠 필요성이 있을 수 있다. 아직은 해당 브랜치가 완성이 안되었기 때문에 부분적으로 합치고 싶은 경우이다. 이때 사용하는 기능이다.

 

git checkout contact // 브랜치 변경

git commit -m "add link to twitter" -a // 모든 변경 사항을 commit 한다.

 

git checkout master // master로 이동

git cherry-pick 321d76f // 321d76f가 commit하려는 선택적인 이력인 것이다.

 

 

□ 충돌 다루기

충돌이란 서로 다른 2개의 branch를 통합하려고 할 때 같은 파일에 동일한 위치에대해서 다른

변경이 있을 경우이다.

 

□ 충돌을 실습하기 위해서는 예제 만들기

충돌을 어떻게 다루는지 확인해보자. 먼저 예제를 위해 about이라는 새로운 브랜치를 생성한다.

> git checkout -b about master

자신이 좋아하는 프로그래밍 언어 리스트를 기입한 about.hml을 생성한다.

> git add about.html

> git commit -m "a list of my favorite programming languages"

git branch about2 about // about을 가지고 about2를 생성한다.

브랜치 전환하기 전에 about.html 파일에 다른 언어를 추가하고 변경 사항을 커밋한다.

> git commit -a // 새로운 언어 리스트를 추가하고 commit한다.

> git checkout about2 // about2 brach로 이동을 한다.

이제 about2에서는 about.html의 마지막 리스트에 아까 입력했던 값이 없다.

여기에 새로운 값을 입력하자.

>git commit -a // commit 한다.

>git checkout about // about branch로 이동 한다.

>git merge about2 // about2와 합병 한다.

이제 당연히 충돌이 발생하게 된다. 충돌이 발생 했을 경우 소스코드를 보면

========= // 다른 브랜치와 충돌이 발생하는 코드

<<<<<< // 이러한 기호 뒤에 나오는 코드는 현재 브랜치의 코드이고,

>>>>>> // 이러한 기호 앞에 나오는 코드는 다른 브랜치의 코드라는 점이다.

그다음에 나오는 기호는

파일 명 앞에 합치려고 하는 브랜치명이 표시된다는 것이다.

<<<<<< HEAD:about.html

>>>>> about2:about.html

□ 브랜치 삭제하기

>>git branch -d about2로 삭제 한다.

제한사항: 브랜치 삭제 명령은 삭제하려는 브랜치가 성공적으로 현재 브랜치에 합쳐졌을 때만 동작한다.

합쳐지지 않았을때는 아래와 같은 에러가 생긴다.

error: The branch 'about' is not fully merged.
If you are sure you want to delete it, run 'git branch -D about'.

이를 해결하기 위해서는 -D (대문자를 사용 한다.)

□ 브랜치명 변경하기

git branch -m contact contacts

m명령어를 사용해서 변경을 한다.

제한사항: 하지만 이 명령어는 존재하는 브랜치를 덮어쓰지 못하므로 새로운 브랜치명은 반드시 고유해야 한다.

-M을 쓰면 덮어씌워 진다.

 

 

 

 

 

 

 

파일 이름을 변경하고 파일 이동하기

 

개발자는 누구나 실수하기 때문에 파일을 변경하고 새로 작성하고 이러한 작업들은 흔히 발생 하는 일이다.

 

Git에서 git mv <원본파일> <새로운 파일>과 같이 입력하면 파일을 이동 시킬 수 있다.

 

 

□ 파일 복사하기

 

Git은 파일이 아니라 그 내용을 추적한다는 사실은 모두가 잘 알 것이다. 왜냐하면 결국 파일 이름이란 그냥 그 파일에대한 메타데이터의 일종일 뿐이기 때문이다.

 

즉, git cp명령어 따위가 없다. 그냥 복사해도 git은 내용을 추적하기 때문에 알아서 중복된 내용으로 commit을 할 수 있게 한다. 하지만 같은 파일을 복사해서 사용하는것은 주의해야한다. 이렇게 중복된 코드를 사용한다는 것은 리펙토링이 필요하다는 의미를 내포하고 있기 때문이다.

 

□ 파일 무시하기

 

.gitignore을 통해서 각 편집기가 사용하는 임시 복원 파일과 같은 것들을 변경이력에서 무시하도록 할 수 있다.

즉 다른 개발자들은 필요없는 정보들은 구지 commit할 필요가 없는 것이다.

 

지역 저장소에서만 해당 파일을 무시하도록 설정할 수도 있다.

.git/info/exclude 파일을 수정하면 위 기능을 구현 할 수 있다.

 

정리하면

모두에게 무시 되어져야 한다면 .gitignore 파일에 규칙을 추가하고 저장소에 커밋한다.

자신에게만 해당된다면 .git/info/exclude파일에 추가한다.

 

Git을 이용해서 차이점을 살펴 보기

 

Git을 이용해서 변경사항을 추적하는 일은 다음과 같다.

1) Git은 작업트리의 변경사항

2) 스테이징 되어서 커밋하려는 변경 사항

3) 저장소간의 차이점을 보여주는 사항

 

매개변수 없이 git diff를 실행하면 아직 스테이징되지 않고 커밋되지도 않은

작업트리(작업 디렉터리)의 변경사항을 보여준다.

 

>git diff

root@ubuntu:/work_remotGitHub/mysite-remote# git diff
diff --git a/index.html b/index.html
index ca86894..06bfc3d 100644
--- a/index.html
+++ b/index.html
@@ -7,6 +7,7 @@
     <h1>Hello World!</h1>
     <ul>
         <li><a href="about.html">About</a></li>
-    </ul>
+                 <li><a href="contact.html">Contact</a></li>
+       </ul>
 </body>
 </html>

 

git diff를 매개변수 없이 실행하면 작업 트리의 변경 사항과 스테이징 영역을 비교 한다.

 

스테이징 영역과 저장소의 차이점을 알기 위해서는 아래를 실행 한다.

root@ubuntu:/work_remotGitHub/mysite-remote# git diff --cached
diff --git a/index.html b/index.html
index e812d0a..ca86894 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,7 @@
 <body>
     <h1>Hello World!</h1>
     <ul>
-        <li><a href="bio.html">Biography</a></li>
+        <li><a href="about.html">About</a></li>
     </ul>
 </body>
 </html>

 

스테이징 한것은 <li><a href="about.html">About</a></li> 이기 때문에 이부분에 대해서만 결과가 나오는 것을 알 수 있다.

 

작업트리(작업디렉터리), 스테이징 영역, 저장소(repository) 3곳 모두에서의 모든 차이점을 보고 싶다면 HEAD 매개변수를 추가한다.

root@ubuntu:/work_remotGitHub/mysite-remote# git diff HEAD
diff --git a/index.html b/index.html
index e812d0a..06bfc3d 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,8 @@
 <body>
     <h1>Hello World!</h1>
     <ul>
-        <li><a href="bio.html">Biography</a></li>
-    </ul>
+        <li><a href="about.html">About</a></li>
+                 <li><a href="contact.html">Contact</a></li>
+       </ul>

 </body>
 </html>

 

HEAD는 현재 작업중인 브랜치에서 가장 최신의 커밋을 나타내는 키워드다.

 

commit -a 해서 변견이력을 등록 한다. 메시지는 각자 알아서 상세히 기록 하자.

 

 

개요

매번 소스코드를 압축하고 뒤에다가 날자를 붙이는 번거로운 작업을 하면서 프로젝트를 진행 할 수는 없다.

현재 많이 쓰이고 있는 CVS나 SVN과 다른 분산 버전 관리 시스템인 Git(깃)을 소개한다.

Git vs CVS, SVN

cvs와 svn의 경우 저장소(repository)가 원격 서버에 있는 방식이다. 즉, 중앙에 집중적인 버전 관리 시스템을 가지고 있는 것이다.

이러한 중앙 집중식 저장소는 컴퓨터에 직접 접근해야 하는 문제는 개선 했지만 여전히 한계가 있다. 먼저, 사용자는 최신 버전의 코드만 가지고 있다. 변경 이력을 보려면 저장소에 정보를 요청해야 하는 것이다. 즉, 반드시 네트워크상에서 원격 저장소로 접근해야 한다는 점이 문제인 것이다.

하지만 Git(깃)이 따르는 모델인 분산 버전 관리 시스템에서는 모든 팀원이 변경 사항을 전송하는 중앙 저장소를 가지는 대신, 각자가 프로젝트의 전체 이력이 있는 자신만의 저장소를 가진다. 커밋할 때는 원격 저장소에 연결할 필요가 없이 변경 사항을 지역 저장소에 기록한다.

은행으로 비유하자면, 중앙 집중식 시스템이 팀 구성원 모두가 사용하는 하나의 은행을 가지는 것이라면, 분산 시스템은 각 개발자가 자신만의 개인 은행을 가지는 것과 같다.

이쯤 되면 다른 사람들이 작업한 변경 사항을 어떻게 동기화 해야 할지, 그리고 내가 수정한 변경 사항을 다른 사람들이 제대로 가지고 있을지 궁금할 법하다. 각 개발자는 여전히 중앙 프로젝트 저장소에 변경 사항을 전송 한다. 개발자가 직접 변경 사항을 중앙 저장소에 전송 하려고 접속할 수 있다. 이런 행동을 Git에서는 푸싱(Pushing)이라고 한다. 또는, 변경 사항을 모아둔 패치를 만들어 프로젝트를 관리하는 사람에게 제출해서 중앙 저장소에 반영하게 할 수 있다.

Git의 작업 트리

사용자가 모든 변경 작업을 수행하는 위치는 작업트리이다.

작업 트리란 결국 저장소를 바라보는 자신의 현재 시점이다. 작업 트리는 소스코드, 빌드 파일, 단위 테스트 등 프로젝트의 모든 파일을 가지고 있는 것이다.

몇몇 버전 관리 시스템에서는 작업트리를 작업 복사본(working copy)이라고 한다. 다른 버전 관리 시스템을 사용하다가 Git을 처음 사용하는 사람들은 저장소와 작업 트리를 구분하는 데 혼란을 겪는다. Subversion(SVN)과 같은 버전 관리 시스템에서 저장소는 '저 너머'의 다른 서버에 존재한다.

하지만 Git 에서 '저 너머'란 로컬 컴퓨터의 프로젝트 디렉터리에 있는 .git/ 디렉터리를 의미한다. 즉 저장소의 이력을 보고 변경 사항을 살펴보려고 다른 서버에 있는 저장소와 통신하지 않아도 된다.

그럼 이 작업 트리를 처음 가져오려면 어떻게 해야 할까? Git에게 자신의 프로젝트를 저장소에 초기화 하도록 요청하거나, 기존 저장소의 프로젝트를 복제(clone)할 수 있다.

복제하기는 지역 저장소(현재 본인의 로컬 컴퓨터)를 만든 후 개발의 기본 흐름인 마스터 브랜치에서 복사본을 체크아웃(check out)한다. Check out은 git이 사용자의 작업 트리를 저장소의 특정 시점과 일치하도록 변경하는 작업이다.

결국 버전관리 시스템은 결국 이 변경사항을 어떻게 추적하는지가 전부이다. 이제 본격적으로 변경사항을 어떻게 추적하는지에 대해서 설명 하도록 하겠다.

파일 다루고 동기화 하기

버전 관리 시스템을 사용하는 주된 이유는 변경을 계속해서 추적하기 위함이다. 개발자는 소스 코드를 변경하고, 잘못된 영향(side effect)을 끼치지는 않았는지 단위 테스트를 수행한 다음 commit한다.

pulling : 다른 개발자가 변경사항을 푸싱 한것을 가져오는 작업을 말한다. CVS, SVN에서의 update와 유사한 기능을 한다.

□ 프로젝트, 디렉터리, 파일 추적하기

여기서는 저장 대상을 구조화하는 방법에 대해서 이야기 해보자.

Git는 제일 원초적인 방법으로 저장한 파일의 내용을 분석해서 그 변경이력을 추적하게 된다.

여타 다른 버전관리 시스템에서는 파일 자체를 추적하는데, git은 내용을 추적하기 때문에 다르다고 할 수 있다.

즉 models.py 파일을 추적하는 대신 models.py에 있는 변수나 함수 등을 구성하는 각 문자와 줄을 추적하며 이름, 파일 모드(file mode), 심볼릭 파일 여부와 같은 메타 데이터(metadata)를 models.py에 추가 한다. 이것은 미묘한 차이점이지만 중요하다.

이러한 점은 기술적으로도 큰 이점이다. 저장소의 전체 이력을 저장하는데 필요한 공간이 줄어든다. 그리고 두 파일 사이에서 함수나 클래스의 이동을 알아내거나 어디에서 복사된 코드인지 결정하는 것과 같은 작업이 가능해졌으며 빠르다.

결국 , 프로젝트란 저장소에 파일과 디렉터리를 조직화한 형태에 불과하다.

□ 태그를 이용해 마일스톤 추적하기

프로젝트를 진행함에 따라 마일스톤(milestone)에 도달하게 된다. 애자일 방법론을 따른다면 매주마다 새로운 기능을 추가하는 주간 개발 주기를 따를 태고, 수 개월에 한 번씩 업데이트를 릴리스하는 기존의 방법론 중 하나를 따를 수도 있다.

둘 중 어느 경우라도 특정 마일스톤을 달성했을 때의 저장소 상태를 추적할 수 있어야 한다. 태그(tag)를 이용해 이러한 상태를 추적한다. 태그에 저장소 이력의 특정 위치를 기록해두면 나중에 편리하게 참조할 수 있다.

태그는 저장소 이력의 특정 시점을 기록하는 용도로 사용하는 이름일 뿐이며, 공개 릴리스 같은 주요 마일스톤이나 버그 수정 같이 사소한 것들도 표현할 수 있다.

쉽게 기억할 수 있는 이름을 특정 리비전의 태그에 부여함으로써 저장소의 이력을 계속해서 추적할 수 있다.

□ 브랜치로 분기 이력 만들기

만약 달력 프로그램을 다시 작성하려면 팀원의 동의를 구해야 하며 변경 사항을 추적해야 한다. 코드 전체를 다른 디렉터리에 복사해두고 바꾸기 시작해도 되지만, 이렇게 변경하면 내역을 추적할 방법도 없고, 더 중요하게는 이것 저것 실험하면서 했던 실수를 되돌릴 수도 없다는 문제가 생긴다.

이런 때 브랜치가 필요하다. 브랜치를 생성하려면 파일이 분기하는 위치가 저장소에 기록된다. 브랜치는 다른 브랜치와 분리하여 내용에 대한 변경 사항을 지속적으로 추적한다. 그래서 분기 이력을 생성할 수 있다.

마스터 브랜치(master branch)는 개발의 기본 줄기이다. // 다른 버전 관리 시스템(svn)에서는 트렁크(trunk)라고 부리기도 한다.

브랜치를 생성하면 기본 줄기에서 분기된다.

브랜치는 계속 남겨둘수도 있고, 바로 지워 버릴 수도 있다.

또한 Git에서는 브랜치도 다른 모든 것과 마찬가지로 다른 사람과 공유하지 않고 지역적으로 생성할 수 있다. 지역 브랜치를 생성하고 공유하지 않는 데에도 나름의 이점이 있다. 개인적으로 몇 가지를 실험해보고, 만족스러운 수준이 된후에 공유할 수 있다. 실험한 내용이 제대로 동작하지 않으면 그냥 조용히 지워버리면 된다.

Git을 이용하면서 브랜치와 태그는 중요한 부분이기에 추후에 따로 자세히 설명 하도록 하겠다.

대부분의 브랜치는 초신의 내용을 유지할 수 있도록 다른 브랜치에 합쳐야 한다.

□ 합치기(Merge)

합치기를 이용해 여러 브랜치의 이력을 하나로 합친다. Git은 사용자가 직접하는 방식과 동일하게 이력을 합친다. Git은 두 브랜치의 변경 사항을 놓고 어디서 변경이 발생했는지 비교한다.

파일이 서로 다른 영역이 변경되었다면 Git이 알아서 합친다. 때로는 Git이 합칠 수 없는 상황이 발생 한다. 이때는 오류가 있음을 기록하고 사용자에게 충돌이 있음을 알린다.

즉, 같은 팀의 개발자가 코드에서 같은 위치를 서로 다르게 수정했다고 하자. Git은 이러한 상황을 보고 둘 중에 어느 것이 올바른지 결정할 수 없기 때문에 충돌로 표시하고, 사용자가 어떤 변경이 올바른지 알려주기를 기다린다.

Git의 막강한 기능은 바로 merge의 변경 이력 추적에 있다. merge 추적을 통해 이러한 작업을 처리하기 위해서는 손수 해야하는 불편함이 과거 버전관리 시스템에는 있었다. 하지만 Git의 경우 함께 합쳐진 커밋 내역을 주적하고, 이미 합쳐진 내용을 다시 합치지 않게 한다.

이게 가능하기 때문에 더 이상 브랜치 사용을 꺼려하지 않아도 되는 것이다.

(단, subversion 1.5.0부터는 merge trace 기능을 support한다.)

□ 잠금 옵션

도서관의 책을 빌리는것과 같은 것이다. 한번에 한사람만 책을 빌릴 수 있는 것이다. 이를 버전 관리에 적용할 경우

즉 한번에 한 사람만이 소스 코드를 수정 할 수 있다는 말이다.

strict locking : 특정 코드의 복사본은 한 번에 한 사람만 가질 수 있다. 이는 함께 일하는 팀원 간에는 그다지 효율적인 방식이 아닐 뿐더러 사로 느슨하게 연결된 분산 버전 관리 시스템 모델과도 어울리지 않는다.

optimistic locking : 대부분의 경우 서로 변경한 영역에 충돌이 없으리라고 가정하므로 다수의 개발자가 같은 파일에 있는 동일한 코드를 이용하는 것을 허용한다.

시나리오)

개발자 A와 B가 동시에 같은 파일을 복사본을 만들어서 수정한다. 이때 optimistic locking이기 때문에 동시에 2명이 체크아웃하는것을 허용한다.

그리고 개발자 A가 자신의 변경사항을 푸슁한다. 그리고 개발자 B가 푸슁하려고한다. 그러면 Git은 거부한다.

그러면 개발자 B는 A가 푸슁한 이력을 폴링해서 자신의 저장소에 반영해야한다. 그다음 다시 푸슁하면 성공한다.

복잡하지만 생각해보면 간단한 이력 업데이트 방식이다. 또한 한팀에서 두명이 동시에 같은 파일을 편집하는 경우도 흔치 않을 것이다.

지금 까지 거시적 관점에서 Git 즉, 분산 버전 관리 시스템의 구성을 보았다. 이제 다음 포스트에서 좀 더 상세한 Git의 사용법에 대해서 다루도록 하겠다.

□ 개요

Git를 실제 어떻게 사용하는지에 대한 실질적인 방법을 다루도록 하겠다.

 

□ 저장소 생성하기

> mkdir mysite
> cd mysite
> git init
Initialized empty Git repository in /root/gitTutorial/mysite/.git/

 

이것으로 끝이다. 이제 프로젝트를 추적할 수 있는 Git 저장소가 생겼다.

이게 전부일 리 없다고 생각할지 모르지만 정말로 더 이상은 없다. Git 저장소를 설정하는 작업은 정말로 간단하다. git init 명령어는 .git 디렉터리를 생성하고 여기에 저장소 메타데이터를 모두 저장한다. 그리고 현재 비어있는 mysite 디렉터리는 저장소에서 체크아웃 할 코드의 작업 트리가 된다.

 

□ 변경하기

이제 빈 저장소에 파일을 추가하자. index.html 파일을 생성하고 해더와 "Hello World"란 텍스트를 추가한다. 내용은 다음과 같다.

<html>
<body>
<h1>Hello World!</h1>
</body>
</html> 

 ---------------------------------------------------------------------
root@ubuntu:~/gitTutorial/mysite# git commit -m "add in heelo world HTML"
[master (root-commit) d5fde6e] add in heelo world HTML
1 files changed, 6 insertions(+), 0 deletions(-)
create mode 100644 index.html
root@ubuntu:~/gitTutorial/mysite# git log
commit d5fde6e2e1174824be35707fe862aea3a3c1109d
Author: Jemin Lee <leejaymin@nate.com>
Date: Sun Jun 3 00:58:42 2012 -0700
add in heelo world HTML

 

첫 줄에서 커밋명을 보여준다. 커밋명은 커밋을 추적할 수 있도록 Git이 생성한 SHA-1 해시(hash) 값이다. Git은 각 커밋의 식별자가 완벽히 고유하도록 SHA-1 해시를 이용한다. 분산 환경에서는 완벽히 고유하다는 점이 중요하다. 해시에 대한 자세한 설명은 추후에 다시 설명 하도록 하겠다.

commit은 해시의 7자리만 사용해도 된다.

두번째는 commit한 사람이고

세번째는 날자이다.

네번째는 commit 메시지이다.

 

□ Git SHA-1 해시를 사용하는 이유

SVN에서는 그냥 리비전 상수만 쓰면 됬었다.
하지만 Git는 분산 버전 관리 시스템이기 때문에 상수값만으로는 충돌을 회피할 수 없다.
따라서 해시를 이용한다. 해시 또한 충돌할 가능성이 있지만 그 확률은 거의 0에 가깝다.
수학적으로 2^63분의 1의 확률을 가진다.
또한 이 해시의 숫자를 모두 사용하지않고 7~8자리만 사용한다. 이것으로도 충분하다.


 

□ 프로젝트를 이용한 작업 시작하기

이제 저장소를 준비 했으며 이미 첫 번째 파일을 추적하고 있다. 이제부터 변경 사항을 다뤄보자.

<html>
<body>
<h1>Hello World!</h1>
</body>
</html>
------------------
1 <html>
2 <head>
3 <title>Hello World in Git</title>
4 </head>
5
6 <body>
7 <h1>Hello World!</h1>
8 </body>
9
10 </html>

 

그다음 아래 명령어를 실행해보면

 

root@ubuntu:~/gitTutorial/mysite# 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: index.html
#
no changes added to commit (use "git add" and/or "git commit -a")

 

출력 결과를 통해 변경된 파일을 Git이 알고 있지만 이것을 어떻게 처리할지는 아직 모른다는 사실을 알 수 있다. 변경한 파일은 수정된 파일(modified)로 표시 되지만, 갱신 전(Changed but not updated) 헤더에 있다. 이 파일을 커밋 하려면 변경 사항을 스테이징(stage)해야 한다.
변경 사항을 stage하면 커밋할 수 있도록 준비한다. Git에서는 사용자의 코드를 세 공에 저장한다.
첫째 위치는 파일을 편집할 때 직접 이용하는 작업 트리다.
작업트리 = 서브버전(SVN)이나 CVS에서는 작업 복사본이라고 부른다.
둘째 위치는 인덱스이며 이후에는 스테이징 영역(staging area)이라 부른다.
스테이징 영역은 작업 트리와 저장소 사이의 버퍼공간이다.
세번째 위치는 Git이 코드를 저장하는 저장소이다. 스테이징 영역은 저장소에 커밋하려는 대상만 올려두는 용도로 사용한다.
이제 git add명령어를 다시 이용하면 index.html 파일의 변경 내용을 스테이징할 수 있다. 아까 새 파일을 추가하기 위해서 사용한 명령어와 동일하다. 이번에는 새로운 파일임을 알리는 용도가 아니라 추적할 새로운 변경 내용이 있음을 Git에게 알린다.

 

oot@ubuntu:~/gitTutorial/mysite# git add index.html
root@ubuntu:~/gitTutorial/mysite# git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
modified:   index.html
#

root@ubuntu:~/gitTutorial/mysite# git commit -m "add <head> and <title> to index" \-m "This allows for a more semantic document" \-m "한글 테스트"
[master a67525a] add <head> and <title> to index
 1 files changed, 5 insertions(+), 0 deletions(-)
root@ubuntu:~/gitTutorial/mysite# git log
commit a67525a717571244586d19e4a15b9dea25a04aec
Author: Jemin Lee <leejaymin@nate.com>
Date:   Sun Jun 3 01:53:19 2012 -0700

    add <head> and <title> to index
   
    This allows for a more semantic document
   
    한글 테스트

commit d5fde6e2e1174824be35707fe862aea3a3c1109d
Author: Jemin Lee <leejaymin@nate.com>
Date:   Sun Jun 3 00:58:42 2012 -0700

    add in heelo world HTML

root@ubuntu:~/gitTutorial/mysite# git log -1
commit a67525a717571244586d19e4a15b9dea25a04aec
Author: Jemin Lee <leejaymin@nate.com>
Date:   Sun Jun 3 01:53:19 2012 -0700

    add <head> and <title> to index
   
    This allows for a more semantic doucment

 

한글 테스트

 

맨 처음 git add index.html을 하면 스테이징에 추가할 파일이 넣어진 것이다.

즉, 버퍼에 들어간 것이다.

그다음 git status를 해보면Changes not staged for commit -> Changes to be committed 으로 변경된 것을 알 수 있다.

modified: index.html 도 초록색으로 변경된 것을 알 수 있다. (변경 사항을 스테이징도 하지 않을경우 빨간색으로 보이게 된다.)

 

이제

git commit -m "add <head> and <title> to index" \-m "This allows for a more semantic document" \-m "한글 테스트"
위 명령어를 실행하면 commit을 저장소로 한것이다.

그다음 git log로 커밋 로그를 찍어보면 변경 이력을 쉽게 알 수있다.

git log -1을 하면 변경이력중 최상위 1개만 볼 수 있다.

 

 

TIp : 커밋 로그에 어떤 내용을 넣어야 할까?

커밋 로그에 어떤 내용을 작성 할지 정하는 일이 처음에는 조금 난해할 수 있다. 커밋 메시지는 메시지만으로도 의도를 드러내도록 커밋의 '이유'를 설명하는 모든 메타데이터를 포함해야 한다.


□ 브랜치 사용하고 이해하기

 

브랜치는 그냥 마음대로 사용하면 되는 것이지만, 실제로 유용한 형태의 브랜치는 두가지가 있다.

 

1) 프로젝트의 여러 버전을 브랜치 별로 관리하기 위해 생성한 브랜치와 특정 기능을 다루는 주제 브랜치다.

이 첫번째에 해당하는 실습을 진행해 보도록 하겠다.

 

git branch RB_1.0 master

 

첫 번째는 생성하려는 브랜치명이고 두 번째는 분기해 나올 브랜치명이다.

 

위 명령어의 의미는 master 브랜치에서 RB_1.0이라는 브랜치를 생성한다. Git에서 master는 기본 브랜치명이다. CVS나 SVN(서브버전)에서는 GIt의 master 브랜치와 같은 역항을 트렁크(trunk)라고 부른다.

 

이제 브랜치를 생성 했기 때문에 릴리즈 버전에 영향을 주지않고도 추가적으로 프로젝트를 진행 할 수 있는 것이다.

 

index.html 파일에 다음을 추가해 보자.

<ul>

<li><a href="bio.html">Biography</a><li>

</ul>

그다음 아래의 명령어를 콘솔에 입력한다.

> git commit -a 

-a 매개변수의 의미는 Git에서 알고 있는 모든 변경된 파일을 커밋하라는 의미이다.

 

현재는 master 브랜치를 변경한 것이다. 브랜치를 변경해서 릴리즈 브랜치로 이동을 해보자.

>git checkout RB_1.0

index.html의 내용이 변경되는 것을 볼 수 있다.

 

이곳에 아래의 내용을 추가하자.

<meta name="description" content="hello world in Git"/>

그다음

>git commit -a

 

이제 릴리즈 준비가 끝났다.

 

□ 브랜치 사용하고 이해하기

 

지금 까지 작업한 코드의 1.0 릴리스 준비를 끝냈다. 여기에 태그를 붙여보자.

Git에서 코드에 태그를 붙이면 저장소 이력의 특정 지점을 기록하기 때문에 나중에 참조하기가 쉽다. 1.0 릴리스에 대한 태그니 숫자로 태그를 붙이자.

 

> git tag 1.0 RB_1.0

> git tag

1.0

 

태그를 해놨기 때문에 이제 브랜치를 제거해서 지저분한 부분을 정리하면 된다.

그전에 변경이력을 통합해준다.

즉, 브랜치를 merge하는 것이다. 아래의 명렁어를 입력한다.

 

>git checkout master // 마스터 브랜치로 이동

>git rebase RB_1.0 // 브랜치 merge

>git branch -d RB_1.0 //브랜치 삭제, tag를 해놧기 때문에 언제든지 복구할 수 있다.

 

그럼이제 tag를 통해서 어떻게 브랜치를 생성하는지 알아보겠다.

git branch RB_1.0.1 1.0 // tag 1.0을 기반해서 브랜치 생성

git checkout RB_1.0.1 // RB_1.0.1 새로 생성한 브랜치로 이동

git log --pretty=oneline // 변경 이력을 출력한다. 이전에 tag를 달았던 RB_1.0 브랜치의 변경 이력과 동일한 것을 알 수 있다.

 

 

+ Recent posts