# 아래의 링크 문서를 정독하면 누구나 git 고수가 될 수 있다!

https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC%EB%9E%80%3F


- Git의 기본 매커니즘. 아래의 그림이 전체 아키텍처를 전부 설명해준다.


위와 같이 git은 local repo와 remote repo가 구분되어 있는 점이 svn과 다른 매우 편리한 분산 버전 관리 시스템이다.

# 일단 git commit으로 로컬에 저장해놓은 데이터는 완벽히 보존된다! 내가 겪은 버그는 ipython의 자동저장기능 때문에, git checkout으로 이동 중 과거에 켜둔 웹이 최신버전에 자동저장되면서 마치 데이터가 사라진것 처럼 보이는 현상이었음.

# git에서 HEAD의 의미: 내 현재 위치라고 생각하면 됨.


- Git 환경 설정하기

git config --global user.email "이메일주소"
git config --global user.name "이름"
git config --global color.ui true : git 출력을 컬러로하기
git config format.pretty oneline : log에서 확정본을 한줄로 짧게 표시 # 별로일 수도 있음. 그러면 full 로 되돌림


# Github의 계정을 public key를 이용, ssh 환경을 세팅해서, 로그인 과정을 생략하기

이렇게하면, putty로 git remote repo에 접속할 때, id 비번 입력없이 바로바로 가능하다.
https://help.github.com/enterprise/2.10/user/articles/connecting-to-github-with-ssh/

1) ssh key 생성
ssh-keygen -t rsa -b 4096 -C "id@mail.com"

2) ssh private key를 내 컴퓨터의 ssh-agent에 등록하기
eval $(ssh-agent -s) 을 입력해서 agent가 실행 중인지 확인한다.
ssh-add 을 입력해서 ssh를 agent에 등록하고,
ssh-add -l -E md5 을 입력해서 제대로 등록되었는지 확인한다.

3) ssh public key를 github에 등록하기
cat ~/.ssh/id_rsa.pub 으로 나온 결과를 통째로 복사한다음

github 사이트의 setting - SSH and GPG keys에 들어가서 복사한 key를 넣으면된다.(title은 적당히 해당 컴퓨터를 가리키는 말을 적으면 됨)

입력하고 나온 Fingerprint가 ssh-add -l -E md5 의 결과와 동일해야함

4) 접속하기
ssh -T git@github.com 을 입력하고 yes를 입력해서 바로 아래의 메시지가 출력되면 정상 접속된 것이다.(주의: git@~~.com 에서 git은 고정이다. 유저 id가 아님)

  1. Hi username! You've successfully authenticated, but GitHub does not
    provide shell access.

4-1) Permission denied (publickey) 에러
위의 메시지가 나오지 않고, 
Permission denied (publickey)에러가 뜰 경우 다음 링크를 확인.
https://help.github.com/enterprise/2.10/user/articles/error-permission-denied-publickey/


5) ID / Password 없이 git 사용하기
기존의 remote url이 https를 통하도록 지정이 되어 있으면, 무조건 항상 ID와 비번을 물어본다. 따라서 방금 우리가 만든 ssh를 이용하도록 remote url을 변경해줘야한다.

git remote set-url origin git@github.com:PATH/TO/Repo.git

https://stackoverflow.com/questions/14762034/push-to-github-without-password-using-ssh-key/37075653


5-1) ssh-agent 자동 실행

그런데 위의 메시지를 봤는데도, 계속해서 username과 password를 물어본다면 다음을 실행해야한다.(ssh-agent가 실행이 안되어있는 경우임)

ssh-keygen -p 를 입력해서 임의의 비밀번호를 생성한다.

https://help.github.com/enterprise/2.10/user/articles/working-with-ssh-key-passphrases/ 을 참조해서 .bashrc에 ssh-agent 자동 실행 스크립트를 추가한다.


### 여러가지 에러 해결 ###

# ssh-add 를 하여도 passphrase를 계속 물어보면?
ssh-keygen -p -P "old_passphrase" -N "" -f ~/.ssh/id_rsa
을해서 passphrase를 제거한다.

