====== Using git ====== ^ git 자주 사용하는 명령어 모음 ^^ ^ 깃 초기화 | git init 경로명 | ^ 깃 상태 확인 | git status | ^ 깃 저장소 복제 | git clone 원격저장소URL 새폴더이름 | ^ 파일 등록과 커밋 | git add 파일이름 -> git commit -> 에디터에서 커밋 메시지 작성 | ^ ::: | git commit -a -> 에디터에서 커밋 메시지 작성 | ^ ::: | git commit -am "커밋 메시지" | ^ 로그 확인 | git log | ^ 커밋 비교 | git diff | ^ 원격 저장소 별칭 확인 | git remote | ^ 원격 저장소 별칭과 URL 확인 | git remote -v | ^ 원격 저장소와 연결 | git remote add 원격저장소별칭 원격저장소URL | ^ 원격 서버 삭제 | git remote rm 원격저장소별칭 | ^ 커밋 가져오기 | git pull 또는 git fetch | ^ 커밋 전송하기 | git push 원격저장소별칭 브랜치이름 | ^ 현재 브랜치 확인 | git branch | ^ 브랜치 생성 | git branch 브랜치이름 | ^ 브랜치 이동 | git checkout 브랜치이름 | ^ 스태시 저장 | git stash | ^ 스태시 읽기 | git stash pop | ^ 브랜치 병합 | git merge 브랜치이름 | ^ 리베이스 병합 | git rebase 브랜치이름 | ^ 리셋 | git reset 옵션 커밋ID | ^ 리버트 취소 커밋 | git revert 커밋위치 | ^ 태그 관리 | git tag | ^ 태그 전송 | git push 원격저장소별칭 태그이름 | ^ 서브모듈로 연결 | git submodule add 원격저장소URL 폴더이름 | ===== why git? ===== * 분산버전관리 (Distributed Version Control System) -> 이것이 주는 장점? -> 기대효과 * 사용자의 요구사항 * 추가할 기능 많음; 각 기능별로 작업 이력을 git commit에 저장하므로 작업 이력을 관리 할 수 있음 * 항상 모든 이슈사항은 응급!; 버그나 수정사항들이 발생하여 프로그램을 수정해야 할 경우, 요청자는 항상 빠르게 대처 가능. * 개발자의 요구사항 * 개발과 실제 운용 소스가 다름; 현재 작업 중인 내용이 있다면 현재 작업 내용을 백업하고, 운영(서비스)되는 배포판의 소스를 가져와서 수정한 후 배포하고 수정된 내용을 작업 중이던 소스에도 적용해야 하는 경우에 git은 유연하게 대처 가능. * 개발 사항에 대한 이력이 필요; 각 작업별로 언제, 어떤 내용을, 누가 했는지 이력을 관리하면 프로젝트 관리에 이점. * ==== pros. and cons. ==== === pros. === * 강력한 브랜치 기능; 브랜치를 쉽게 만들고 병합 가능, 일시적인 작업에 대한 이력 관리 쉬움 * 속도와 성능; 처리 속도가 빠르고 기능이 많음 * 분산작업; 장소에 구애 받지 않고 협업이 가능(메인 서버에 연결없이 작업 가능), 저장소의 완전한 복사본으로 작업 * 데이터 보장성; 모든 파일을 암호화하여 저장 * 무료; 비용 안 듬. === cons. === * 배우기 어려움. * 어떻게 사용하는 가가 중요하므로 잘 정의된 개발 프로세스가 필요. * git hub와 같은 서비스를 이용할 경우 비용 발생. (bitbucket은 5명까지 무료 사용 가능) ===== setting up a git ===== * 설치 osx, windows, linux * global settings ===== git 시작하기 ===== * 생성 init, clone * git이 파일(디렉토리)를 관리하는 방법 * working directory -> stage area -> git repository * working directory; 사용자가 작업하는 디렉토리 * stage area; git repository에 저장될 파일 목록 * git repository; git이 파일을 저장하는 저장소 * git repository의 파일 관리 add, remove, commit * 상태 보기 status * 뒤로 되돌아 가기 reset * 버전 되돌아보기 log * 태그 붙이기 tag * 이건 저장하지 않을 거야 .gitignore * repository에 넣으면 좋은 것들; 스펙문서, 설계서, 매뉴얼, 도움말, 소스코드, 이미지, 외부라이브러리, 빌드스크립트 * 넣지 말아야 할 것들; 바이너리, 설치본, 영업자료, 마케팅자료, 판매자료 등. * stash * HEAD; 최종 커밋 작업의 위치 포인터, HEAD와 스테이지 영역의 내용을 합쳐 다음 커밋을 생성 * ^,~; HEAD^^, HEAD~~, HEAD^3, HEAD~3 * AHEAD; 서버로 전송되지 않은 로컬 커밋 * BHEAD; 로컬로 내려 받지 않은 커밋 * pull -> 작업 -> commit -> pull -> push * 대부분의 git 명령어는 working tree clean 상태에서 작업 * reset; 저장소를 외부에 공개했거나 공유하고 있다면 주의해서 리셋 사용 * revert; 기존 커밋을 남겨 두고 취소에 대한 새로운 커밋 생성. * reset vs. revert; 커밋 정보의 삭제 여부. 리셋: 커밋 삭제, 리버트: 취소 커밋 생성 * versioning; major.minor.patch, SemVer(Semantic Versioning) * RC(Release Candidate), GA(General Availability), M(Milestone) * tag; 특정 커밋에 태그 부착 * Annotated; 태그 이름 + 정보 포함 * Lightweight; 태그 이름만 포함 * ./git/ref/tags 폴더 $ git config --global core.editor "에디터경로" $ git config --global credential.helper cache # 인증정보 캐시 $ git init $ git clone 원격저장소URL 새폴더이름 $ git add 파일이름 $ git rm --cached 파일이름 # 스테이지에서 파일이름 삭제, 파일 등록 후 커밋하지 않음 $ git reset HEAD 파일이름 # 한 번이라도 커밋을 했을 경우 $ git status $ git mv 파일이름 새파일이름 # 파일 이름 변경, mv -> git rm -> git add 와 같음 $ git commit $ git commit -a # 커밋 하기 전 자동으로 모든 파일을 등록 후 커밋 $ git log $ git log --pretty=short $ git show 커밋ID # 특정 커밋의 상세 정보 $ git diff # 워킹 디렉토리와 스테이지 영역 간 변경 사항 $ git diff HEAD # 최신 커밋과 워킹 디렉토리 간 변경 사항 $ git checkout -- 수정파일이름 # 수정된 파일을 커밋 상태로 되돌림 $ git add 수정파일이름 $ git commit -m "커밋메시지" $ git commit -am "커밋메시지" $ git commit --allow-empty-message -m "" # 빈 커밋 작성 $ git commit --amend # 방금 전에 작성한 커밋 메시지 수정 $ git commit -v # 커밋 메시지에 diff 내용 추가 $ git stash # 현재 작업들을 임시 스택에 저장, 워킹디렉토리+스테이지영역 파일까지 모두 저장 $ git stash save $ git stash save "WIP: message" # 작업 중인 내용을 강제 커밋(비추천) $ git commit -am "temp" # 임시 커밋 $ ... # 다른 브랜치 작업 후 현재 브랜치로 $ git reset -soft HEAD^ # 리셋 복워 ### $ git stash list # 스태시 리스트 $ git stash show # 스태시와 워킹디릭토리 차이 $ git stash show -p stash{0} # 상세 $ git stash pop # 스태시 스택에서 pop, 자동 삭제, 충동시에는 삭제 안함 $ git stash apply --index # 스테이지 등록된 상태까지 복구 $ git stash branch 브랜치이름 # 스태시를 브랜치에 적용 $ git stash apply # 스태시 스택에서 읽어오지만 삭제하지 않음 $ git stash apply stash@{0} # 0번 스태시로 복원 $ git stash drop # pop 충돌시, apply 했을 시 스태시 삭제 $ git clean # 워킹디렉토리 안에 추적되지 않는 파일을 모두 삭제, -f 강제, -n 가상으로 처리하고 사용자 확인, -d untracked 상태의 파일만 삭제, -x .gitignore 설정된 파일까지 삭제 $ git log --oneline # 로그 한줄씩 $ git reset --hard HEAD^^^ # HEAD로부터 세번째로 $ git rest 옵션 커밋ID # 옵션: soft; 스테이지 영역을 포함한 상태로 복원, mixed; 기본값, hard: 실제 파일이 삭제된 이전 상태로 복원 $ git reset --soft HEAD~ # 이전 커밋으로 soft 옵션을 사용한 리셋. 파일을 수정하고 add 명령어로 스테이지 영역에 올려 커밋을 실행하기 직전의 단계로 되돌림 $ git commit --amend # 위와 유사함 $ git reset --mixed 커밋ID $ git reset 커밋ID # 위와 같은 명령 $ git reset --mixed HEAD~ # 리셋한 후 스티이지 상태까지 복원하지 않음, 커밋하려면 add 명령어를 먼저 실행 $ git reset --hard HEAD~ # 사용한 커밋 이후의 모든 내용 삭제, 워킹 디렉토리 내용도 함께 삭제 # 스테이지 리셋 $ git add 파일이름 $ git reset 파일이름 $ git reset --mixed HEAD 파일이름 # 파일 이름을 지정하여 리셋하면 해당 파일은 unstage 상태 $ git reset 커밋ID 파일이름 # 작업취소 $ git reset --hard HEAD # 병합 취소 $ git reset --merge HEAD~ $ git revert HEAD # 현재 커밋을 리버트, 새로운 리버트 커밋 생성 $ git revert 커밋ID $ git revert 커밋ID .. 커밋ID # 범위 연산자 ..를 사용, 여러 커밋 리버트 $ git revert --mainline 숫자 병함커밋ID # 리버트로 병합 취소 $ git tag $ git tag -l # 또는 --list $ git tag -a 버전 # annotated 태그 생성, 에디터로 작성 $ git log --decorate $ git tag -a 버전 -m "메시지" # 에디터 안뜸 $ git tag -d 태그이름 $ git show 태그이름 # 태그의 상제 정보 확인 $ git tag 태그이름 # lightweight, 커밋의 체크섬만 가지고 있다 $ git tag -a 태그버전 커밋ID # 특정 커밋ID에 태그 버전 생성 $ git checkout 태그버전 # 태그버전으로 체크아웃, 이 경우 추가 커밋 작성 불가 $ git checkout -b 브랜치이름 태그이름 # 태그 기준으로 브랜치 생성 $ git push 태그이름 # 원격저장소에 태그이름 push $ git push 원격저장소이름 --tags # 모든 태그를 한꺼번에 원격저장소에 push $ git push --delete 원격저장소이름 태그이름 # 원격저장소의 태그 삭제 $ git push 원격저장소이름 로컬태그이름:원격저장소태그이름 # 원격저장소에 로컬과 다른 이름으로 태그 전송 ===== git branch ===== * 기준이 되는 메인 프로젝트와 개발 프로젝트 혹은 디버그 프로젝트, 핫픽스 프로젝트 master, branch * 가지 치기, 가지 잘라내기 * 지금 작업하고 있는 위치 head * 개발 브랜치에서 핫픽스 브랜치로 전환 checkout * 메인+브랜치=>새로운 메인, 브랜치1+브랜치2=>새 버전의 브랜치1 merge * 병합(merge)하기 전에 diff * rebase * Fast-Forward 병합; 순차적 커밋에 맞추어 병합 처리 * 3-Way 병합; 공통 조상 커밋 + 공통조상커밋을 포함하는 브랜치 + 새로운 브랜치 => 하나로 병합, 병합을 성공적으로 완료 후 새로운 커밋을 추가로 생성 (=병합 커밋) * Rebase; 두 브랜치를 서로 비교하지 않고 순차적으로 커밋 병합. 병합 커밋 없음, 브랜치의 마지막을 가리키는 커밋 위치 다름. 원격 저장소에 푸시하면 리베이스 사용하지 않는 것이 원칙. $ git branch # 브랜치 목록 $ git branch 브랜치이름 커밋ID # 커밋ID를 기점에서 브랜치이름으로 브랜치 생성, 커밋ID 없으면 HEAD 포인터 기준 $ git rev-parse 브랜치이름 # 커밋 해시값(SHA1) 확인 $ git branch -v # verbose, 브랜치 세부 사항 $ git checkout 브랜치이름 # 브랜치이름으로 이동, working tree clean 이어야 함, HEAD 포인터도 이동 $ git checkout -- 파일이름 # 파일로 체크아웃 $ git checkout - # 이전 브랜치로 이동 $ git checkout -b 브랜치이름 # 브랜치이름 생성하고 그 브랜치로 이동 $ git checkout 커밋해시키 # 해시키로 체크아웃 $ git checkout HEAD~1 # 한 단계 전 $ git checkout - # 현재로 이동 $ git log --graph --all # 텍스트 그래프 출력 $ git show-branch --more=10 # 출력 커밋 개수 제한 $ git merge 브랜치이름 # 현재 브랜치 + 브랜치 병합 $ git merge 브랜치이름 --edit # --edit 옵션 없으면 커밋 메시지 자동생성, 옵션 붙이면 메시지 에디트 $ git reset --hard HEAD^ # 방금 병합한 내용 취소 $ git branch -d 브랜치이름 # 병합을 완료한 브랜치만 삭제 가능 $ git merge --abort # 병합시 충돌일 경우, 병합 취소 $ git ls-files -u # 충돌한 파일들의 집합 확인 $ git commit -m "resolve complicit" # 충돌 해결 후 커밋 $ git branch --merged # 병합한 브랜치 표시 $ git branch --no-merged # 병합하지 않은 브랜치 표시 $ git rebase 원본브랜치 # merge(현재기준에서 파생브랜치랑 병합)와 반대로 파생에서 원본으로 병합, 브랜치의 HEAD 포인터가 다름 $ git checkout 원본브랜치 $ git merge 대상브랜치 # rebase 후에 merge 다시 함. $ git rebase --continue # rebase 병합시 충돌 났으면 그것을 해결하고 충돌된 부분들을 한단계씩 진행, 리베이스 안되면 git add 명령어 $ git rebase --abort # 리베이스 취소 $ git rebase -i HEAD~3 # 커밋 묶기, 이 예에서는 커밋 3개가 커밋 하나로 변경 ===== 원격 repository ===== * Protocols; Local, HTTP, SSH, Git * 서버 repository에서 혹은 서버 repository으로 pull, push * 업스트림 트래킹; 리모트 브랜치와 로컬 브랜치를 연결하는 중간 다리 역할 * ./git/config $ git remote add 원격저장소별칭 폴더경로 # 로컬 저장소를 서버로 이용 $ git remote add 원격저장소별칭 원격저장소URL # 원격 저장소 연결 $ git remote # 원격 저장소의 이름 출력 $ git remote -v # verbose, URL도 확인 $ git remote rename 변경전이름 변경후이름 $ git remote show 원격저장소이름 # 상세 정보 $ git remote rm 원격저장소이름 # 원격 저장소 삭제 $ git push 원격저장소별칭 브랜치이름 # 원격저장소/브랜치에 현재 브랜치 전송 $ git push -u 원격저장소별칭 브랜치이름 $ git push 원격저장소별칭 로컬브랜치이름:새로운원격브랜치 $ git pull $ git fetch $ git merge 원격저장소별칭/브랜치이름 $ git branch -r # 리모트 브랜치 목록 $ git branch -a # 모든 브랜치 정보 확인 $ git branch -vv # 트래킹 브랜치 목록 $ git checkout --track 원격저장소별칭/원격브랜치 # 업스트림 브랜치 생성 $ git checkout -b 새이름 원격저장소별칭/브랜치이름 # $ git branch -u 원격저장소별칭/브랜치이름 # 업스트림 연결, -u(==--set-upstream-to), 기존 브랜치를 특정 원격 브랜치로 추적 $ git push --set-upstream 원격저장소별칭 원격브랜치 # 업스트림 설정 $ git merge 원격저장소별칭/브랜치이름 # 리모트 브랜치와 병합 $ git checkout -b 임시브랜치이름 원격저장소별칭/원격브랜치 # 원격 브랜치의 포인터를 사용하여 임시 브랜치 생성하거나 직접 체크 아웃 $ git branch -d 브랜치이름 # 브랜치 삭제, -d 옵션은 스테이지 상태가 깨끗할 때만 삭제 허용 $ git branch -D 브랜치이름 # 브랜치 강제 삭제 $ git push 원격저장소별칭 --delete 리모트브랜치이름 # 리모트 브랜치 삭제 ===== git flow stories ===== * 도구의 사용법 보다 사용 방법이 더 중요하다. * 메인 프로젝트는 놔두고 개발 프로젝트로 작업하기 * master에서 develop 브랜치 만들어 작업하고 develop에서 release 브랜치 생성, release * 한참 개발 중인데 급한 버그 수정 요청이 들어왔다 * master에서 hotfix 브랜치를 만들어 작업하고 master와 현재 개발중인 브랜치로 merge * 하나의 프로젝트 여러 명의 개발자 * develop 브랜치에서 각 개발자별로 브랜치 생성후 작업 (보통 기능별로 개발자에게 분배) 혹은 develop에서 기능별 브랜치 생성 * git-flow, github-flow, gitlab-flow 가 조금씩 다르다. ===== submodule ===== * 저장소를 모듈화, 저장소 분리 * 저장소 하나가 다른 깃 저장소를 포함하는 형태 * 메인 저장소 <-> 부 저장소 * 2개 이상인 저장소를 부모/자식 관계로 연결 * 서버 저장소를 서브폴더 형태로 취급 * .gitmodules * 메인에서 서브저장소 추가 -> .gitmodules 추가 -> 커밋 * 저장소마다 별도로 커밋 수행 * 메인 저장소는 서브모듈의 변경 내용을 모니터링, 서브모듈이 변경되면 메인 커밋 $ git submodule -help $ git submodule add 원격저장소URL 폴더이름 # 메인저장소에서 작업, 서브저장소 등록 $ git add .gitmodules # .gitmodules 등록 $ git commit -m "add submodule" # 커밋 $ git submodule init # 서브모듈 초기화, 하위 저장소의 내용을 가져오기 위해. 메인저장소에서 실행 $ git submodule update # 서브모듈 업데이터 # submodule 사용시, 아래 두 줄은 세트라고 생각하면 됨. $ git pull origin master $ git submodule update ===== fork, pull request ===== * PR(Pull Request) @github, MR(Merge Request) @gitlab * fork -> clone forked repository -> make branch and move to branch on forked repository -> coding jobs on branch -> push -> pull request ===== Etc ===== * refs, reflog * file annotation; blame, * replace; 기존 커밋을 다른 커밋인 것처럼 변경 * garbage collect; 연결고리가 없는 고립된 객체들, 주로 리셋/리베이스 등을 자주할 때 발생 * prune * rerere(reuse recorded resolution); 어떤 문제로 충돌이 발생할 때 이를 기록 $ git rev-parse 브랜치이름 # 브랜치이름의 해시값 확인 $ git show 해시값 $ ls .git/refs -all # 저장소 refs 파일 목록 $ git reflog # reflog, 시스템에서 정의한 며칠 간의 기록만 보관 $ git blame 파일이름 # 누가 코드의 어느 라인을 수정했는지 파악할 때 유용 $ git blame -L 시작줄,마지막줄 파일이름. -e: 사용자 이름 대신 이메일 출력, -w: 공백 문자 무시, -M: 같은 파일 내에서 복사나 이동 감지, -C: 다른 파일에서 이동이나 복사된 것을 감지 $ git replace 커밋ID1 커밋ID2 # 커밋ID1 -> 커밋ID2 연결 $ git gc --auto $ git prune --dry-run --verbose # 객체 삭제, --dry-run: 실행하지 않고 작업할 내역만 출력, --verbose: 작업한 결과 출력 $ git reflog expire --expire=now --expire-unreachable-now --all # reflog 삭제 $ git prune --expire now -v # 객체 삭제 실행 $ git remote prune # 원격 저장소의 브랜치를 병합한 후 삭제, 삭제된 원격 저장소 브랜치는 더이상 참조할 수 없다 $ git fetch --prune # 오래된 브랜치 정리 $ git config rerere.enabled true # rerere 기능 사용, --global 옵션 가능 $ git rerere status # 상태 ===== references of git ===== * [[http://rogerdudler.github.io/git-guide/index.ko.html|git 간편 안내서]] * [[http://git-scm.com/book/ko|Pro git 온라인 북 - 한글판]] * [[http://dogfeet.github.io/articles/2011/a-successful-git-branching-model.html|git-flow]] * [[http://namhyung.github.io/git-user-manual-ko/|git 사용자 설명서]] ====== Git 사용법 정리 ======   *basic concept workspace -> staging area(index) -> local repository -> remote repository stash *file status lifecycle 1. untracked; git에 의해 추적되지 않는 파일. add the file 후 tracked로 변경됨 2. tracked; git에 의해 추적되는 파일. remove the file 하면 untracked로 변경됨   2.1 unmodified; 수정되지 않은 파일. edit the file 후 modified로 변경됨   2.2 modified; 수정된 파일. stage the file    2.3 staged; staging area에 있는 파일. commit 후에는 unmodified로 변경됨 *기본 동작 만들기 (저장소 받아오기) 파일 저장: 생성, 삭제, 수정 로컬 저장소 저장: 생성, 삭제, 수정 원격 저장소 저장: 생성, 삭제, 수정 브랜치: 생성, 삭제, 수정, 이동, 병합 *install git  -Unix/Linux  -Mac  -Windows *config git  .gitignore  Glob pattern *starting w/ git  git init; create local repository  git remote add ; connect local repository with remote repository  git pull; get data from remote repository git clone   ex) git clone /local/repository/path  ex) git clone user@hostname:/remote/repository/path *basic commands  git add; workspace -> staging area(index)  git commit -a; workspace -> local repository  git push; local repository -> remote repository git fetch; remote repository -> local repository  git merge; merge git pull; fetch & merge git status; modified, staged or unstaged  git diff; show differences between staged and unstaged  git diff --staged or git diff --cached; show differences between staged and committed *snapshot *branch  -create branch  git branch   git checkout git branch -b ; branch & checkout -delete branch  git branch -d -merge branch  git checkout master  git merge branch -list branch  git branch  git branch --no-merged  git branch -merged *rebase *tag  -create tag  git tag   git tag -a -delete tag  git tag -d -list tag  git tag *rollback  git checkout --; rollback unstaged file git reset HEAD; unstage staged file git fetch origin; rollback commited file  git rest --hard oring/master *stashing    * gitignore 재 적용 git rm -r --cached . git add . git commit -m "git ignore applied and fixed untracked files" git push git pull git add . git commit -m "git ignore applied" git push references * pro git 한글판 http://git-scm.com/book/ko/ * git 간편안내서 http://rogerdudler.github.io/git-guide/index.ko.html  * [[https://shanepark.tistory.com/214|Sourcetree 에서 잘못된 비밀번호로 저장소 접근 안될때 해결방법]] * [[https://zi-c.tistory.com/entry/Sourcetree%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-git-merge-commit-conflict-%EC%B6%A9%EB%8F%8C-%ED%95%B4%EA%B2%B0|Sourcetree를 활용한 git merge commit conflict 충돌 해결]] * [[https://gitabout.com/8|Git commit 되돌리기 명령어 Reset 과 Revert]] * [[https://github.com/k88hudson/git-flight-rules|Flight rules for Git]] * [[https://velog.io/@u-nij/Git-Flow-Commit-message-Issue-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0|Git-Flow & Commit message & Issue 이용해서 협업하기]] * [[https://hyeonic.tistory.com/181|[git, github] git issue 생성 및 작성 방법 (1)]]