Tag

Git


git를 사용하면서 자료를 정리한다. 


git 유용한 싸이트들


프로깃 한글 

http://dogfeet.github.io/articles/2012/progit.html


깃 튜토리얼

http://schacon.github.io/git/gittutorial.html


에브리데이 깃

http://schacon.github.io/git/everyday.html


깃이 좋은 이유

http://git-scm.com/about


깃 레퍼런스

http://gitref.org/


깃 프랜치 배우기

http://learnbranch.urigit.com/


git manual

http://namhyung.springnote.com/pages/3132772


git tutorial 

http://www.funit.net/git

http://gitimmersion.com/


suapapa 의 질문

https://kldp.org/node/118784


git util


tig : terminal 에서 텍스트로 볼 수 있는 유틸. sudo apt-get install tig

gitg : gtk+/GNOME 기반

gitk : tcl/tk 기반

기타 git client들 : http://git-scm.com/downloads/guis


환경 설정

git config --global --list

현재 설정정보 조회할 수 있습니다. --global옵션은 전역설정에 대한 옵션이며 현재 프로젝트에만 적용할때는 주지 않습니다.


git config --global user.name "사용자명" 

사용자명을 등록합니다 (필수)


git config --global user.email "이메일주소" 

이메일 주소를 등록합니다. (필수)


git config --global color.ui “auto”

터미널에 표시되는 메시지에 칼라를 표시해줌


git config --global core.editor "vim"

기본 에디터를 vim으로


git config --global merge.tool meld

kdiff3, tkdiff, meld, xxdif, emerge, vimdiff, gvimdiff, ecmerge, opendiff, p4merge 

등을 지원한다. p4merge가 제일 좋다고 하지만 난 meld가 익숙해서 젤 편함.


git config --list


git config user.name


~/.gitconfig 

특정 사용자에게만 적용되는 설정파일

이 파일에 모두 저장됨. 이 파일을 수정해도 됨.

git config --global로 읽고 쓸 수 있음

우선순위 3


/etc/gitconfig

전역적으로 적용되는 설정파일

git config --system으로 읽고 쓸 수 있다.

우선순위 2


.git/config

특정 프로젝트에만 적용된다.

우선순위 1


Git 사전지식

git의 저장소는 3가지 단계로 나누어 집니다. 

커밋한 소스가 보관되는 저장소와 현재 프로젝트 파일들이 있는 작업트리, 저장소와 작업트리사이의 버퍼영역으로 커밋될 대상이 저장되는 스테이징 영역입니다.

git은 빈 디렉토리는 추적하지 않습니다.

형상관리를 하지 않을 파일은 .gitignore 파일 에 추가합니다.

HEAD는 현재 브랜치의 가장 최신커밋을 의미한다.

기본원격 저장소를 origin이라고 부릅니다.


.gitignore

정규표현식 가능

#으로 시작하면 주석

디렉토리는 끝에 /를 붙이면 된다.

! 느낌표로 시작하는 패턴은 무시하지 않는다.


만약, /폴더1/폴더2/폴더3 에서 폴더2 이하의 폴더를 무시하게 설정할 때

**/폴더2/


만약, 폴더3 이하를 무시하고 싶으면

**/폴더2/폴더3/


gitignore 설정 후에 항상 Tacking file이나 folder의 cache를 삭제해주고 다시 파일을 무시하지 않게 수정했으면 수정해야 한다.

전체 cache를 다 지우고 다시 cache 하는 방법

- git rm -r –cached . => 현재 repository의 cache를 삭제

- git add . => 다시 tracking하도록 설정


기본적인 명령어

git --version

현재 git의 버전을 확인합니다.


git init

현재 디렉토리에 git 저장소를 생성합니다.


git add 파일명

git add는 2가지를 하는데 untracked files의 파일들을 git가 추적하도록 하거나 파일은 수정했지만 아직 스테이징 영역에 올라가지 않은(Changed but not updated) 파일들을 스테이징 영역에 올립니다. -i 옵션을 주면 대화형모드가 시작되며 파일의 일부분만 선택해서 스테이징하는 것이 가능합니다. -p 옵션을 사용하면 -i 대화형모드없이 바로 패치모드를 사용할 수 있습니다.