https://stackoverflow.com/questions/42631711/git-keeps-prompting-me-for-passphrase-for-my-ssh-key-ubuntu-vm

# remote: Invalid username or password. 에러 해결
git remove -v
git remote set-url origin ssh://git
@github.com:PATH/TO/Repo.git

https://stackoverflow.com/questions/29297154/github-invalid-username-or-password


# git credential만들기: 비밀번호가 plain text로 저장되는 것에 유의하고 사용할 것.

git config --global credential.helper store

다시 해제하고 싶으면 아래를 입력한다.


git config --global --unset credential.helper

## 주의사항 ##
위의 명령을 실행하면 ~/.git-credentials라는 파일이 생성되는데 이 파일에는 사용자의 ID와 Password가 플레인 텍스트 형태로 그냥 기록된다. 따라서 완전히 무방비로 보안이 노출되기 때문에 가능하면 이 기능은 사용해선 안된다. SSH public key를 이용하는것이 가장 좋은 해결책으로 보인다.


- Git stash: commit 하지 않은 현재 작업내용을 임시로 저장하고, 마지막 commit한 상태를 불러오기


git stash: 현재 modified 된 파일을 임시로 저장하고, 마지막 commit상태를 불러옴
git stash pop: 임시로 저장해둔 변경내용을 불러옴.
          git stash pop == git stash apply && git stash drop.
git stash list : 임시 저장목록 가져오기

git stash apply [stash@{0}] : 임시 저장목록 불러와서 다시 적용하기
git stash drop [stash@{0}] : 저장해둔 내용 삭제

git stash show -p stash@{0} | git apply -R : 실수로 충돌 등이 일어난 경우, stash apply한 것을 되돌릴 수 있다.

- Git 의 핵심 명령어

git clone : 최초로 원격 서버에서 최신 버전의 git 서버의 파일들을 컴퓨터로 받아옴.
ex) git clone https://github.com/imcomking/Practical_Deep_Learning_Tutorial.git

git pull : 서버에서 최신 버전의 workspace 가져오기 (workspace 안에서 실행. push안한 사항이 있을 경우 충돌이 발생함. fetch + merge 을 합친 명령어)
ex) git pull origin master : 해당 branch의 원격 서버에 저장된 최신 내용을 가져온다

git checkout . : local repo에서 작업하고, commit 하지 않은 file을 모두 마지막 pull 시점으로 되돌린다.
(정확히는 Modified file들의 변경사항만 되돌리고, Untracked file들은 가만히 놔둔다.)

git checkout HEAD [파일명] : 해당 파일의 변경사항을 HEAD에 있는 버전으로 되돌린다


git add . : 서버로 새로 추가한 모든 파일의 목록을 전송한다. (git commit 혹은 push 하기 전에 반드시 add 먼저해야함.) (git add -i 혹은 -p 를 하면 대화식으로 추가가 가능) (git add * or -A 랑 다르네 뭔가)

(git add -u : 기존에 tracking하던 파일들만 add하기. 즉 modified file들만 add)
(git add -i : 를 이용하면 편리하게 원하는 파일들만 골라서 add할 수 있다. 13 14 15 a 이런식으로)

git reset <파일명> : add한 파일 취소하기(add는 했는데 commit은 아직 하기 전 상황에서 사용). 이 명령어는 git add와 정반대로 unstaging을 한다. 즉 git에 의해 파일이 관리를 받지 않도록 한다.

https://stackoverflow.com/questions/348170/how-to-undo-git-add-before-commit
http://stackoverflow.com/questions/1505948/how-do-i-remove-a-single-file-from-the-staging-area-of-git-but-not-remove-it-fro

git rm 파일명 : commit 된 파일이나 폴더를 삭제한다.(로컬에 있는 것까지 삭제해버리는듯.) reset만하면 staging만 안하는데, rm은 여기서 로컬 삭제까지 시켜버림.

git commit -m "메시지" : 현재 작업 상태의 스냅샷(백업)를 메시지와 함게 local repository에 저장
ex) git commit -m "something is changed" (workspace 안에서 실행. -a를 붙이면 add도 한번에 같이 처리 가능)

git push origin master : 서버로 commit 한 내용을 보냄 (git clone으로 workspace를 먼저 다운받은 뒤, 그 안에서 실행) ( -u는 최초의 branch를 push할 때 1회 해주어야 한다는 것 같음.)
git push가 하는 일은 local에 있는 branch를 remote에 있는 branch로 보내는 것이다.


- Git 을 local에서부터 시작해서 remote repo에 push 하기 : 주의 사항. remote repo에 파일이 0개인 상태여야만 깔끔하게 연결이 가능하다. (README, License, .gitignore 파일 등도 있으면 안됨.)

rm -rf .git : git init 취소하기. 즉 내가 작업하던 폴더의 기존 git 저장소 삭제하기(내 소스코드는 그대로지만, commit/branch 등의 내역들은 다 삭제된다.)

git init : 내가 작업하던 폴더를 git의 workspace로 만들기

git remote add origin 원격서버주소.git : git clone이 아닌, git init에서부터 시작 한 경우, 이 명령어를 통해 서버와 local repo를 연결해야한다. 당연히 이걸 하려면, 서버에서 먼저 repo를 생성한 다음 해야한다. ( 여기서 origin은 내가 add할 remote repo를 가리키는 별칭이다. 만약 여러개의 remote repo를 사용할 경우 origin2, origin3 등의 이름을 지어줄 수 있다.)

git add .
git commit -m "메시지"
(git branch --set-upstream-to=origin/master : 필요없는듯)
git pull origin master
git push origin master 



- Unstaging 하기
git rm --cached [path] : 특정 파일이나 폴더를 git repo에서 제외시키기(즉 다른 유저가 pull하면 해당 파일이 삭제됨)

- Change Tracking 중지하기
git update-index --assume-unchanged [path] : 내가 해당 파일을 local에서 수정한 모든 내용을 무시함. 즉 개발자가 앞으로 변경하지 않을 것이라고 생각되는 대규모의 sdk와 같은 파일에 대해 추적을 중단하여 git stat의 속도를 빠르게 하기 위함.

- 독립 작업 파일/폴더 설정하기
git update-index --skip-worktree [path] : local 전용 개발을 위한 독립 파일/폴더를 설정함. 즉 개발자가 오직 local에서만 사용할 목적의 수정이 일어나는 경우 설정해줌



- .gitignore 표준 파일
위의 내용으로 .gitignore파일을 만들고 시작하면 좋음. github에서도 선택을 하면 기본 제공한다고하는듯

- commit 해둔 버전으로 돌아가기 : 이건 정말 흔하게 많이 쓰이는 기능이다.
git checkout HEAD~5 : 최신 버전에서 5번 뒤로 가기
git checkout 9d51a7 : 9d51a7이름의 commit으로 돌아가기
git checkout master : 다시 최신버전으로 돌아오기
(여기에 -f 옵션을 추가하면, 수정하던 것을 다 버리고 해당 버전으로 옮겨감)
http://opendive.blogspot.kr/2015/06/git.html

- 특정 파일만 commit 해둔 버전으로 돌아가기 :
git checkout <commit> 파일명
http://ohgyun.com/443

- Git 의 branch 다루기 : branch란 내가 원래 작업하던 파일을 안전하게 격리보존한 상태에서(master), 새로운 작업을 다른 저장소에서 해줄 수 있게 하는 기능이다. 마치 backup본 저장시켜 놓고 새로 작업하는 것과 같음. 말그대로 가지치기

git checkout -b 브랜치이름 : 새로운 branch를 생성
git branch -d 브랜치이름 : 해당 branch를 삭제
git branch -m Old이름 New이름 : branch 이름 변경

git branch : 현재 있는 모든 branch 확인
git push origin 브랜치이름 : 해당 branch를 remote 서버에 저장한다.