git commit -m "커밋메시지"

스테이징 영역에 올라가 있는 파일들을 커밋합니다. -m 은 커밋메시지를 주는 옵션으로 여러 줄의 커밋메시지를 쓸 경우 -m 을 여러개 사용할 수 있습니다. -a 옵션을 사용하면 스테이징에 올리는 작업과 커밋을 동시에 할 수 있습니다.(추적되지 않는 파일은 추가하지 않습니다.) -m을 사용하지 않을때 -v옵션을 사용하면 편집기에 커밋하려는 변경사항의 다른점을 보여줍니다. 특정파일만 커밋하려면 마지막에 파일명을 추가해주면 됩니다.


git commit -C HEAD -a --amend

지정한 커밋의 로그메시지를 다시 사용하여 기존커밋을 수정합니다. -c를 사용하면 기존메시지를 수정할 수 있는 편집기를 실행해 줍니다.


git status

커밋되지 않은 변경사항을 조회합니다.


git diff

스테이징영역과 현재 작업트리의 차이점을 보여줍니다. --cached 옵션을 추가하면 스테이징영역과 저장소의 차이점을 볼 수 있다. git diff HEAD를 입력하면 저장소, 스테이징영역, 작업트리의 차이점을 모두 볼 수 있다. 파라미터로 log와 동일하게 범위를 지정할 수 있으며 --stat를 추가하면 변경사항에 대한 통계를 볼 수 있습니다.


git diff-tree -p 비교할브랜치명

git read-tree로 옮겨온 브랜치와 원래 브랜치를 비교 할 때 사용한다.


git difftool HEAD HEAD^ -y

설정에 diff.tool의 값에 있는 difftool을 찾아서 실행한다.

-y 하면 자꾸 물어보는거 자동으로 y 해준다.


git mv 파일명 새파일명

기존에 존재하는 파일을 새파일로 이동합니다. 변경이력은 그대로 유지합니다.


git rm 파일또는 디렉토리명

git에서 파일 또는 디렉토리 제거


git checkout -- 파일명

아직 스테이징이나 커밋을 하지 않은 파일의 변경내용을 취소하고 이전 커밋상태로 돌립니다. svn에서 revert와 동일합니다.


Branch와 Tag

git branch

현재 존재하는 브랜치를 조회합니다. -r 옵션을 사용하면 원격저장소의 브랜치를 확인할 수 있습니다. 


git branch 브랜치명B 브랜치명A

브랜치명A에서 새로운 브랜치 브랜치명B를 만듭니다. (git에서 기본 브랜치는 master라는 이름을 사용합니다.)


git branch 브랜치명

브랜치명의 새로운 브랜치를 만듭니다.(체크아웃은 하지 않습니다.)


git branch -d 브랜치명

브랜치를 삭제합니다.


git branch -m 존재하는브랜치명 새로운브랜치명

존재하는 브랜치를 새로운브랜치로 변경합니다. 이미 존재하는 브랜치명이 있을 경우에는 에러가 나는데 -M 옵션을 사용하면 이미 있는 브랜치의 경우에도 덮어씁니다.


git tag 태그명 브랜치명

브랜치명의 현재시점에 태그명으로 된 태그를 붙힙니다. git tag만 입력하면 현재 존재하는 태그 목록을 볼 수 있습니다.


git push 원격저장소명 태그명

태그를 원격저장소에 등록하기

예) git push origin 1.0 


git checkout 브랜치명/태그명

해당 브랜치나 태그로 작업트리를 변경합니다. 


git checkout -b 브랜치명B 브랜치명A

브랜치명A에서 브랜치명B라는 새로운 브랜치를 만들면서 체크아웃을 합니다.


git rebase 브랜치명

브랜치명의 변경사항을 현재 브랜치에 적용합니다.


git merge 브랜치명

브랜치명의 브랜치를 현재 브랜치로 합칩니다. 

--squash 옵션을 주면 브랜치명의 모든 커밋을 하나의 커밋으로 만듭니다.