git checkout master : 현재 workspace를 master branch에 저장해둔 상태로 되돌린다.
git checkout 브랜치이름 : 현재 workspace를 해당 branch로 이동한다. ( master , devel , debug 등등 )
git checkout 브랜치이름 --파일이름 : 해당 파일 하나를 해당 branch의 최신 버전으로 되돌린다. (SVN의 revert와 완전히 동일. 즉, 변경사항을 전부 날리고 원래 commit했던 파일로 복구하기)


- Auto-merge된 파일 되돌리기
git checkout HEAD~1 -- 해당파일

* 이때 --는 생략해도 되는데, 하면 더 좋은 이유는 똑같은 이름을 가진 branch와 파일이 서로 헷갈리는 것을 막기 위함이다. 즉 -- 를 붙이면 오직 파일중에서만 해당이름을 인식함.
https://stackoverflow.com/questions/41101998/git-checkout-vs-git-checkout

- 실수로 pull 한 작업 취소하기
git reset --hard

* 설명) 일단 pull은 아래와 동치이다.
git pull origin master = git fetch origin + git merge origin/master
이 작업 중에서 merge가 항상 문제인데, 이 merge는 git reset --hard하면 취소됨. 즉 git fetch origin만 한 상태로 돌아가짐.

- 실수로 Commit 한 작업 취소하기
git reset --soft HEAD~1 : 최근 HEAD에서 한단계로 돌아가, commit 한 작업만 취소하기
git reset --mixed HEAD~1 : 최근 HEAD에서 한단계로 돌아가, commit 한 작업과 add한 작업 취소하기
git reset --hard HEAD~1 : 최근 HEAD에서 한단계로 돌아가, commit 한 작업과 add한 작업을 완전히 삭제해버리기(되돌릴 수 없다.)

https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-Reset-%EB%AA%85%ED%99%95%ED%9E%88-%EC%95%8C%EA%B3%A0-%EA%B0%80%EA%B8%B0

- 실수로 Commit 한 작업에서 1개 파일만 취소하기
git reset --soft HEAD~1 : commit 한 내용을 취소한다.(HEAD = HEAD~1 가 되는듯?)
git reset HEAD <파일이름> : add한 내용을 취소한다.
git commit -c ORIG_HEAD : message를 수정하면서 다시 원래대로 commit한다. 

https://stackoverflow.com/questions/12481639/remove-files-from-git-commit


- 이미 push 한 작업에 대한 처리인듯?

git revert --hard commit이름 : 그동안의 커밋을 지우지는 않고, 예전으로 되돌아간다.


- Commit의 작업 내용 확인하기
git show [Commit]


- 두 Commit 간의 차이점 비교하기

git diff HEAD : 현재의 작업으로 변경한(commit하지 않은)내용을 확인
git diff <commit> : HEAD와 commit과의 차이 비교
git diff HEAD~3 : HEAD~3번째와 HEAD와의 차이 비교
git diff <commit1> <commit2> : 두 commit간의 차이 비교 (이때 나중에 만든 commit이 뒤쪽에 와야 +, - 기호가 제대로 표기됨..)
--color-words : 이 옵션을 주면 간결하게 색으로 구분할 수 있음

git diff --name-status HEAD : 변경된 파일의 이름과 상태만 출력
git diff --staged : add한 상태이나, commit되지 않은 변경내용을 확인

- 두 Branch 간의 차이점 비교하기
git diff branch1 branch2
git diff branch1:[파일경로] branch2:[파일경로]
https://stackoverflow.com/questions/4099742/how-to-compare-files-from-two-different-branches



- 두 Branch 합치기: 이게 branch를 다루는 데서 가장 어려운 부분일 듯.
git diff 브랜치1 브랜치2 : 두 branch사이의 차이점 비교

git rebase 목표브랜치이름 : 두개의 branch를 하나의 branch로 합치기 위해서 없애고, 현재의 branch에다가 목표브랜치의 commit을 가져와서 적용시킨다. (그다음 git checkout 를해서 목표브랜치로 이동한다음, 아래의 merge 명령어 실행)

git merge 가져올브랜치이름 --no-commit : 현재 branch에다가 해당 branch를 가져와서 합치되, commit은 하지 않고 staging만 한다.
    * git merge의 기본 동작은 다른 branch의 변경사항을 가져와서 auto-merge를 한 다음, conflict가 안나면 commit까지 해버리는 것이다.


- 다른 Branch에 있는 일부 변경사항(commit)을 가져오기
git cherry-pick <commit>
https://stackoverflow.com/questions/4315948/git-partial-merge-not-whole-branch


- 다른 Branch에 있는 새로운 파일을 복사해서 가져오기
git checkout 다른브랜치 파일이름
http://seorenn.blogspot.kr/2014/04/git.html


- 다른 Branch에 있는 파일 내용으로 덮어씌우기
git checkout -p 다른브랜치 파일이름
http://seorenn.blogspot.kr/2014/04/git.html

- 다른 commit에 있는 파일 내용을 가져오기
git checkout HEAD~3 -- 파일이름


- Remote에 있는 branch에 checkout하기
git fetch origin
git checkout [브랜치이름]
https://stackoverflow.com/questions/1783405/how-do-i-check-out-a-remote-git-branch

- Local에 있는 branch 삭제하기
git branch -d 브랜치이름
git branch -D 브랜치이름 (merge 안된 내용이 있어도 강제 삭제)


- Remote에 있는 branch 삭제하기
git push origin --delete 이름
* 단 Github에서는 master 브랜치를 삭제하려면, 웹사이트의 setting에 들어가서 default branch를 다른 걸로 변경한다음 삭제해야함.

- Branch 이름 변경하기: 이미 remote 에 branch를 push한 경우에 해당함. (push를 안한 경우 그냥 첫번 째 줄만 하면됨.)
git branch -m old_name new_name
git branch -a (local과 remote에 있는 모든 branch 이름확인)
git push origin --delete old_name (old branch 삭제)
git push origin new_name (new branch 올리기)




- Remote 다루기
git remote -v : 현재 remote 목록 확인
git remote add orgin https://github.com/bi-lab/deeplearning_tutorial.git : remote 추가
git remote remove origin : remote 삭제

- Remote에 권한이 없어서 403에러가 뜨는 경우(실제로 권한이 없을 수도 있다.)
git remote set-url origin https://YOURID@github.com/USERNAME/REPOSITORY.git

- Remote Repository에 새로 업데이트된 정보가 있는 지 확인하기: 
https://stackoverflow.com/questions/2514270/how-to-check-for-changes-on-remote-origin-git-repository

git remote update : remote의 정보를 가져오기만한다.(합치진 않음, git fetch origin 과 거의 같은 것으로 보임?)
git status



- Git 의 기타 명령어

git status : 파일들의 현재 상태 및 변경 사항등을 확인할 수 있다. 가령 add가 안된 파일 등이 나온다.

git log : commit log 살펴보기
git log --all --graph : commit log 에서 branch 정보를 그림으로 확인. 아주 유용함.

git tag 버전넘버 고유식별자(a1d2c3) : 버전 이름 달기

git fetchremote에 있는 최신 데이터를 내 로컬에 다운로드함. 그 이외 추가적인 작업은 전혀 안 함.(이걸해야 remote에만 존재하는 branch에 checkout을 할 수 있음.)
git merge : 서버에서 가져온 최신 내용을 내 local repo와 합침


# Detached Head에 대한 이해
HEAD: 내 현재 워크스페이스가 가리키는 commit을 의미함. Detached HEAD는 내 HEAD가 가장최신 지점을 가리키지 않는다는 의미임. 즉 몸통을 보고있다.

보통의 경우 branch를 checkout하면 항상 가장 마지막 commit 으로 이동되므로 HEAD가 항상 끝에 있다. 그런데 checkout을 branch가 아니라 특정 과거 commit 으로 돌아가는 경우 detached HEAD상태가 된다. Detached HEAD상태에서는 내가 새로 생성항 commit이 그 어떤 branch에도 속하지 못하고, 혼자서만 존재하게 된다. 즉 HEAD에만 새로운 commit을 붙일수가 있는 것인데 몸통에서 commit하면 갈데가 없는것.