-s subtree 를 쓰면 하위 프로젝트를 머지할 때 유용하다. subtree merge는 하위 프로젝트가 합쳐진것처럼 보일 정도로 한 프로젝트를 다른 프로젝트의 하위 디렉토리에 연결해 준다.


git read-tree --prefix=rack/ -u rack_branch

rack 이라는 디렉토리에 rack_branck 라는 브랜치의 내용을 집어 넣어준다. (단순 복사한것과 다름 - 브랜치를 자유롭게 바꿀 수 있고 최신 버전의 rack프로젝트의 코드를 끌어올수 있다는점)


git cherry-pick 커밋명

커밋명의 특정 커밋만을 선택해서 현재 브랜치에 커밋으로 만듭니다. -n 옵션을 주면 작업트리에 합치지만 커밋은 하지 않기 때문에 여러개의 커밋을 합쳐서 커밋할 수 있습니다.


로그 관리

git log

커밋로그들을 볼 수 있으면 -1나 -2같은 옵션을 주어 출력할 커밋로그의 갯수를 지정할 수 있습니다. --pretty=oneline 옵션을 주면 한줄로 간단히 보여주고 --pretty=format:"%h %s"처럼 형식을 정해줄 수 있습니다. -p 옵션을 사용하면 변경된 내용을 같이 보여줍니다. --since="5 hours" 이나 --before="5 hours"같은 옵션도 사용가능합니다. --graph 옵션을 주면 브랜치 트리를 볼 수 있습니다.


git log 커밋명

해당 커밋명의 로그를 볼 수 있습니다. 커밋명A..커밋명B (마침표2개)와 같이 입력하면 커밋명A이후부터 커밋명B까지의 로그를 볼 수 있습니다. ^은 -1과 동일해서 HEAD^라고 하면 최신바로 이전 커밋이고 HEAD^^^와 같이 쓸 수 있으며 HEAD~3을 하면 HEAD의 3개 이전의 커밋을 뜻합니다.


git log -p -m

현재까지 changeset을 모두 추출


git log --author=bunhere | git shortlog

bunhere가 작업한 commit들을 보기



git blame 파일명

갈 줄 앞에 커밋명과 커밋한 사람등의 정보를 볼 수 있습니다.


git blame -L 10,15 파일명

-L 옵션을 사용하면 10줄부터 15줄로 범위를 지정해서 볼수 있고 15대신 +5와 같이 사용할 수 있습니다. 숫자의 범위 대신 정규식도 사용이 가능합니다.


git blame -M 파일명

-M 옵션을 사용하면 반복되는 패턴을 찾아서 복사하거나 이동된 내용을 찾아줍니다.  -C -C 옵션을 사용하면 파일간의 복사한 경우를 찾아줍니다. -C -C는 git log에서도 사용가능하며 내용의 복사를 찾을때는 git log에서 -p옵션을 사용합니다.


git revert 커밋명

기존의 커밋에서 변경한 내용을 취소해서 새로운 커밋을 만듭니다. -n옵션을 사용하면 바로 커밋하지 않기 때문에 revert를 여러번한 다음에 커밋할 수 있습니다.(항상 최신의 커밋부터 revert해야 합니다.)


git reset 커밋명

이전 커밋을 수정하기 위해서 사용합니다. --soft 옵션을 사용하면 이전 커밋을 스테이징하고 커밋은 하지 않으며 --hard옵션은 저장소와 작업트리에서 커밋을 제거합니다. 

git reset HEAD^와 같이 입력하면 최근 1개의 커밋을 취소할 수 있습니다.

git reset HEAD 하면 staging된 파일을 unstage 상태로 되돌 릴 수 있다. HEAD로 하면 몽땅 돌아오고 git reset 파일명 하면 원하는 파일만 돌아온다.


git rebase -i 커밋범위

-i옵션으로 대화형모드로 커밋 순서를 변경하거나 합치는 등의 작업을 할 수 있습니다.


원격저장소

git clone 저장소주소 폴더명

원격저장소를 복제하여 저장소를 생성합니다. 폴더명을 생략가능합니다.


git fetch

원격저장소의 변경사항 가져와서 원격브랜치를 갱신합니다.

 

git pull