- checkout으로 commit을 이동하다가 branch에서 떨어져 나온 commit 발생 시 해결 법:
우선 이런 상황에서는 다음과 같은 경고 메시지가 뜬다.
head detached from <~~~>
Warning: you are leaving 1 commit behind, not connected to any of your branches.

이런 현상이 발생하는 것은 checkout으로 branch가 아니라, 특정한 commit에서 작업하다가 새로운 commit을 생성하면, 그것이 특정한 branch에 속하지 않은 상태로 저장되기 때문이다. 반드시 모든 commit은 branch에 속해야하기 때문에 이를 해결하기 위해서는 우리가 원하는 branch로 checkout한 다음 아래와 같이 cherry-pick으로 낙동강 오리알이 된 commit들을 붙여야한다.

## 해결법 1: detached된 commit을 HEAD로 통합해서 가져오는 방법
git reflog : commit을 포함해 내가 HEAD를 이동한 흔적을 확인할 수 있다. 이 명령어로 branch에 안 붙은 commit의 id를 확인한 다음

git checkout <붙일 branch이름>
git cherry-pick <commit> <commit> <commit> ... : 이 명령어를 통해서 현재의 branch로 해당 commit을 가져온다.

http://stackoverflow.com/questions/9984223/what-happens-to-git-commits-created-in-a-detached-head-state


## 해결법 2: HEAD를 날려버리고, 과거 commit을 HEAD로 만들고 싶을 때
git checkout 과거commit : 이러면 detached HEAD상태가 됨
git branch -b tmp_master : 임시로 카피를 떠둠
git branch -D master: HEAD를 날림
git branch -M tmp_master master: master로 이름을 변경함

그런데 이렇게 번잡하게 안하고, git reset --hard HEAD~1 으로도 할 수 있을 것 같은데 정확히는 모르겠다.


- Git 의 log 쉽고이쁘게 보기
http://blog.kfish.org/2010/04/git-lola.html

vim ~/.gitconfig 에다가 다음의 설정을 입력한 후 저장한다.

[alias] lol = log --graph --decorate --pretty=oneline --abbrev-commit lola = log --graph --decorate --pretty=oneline --abbrev-commit --all lolan = log --graph --decorate --pretty=oneline --abbrev-commit --all --name-status
[color] branch = auto diff = auto interactive = auto status = auto

또는 다음을 실행해도 된다.
git config --global alias.lol "log --graph --decorate --pretty=oneline --abbrev-commit"
git config --global alias.lola "log --graph --decorate --pretty=oneline --abbrev-commit --all"
git config --global alias.lolan "log --graph --decorate --pretty=oneline --abbrev-commit --all --name-status"

사용법: git lol / git lola / git lolan


# git 협업 이슈 해결
## OS가 다른 환경에서 공동 작업시 생기는 CRLF문제
- Window는 line ending으로 \r\n (CRLF)를 사용하는 반면, Unix나 Mac OS에서는 \n (LF)만을 사용한다.

- 만약 Mac에서 작업한 코드를 윈도우에서 pull하게 되면 변경된 모든 파일의 line ending이 달라서 파일 전체에 대해 수정이 일어 났다고 인식해서 git diff를 하게되면 지옥이 펼쳐진다.

- 이러한 문제를 다음의 문서를 참조하면 거의 대부분 해결이 가능하다.

* 한글자료: https://www.lesstif.com/pages/viewpage.action?pageId=20776404
* 영어자료: https://stackoverflow.com/questions/170961/whats-the-best-crlf-carriage-return-line-feed-handling-strategy-with-git


- 위 해결 방법의 결론을 요약하면 다음과 같이 2가지 선택지가 있다.
1. 윈도우 사용자는
git config --global core.autocrlf true

Unix나 Mac 사용자는
git config --global core.autocrlf input

을 빠짐 없이 입력하면 아무런 문제가 생기지 않는다.(무조건 git repo에 LF만 올리는 방식)

2. 그러나 위 방법의 불편함을 없애려면, .gitattributes 파일을 repo에 추가시키면 알아서 각 contributor의 설정을 덮어 씌워서 해결된다.

그리고 다음 github에서 기본 공통 파일을 받을 수 있다.
https://github.com/alexkaratarakis/gitattributes


- 그런데 위의 세팅을 개발 처음단계에서 부터 했으면 괜찮은데, 개발 중간에 추가하게 된 경우 모든 파일의 line ending을 초기화해주어야한다. 다음을 참조

https://help.github.com/en/articles/dealing-with-line-endings#refreshing-a-repository-after-changing-line-endings


- 다음은 line ending을 무시하고 diff 및 merge를 하는 방법이다,
git diff master origin/master --ignore-space-at-eol
git merge origin/master -s recursive -Xignore-space-at-eol


## Conflict Resolve 하기(Resolve: HEAD, ===== 등을 제거하고 conflict난 코드를 1개로통합하는 작업을 의미함)

git pull : Automerge가 불가능한 파일들에서 conflict가 발생했다고 뜬다.
git status : Unmerged path에 conflict가 발생한 파일을 확인한다.
conflict가 일어난 파일을 에디터로 열어서 head <<< / >>> source 이런 부분을 다 지우고 제대로된 하나의 파일로 만들어준다. 이때 vim의 여러 단축기 (ex) 한줄 삭제 : dd)를 활용하면 좋다. 그리고나서 파일을 다 수정한다음,
git add -A
git commit -m "conflict merged"
git push origin master


## 3-way Conflict Resolve하기
Sublime_merge 에서 resolve를 클릭하면 [Commit A/Conflict Merge상태/Commit B] 세가지 화면이 보여지는 3-way merge tool이 실행된다. 이를 사용해서 수동으로 merge하면 된다.





- Git 프로젝트의 버전을 변경하기 : 현재 프로젝트를 특정한 branch 상태로 되돌아가는 것

git clone 깃주소
git checkout 버전명(ex. master , r0.7 등)



- gitignore 사용하기

.gitignore 파일을 이용해 특정한 확장자의 파일들이 add되는 것을 방지할 수 있다. 예를 들어 pyc같은 백업 파일 등이 이에 해당한다.

*.swp
*.pyc

등을 작성해서 .gitignore파일을 workspace에 넣어놓으면 알아서 add대상에서는 제외된다.



- Github 프로젝트에 contribute 하기: 아래의 과정을 수행하려면, 먼저 반드시 git repo에 push 할 수 있는 권한이 필요하다. 

git clone 깃주소
(코드 혹은 새로운 파일 등을 추가)
git pull
git add .
git config --global user.email "이메일주소"
git config --global user.name "이름"
git commit -m "메시지 작성"
git push origin master
(해당 서버 git의 아이디, 비밀번호 입력)



- Git config 설정하기
git config -l : 전체 config 목록 확인
git var -l : 전체 var 목록 확인

vim ~/.gitconfig

git config --global http.proxy ~~~
git config --global --unset http.proxy 


- Git config를 각 디렉토리마다 설정하기
git config --local user.email "이메일주소"
git config --local user.name "이름"


# Git 아키텍쳐 관리

반드시 최소한의 project 단위로 repo를 생성해야한다. 그렇지 않으면 두개의 project에서 동시에 작업이 일어났는데, 그것이 하나의 repo에 모두 저장이 되면 context가 꼬여서 도저히 작업을 할 수 없게된다.

또한 git repo내부에 또다른 git 을 생성하면 submodule의 개념으로 다른 repo에서 해당 작업을 알아서 clone해서 가져온다. 그러나 일반적으로는 사용하지 않는 방식. 거대한 프로젝트에서 사용


- Submodule 추가하기
git submodule add [remote-repo-URL] : remote repo를 "repo이름"을 기본 경로로하여 clone해서 submodule로 추가함
git submodule add [remote-repo-URL] [submodule_path]: remote repo를 지정한 경로에 clone해서 submodule로 추가함

git submodule add -b [branch이름] [remote-repo-URL] [submodule_path]: remote repo의 특정 branch를 지정한 경로에 clone해서 submodule로 추가함