git fetch에서 하는 원격저장소의 변경사항을 가져와서 지역브랙치에 합치는 작업을 한꺼번에 합니다. 파라미터로 풀링할 원격저장소와 반영할 지역브랜치를 줄 수 있습니다.


git push

파라미터를 주지 않으면 origin 저장소에 푸싱하며 현재 지역브랜치와 같은 이름의 브랜치에 푸싱합니다. --dry-run 옵션을 사용하면 푸싱된 변경사항을 확인할 수 있습니다. 로컬에서 tag를 달았을 경우에 기본적으로 푸싱하지 않기 때문에 git push origin 태그명이나 모든 태그를 올리기 위해서 git push origin --tags를 사용해야 합니다.


git remote add 이름 저장소주소

새로운 원격 저장소를 추가합니다.


특정 저장소로 올리기

cd uluck_kernel

git remote add dgit git@dgit.co:messijeon/uluck_kernel.git

git push -u dgit master


git remote

추가한 원격저장소의 목록을 확인할 수 있습니다.


git remote show 이름

해당 원격저장소의 정보를 볼 수 있습니다.


git remote rm 이름

원격저장소를 제거합니다.


서브모듈

git submodule

연관된 하위모듈을 확인할 수 있습니다.


git submodule add 저장소주소 서브모듈경로

새로운 하위모듈을 해당경로에 추가합니다. 추가만하고 초기화 하지는 않으며 커밋해쉬앞에 마이나스(-) 표시가 나타납니다.


git submodule init 서브모듈경로

서브모듈을 초기화 합니다.


git submodule update 서브모듈경로

서브모듈의 변경사항을 적용합니다.(저장소의 최신커밋을 추적하지 않습니다.)


기타 명령어

git archive --format=tar --prefix=폴더명/ 브랜치혹은태그 | gzip > 파일명.tar.gz

git archive --format=zip --prefix=폴더명/ 브랜치혹은태그 > 파일명.zip

해당 브랜치나 태그를 압축파일로 만듭니다. --prefix를 주면 압축하일이 해당폴더 안에 생성되도록 할 수 있습니다.


git mergetool

설정에 merge.tool의 값에 있는 머지툴을 찾아서 실행합니다.


git gc

저장소의 로그를 최적화 합니다. 로그가 변경되지는 않고 저장하는 방식만 최적화 합니다. --aggressive 옵션을 주면 더 자세하게 최적화합니다.


git rev-parse --show-toplevel

git 저장소내에서 입력하면 루트디렉토리를 알려줍니다.


git filter-branch --tree-filter "find * -type f -name '*.order' -delete" -f

전체 커밋에 대해서 *.order 이라는 파일을 히스토리상에서 아예 삭제해준다. 

중앙서버에 올린 커밋에 대해서는 적용하면 절대 안됨.

이 명령은 모든 파일과 커밋을 정리하고 브랜치 포인터를 다시 복웒준다.

filter-branch 명령에 -- --alll을 추가하면 모든 브랜치에 적용된다.


git ls-tree -r master --name-only

현재 git에 등록되어 있는 파일들의 목록을 보고 싶을 때. list of all fils.


git stash

내가 가장 유용하다고 생각하는 명령어. 

작업중에 pull해야 된다던지 브랜치를 옮겨서 작업해야 할 때 완성되지도 않은 소스를 커밋하기는 찜찜한 경우 현재 수정중인 작업 들을 잠시 저장해두는 것.

워킹 디렉토리에서 수정한 파일만 저장한다.

modified 이면서 tracked상태인 파일과 staging area에 있는 파일들을 보관해 두는 장소다.

스택처럼 되어있다.


git stash list

stash 로 저장한 목록을 보여준다. 


git statsh apply  

stash 로 저장한 마지막 목록을 적용해줌. stack에 남아있다.


git stash apply stash@{2}

stash목록중에 원하는 것을 적용한다.


이것은 master 브랜치에서 stash했다고 해서 반드시 master에만  apply해야하는 것이 아니고 아무데나 적용 가능하다.


git stash apply --index

stash 할때 staged상태였던 파일들을 자동으로 staged상태로 적용해준다. --index옵션 안쓰면 다 modified상태가 됨.