* 위의 submodule add 명령을 한다음에는, 반드시 다음 명령을 수행해야함

git submodule update --init --recursive

그 후 git add / commit / push 실행

https://chrisjean.com/git-submodules-adding-using-removing-and-updating/
https://www.activestate.com/blog/2014/05/getting-git-submodule-track-branch


- Submodule 삭제하기: 안타깝게도, 현재 submodule은 수동으로 직접 삭제해줘야한다.
1. vim .gitmodules
-> 해당 submodule에 대한 내용삭제 후 저장
(만약 한개의 submodule만 존재하면, 그냥 .gitmodules 파일을 삭제해도 됨)

2. vim .git/config
-> 해당 submodule에 대한 내용삭제 후 저장

3. 수동 파일 삭제
git rm --cached [submodule_path]
rm -rf .git/modules/[submodule_path]
rm -rf [submodule_path]

4. git commit
git add .gitmodules
git commit -m "submodule removed"

https://gist.github.com/myusuf3/7f645819ded92bda6677


- Submodule 만 업데이트하기

git submodule update --init --recursive : 최초로 가져오는 submodule 업데이트
git submodule update --recursive : 그 다음부터는 이렇게

https://stackoverflow.com/questions/25957125/git-submodule-permission-denied



- git pull 하면서 한번에 submodule도 업데이트하기

git pull --recurse-submodules

https://stackoverflow.com/questions/1030169/easy-way-to-pull-latest-of-all-git-submodules



- Submodule 내용을 실수로 수정한 경우, dirty 라고나옴.
Submodule은 수정 불가능한 library로 취급됨. 따라서 이럴 때는 submodule 디렉토리에 들어간다음 git checkout . 을 해주면 됨.
https://stackoverflow.com/questions/4873980/git-diff-says-subproject-is-dirty/39803366



- Github 에서 5개의 Private repo가 사용 가능한 학생 계정 받기 ( 월 7달러짜리)

https://education.github.com/pack 에 들어가서 학교 이메일로 인증을 받으면 된다.




# Pull Request(PR 날리기)

아래의 링크에 잘 설명되어 있다.

핵심은 다음과 같다.
1. fork를 해서 push 권한을 갖고 있는 repo를 내 계정으로 가져온다.
2. remote add를 통해 PR을 날리고 싶은 repo를 새로 추가한다.
3. branch를 새로 만들고, fork한 내 repo에 push를 한다.
4. 그다음 "New pull request" 버틀을 클릭하고(항상 보임), 이를 통해 원래의 repo에 merge를 요청할 수 있다.

https://wayhome25.github.io/git/2017/07/08/git-first-pull-request-story/


# 기타 팁
리베이스 머지하면 갈라졌던 브랜치를 옮겨서 한줄기로 만드는 일을 한다. 구체적으로는 다른브랜치에 적용된 커밋을 가져와서 적용하는게 리베이스 임

깃허브는 컨트리뷰션하기위해서는 포크해서 고대로 복사해온다음 코드 수정하고 그 해닿레포가 내꺼를 풀하게만드는거라 풀 리퀘스트를 요청하는개념 임

머지할때 --노-에프에프 옵션을 반드시 줘야 브랜치를 머지한기록이 남아서 되돌릴수가 있음


- 주요 참고 자료
https://backlogtool.com/git-guide/kr/stepup/stepup3_1.html

rogerdudler.github.io/git-guide/index.ko.html

http://bcho.tistory.com/773

http://blog.outsider.ne.kr/572

http://bi.snu.ac.kr/~jkim/basic.html#1


'프로그래밍 > 오픈소스, 빅데이터' 카테고리의 다른 글

IPython Notebook 사용법  (0) 2015.06.02
빅데이터 플랫폼  (0) 2015.04.13
오픈소스 라이센스 및 개발 가이드  (0) 2015.04.13
openFramework, ofxFenster 버그 수정  (0) 2015.03.15
Git 사용방법  (0) 2014.05.07
by 곽동현 이스텔리앙 2014.05.07 21:12
| 1 2 3 4 5 |