git stash drop

적용하지 않고 스택에서 제거


git stash pop

적용하면서 스택에서 제거


git stash branch 브랜치명

마지막 stash가 이루어진 시점에서 checkout한후 새로운 브랜치를 만들고 여기에 적용함.


git stash show -p stash@{2}

특정 stash를 자세히 볼때.


문제발생

git 원격저장소에 잘못 올렸을때

git를 잘못 commit 한데다가 push 까지 한 경우 되돌리기

1. 일단 git reset 을 해줌 

git reset HEAD^

이렇게 하면 한단계 앞으로 리셋됨

2. 다시 재작업함

3. 다시 올리기. 이미 reset 전에 commit 이 올라가있어서 fast-forward 어쩌고 저쩌고가 나오면 그냥 무시하고 덮어쓰기

git push origin +master 

이렇게 + 표시를 해주면 그냥 다 지우고 덮어써버림



질문답변


1. HEAD는 remote 저장소의 기본 브랜치를 지정하는 역할을 합니다.

origin의 경우 HEAD가 master 브랜치를 가리키고 있으므로 origin/master를 그냥 origin으로만 적어도 됩니다.


2. 첫 질문에 이어 가는 질문입니다. 왜 remote/suapapa/HEAD -> suapapa/master 는 없을까요?

git remote add 시에 -m 옵션을 주거나 git remote set-head 명령을 실행하면 됩니다.


root@ip-172-31-25-206:~/flask_1# git branch -a

* master

  test

  remotes/origin/master

  remotes/origin/test

  remotes/origin/work


root@ip-172-31-25-206:~/flask_1# git remote set-head -a origin/master

fatal: 'origin/master' does not appear to be a git repository

fatal: The remote end hung up unexpectedly


root@ip-172-31-25-206:~/flask_1# git remote set-head -a origin

Enter passphrase for key '/root/.ssh/id_rsa': 

origin/HEAD set to master


root@ip-172-31-25-206:~/flask_1# git branch -a

* master

  test

  remotes/origin/HEAD -> origin/master

  remotes/origin/master

  remotes/origin/test

  remotes/origin/work


3. --track의 개념을 잘 모르겠습니다. suapapa 브랜치에서 push/pull 하면 remote/suapapa/master에서 push/pull 하게 하기 위함인가요? push/pull 시 remote 브랜치를 지정할 수도 있던 것 같은데 그러면 --track으로 지정한 remote 브랜치를 무시하게 되는 것인지?

이해하신 내용이 맞는 것 같습니다.


4. 정확한 방법은 모르겠지만 git config -l | grep branch 명령으로 대강 확인해 볼 수 있습니다.


$ git config -l | grep branch.*remote

branch.master.remote=origin

branch.suapapa.remote=suapapa

이 정보가 딱 제가 원하던 정보였습니다. 브랜치가 많아지면 어떤 리모트를 따르고 있는지 헷갈릴 것 같았는데, alias로 설정해 두고 유용하게 쓸 수 있겠네요. :)


관련 문서를 찾아 링크 추가합니다.

http://help.github.com/forking/

관례적으로 원본 원격 저장소는 upstream이라고 명명하네요. ^^



Fork로 만든 저장소와 원본 저장소 연결

이 과정이 꼭 필요한건 아니다. 하지만 단 한번만 이 프로젝트에 참여할 것이 아니라면 이 과정을 해두면 정말 쓸모있다. 아래 명령을 실행하여 원래 프로젝트 저장소를 'upstream'으로 등록해두면 원래 프로젝트의 변경사항을 계속 받아볼 수 있다. 'upstreamname'과 'projectname' 부분을 실제 프로젝트에 맞게 적당히 바꿔서 명령을 실행한다.

git remote add --track master upstream git://github.com/upstreamname/projectname.git

자 이렇게 하면 upstream 이라는 리모트로 등록이 된다.

git fetch upstream

이렇게 하면 원래 프로젝트의 최신 내용을 받아오고

git merge upstream/master

이렇게 하면 최신 내용을 현재 작업하고 있는 브랜치에 Merge하게 된다. 짜잔!

Posted by Real_G