Repository 생성
cd ~/work/git_demo
git init
초기화의 결과로 .git/ 디렉토리가 생성된다.
기본 Workflow와 Git Status
git을 이해하기 위해서는 무엇보다도 상태(status)의 변화를 잘 인지하고 있어야 한다. 상태(status)에 따라 적용되는 git 명령어가 다를뿐 아니라, git 명령의 결과에 의해 상태도 변하게 된다. 파일의 생성, git index로의 편입, commit 저장 등이 상태가 변하는 예에 해당한다.
Untracked in working directory 1 Staged in index(=staging area) 2 Committed as commit object 3
파일 생성에서 Commit 까지 touch README 1
git add -A 1 to 2
git commit -m "Create a README" 2 to 3
파일 수정과 Commit 하기 vi README 1
git add -A 1 to 2
git commit -m "Modify the README" 2 to 3
Unstaging vi README 1
git add -A 1 to 2
git reset HEAD README 2 to 1
여기서 git reset은 index 영역의 README를 HEAD(=최신 commit)에 있는 README로 복구(reset)한다. 따라서 이전의 git add는 효력이 사라진다.
Discarding Change git checkout -- README
앞의 예에서 수정한 README 파일은 다시 Unstaged 상태로 되돌려졌다. 현재 상태에서 수정하던 내용을 아예 버리고 싶으면 어떻게 할까? 위 명령어는 현재 commit에 저장된 README 파일을 working directory로 expand하는 역할을 수행한다.
파일 삭제 rm README 1
git rm README 또는 git add -A 1 to 2
git commit -m "Delete the README" 2 to 3
rm README는 working directory에서 해당 파일만을 삭제한다. index 영역에는 (그 이전에) git add를 통해 옮겨놓은 README가 아직 존재하고 있기 때문에 이를 삭제하여야 한다. git index에 어떤 내용이 있는지는 git ls-files 명령으로 확인할 수 있다.
삭제된 파일을 이전 Commit으로 부터 복구 git reset --hard HEAD^
현재 마지막 commit에서는 README 파일이 삭제된 상태이므로 이 commit을 복구해도 README가 살아 나지는 않는다. 따라서 그 전 commit을 복구해야 한다. HEAD^에서 사용된 캐럿(Caret)은 Parent commit을 의미하는 기호로 현재 commit(=HEAD) 바로 이전의 commit을 지칭한다. 이 명령에 의해 HEAD가 가리키는 마지막 commit은 취소(undo) 되고 그 이전 commit의 내용으로 working directory와 index 영역이 바뀐다.
git reset --hard HEAD^^
이 명령어는 마지막 2번의 commit을 없애고(undo) 그 이전 commit의 내용으로 working directory와 index 영역을 교체한다.
git reset --soft HEAD^^
이 명령어에서는 soft 옵션이 사용되었다. hard 옵션과의 차이는 working directory의 내용을 바꾸지는 않는다는 것이다. 즉, index(=staging area)의 내용을 이전 commit으로 바꾸지만 작업 중이던 working 영역은 건드리지 않는 차이가 있다.
수정한 내용을 (새로운 commit에 저장하지 않고) 마지막 commit에 추가 vi README 1
git add README 1 to 2
git commit --amend -m 'Fix README' 2 to 3
Git Branch
전체 Branch 보기 git branch -a Branch 생성 git branch slave 특정 Commit으로 부터 Branch 생성 git branch experiment 8190528
여기서 8190528는 특정 commit의 SHA-1값
Branch 전환 git checkout slave Branch 생성과 전환을 한번에 git checkout -b slave Branch 삭제 git branch -d slave
이때 수정 중인 파일이 있으면 처리(=merge 또는 commit) 할 것을 요구한다. 만약 강제로 삭제하고 싶으면 -D 옵션을 사용하면 된다.
Git Diff
index(staging area) vs. working directory git diff 최신 commit vs. index(staging area) git diff --staged HEAD vs. 현재 state(both index and working directory) git diff HEAD
git diff HEAD^
git diff HEAD^^
git diff HEAD~5
Second most recent commit vs. Most recent git diff HEAD^..HEAD 비교 by SHA-1 git log 의 결과로 commit들의 SHA-1값을 얻은 후
git diff 41372e7b41df1ab33b47ea201fa14c753f9ab412..81905281ac0fe393331a548130b5359c8c8f0863
보통 SHA-1 값이 너무 길기 때문에(20 Hex) git log --oneline을 통해 단축된 SHA-1 값으로 비교
git diff 41372e7..8190528
두 branch간의 비교(master vs. slave) dit diff master slave 개발 파일에 대한 diff 이력 보기 git blame index.html --date short
Remote
(작성 중입니다...)
Merge
(작성 중입니다...)
Rebase
(작성 중입니다...)
Stashing
(작성 중입니다...)
오브젝트 탐색(Object Browsing)
Reference(branch, remote) 보기 git show-ref
d8f9c70ee33d84743541436ec22acc073dce47f3 refs/heads/master
d8f9c70ee33d84743541436ec22acc073dce47f3 refs/heads/slave
cat-file로 Commit, Tree, Blob 내용 보기 git log --oneline
3a62e38 Update the README
8190528 Modify the README
c1cbdca Create a README
git cat-file -p 3a62e38
tree 6769da7a1b23d49292a6abbd6590a99a340b1974
parent 81905281ac0fe393331a548130b5359c8c8f0863
author James Bond
committer James Bond
git cat-file -p 6769da7a1b23d49292a6abbd6590a99a340b1974
100644 blob 6b42d5b098e4c2239b845fa03cba56e0fb7844eb README
git cat-file -p 6b42d5b098e4c2239b845fa03cba56e0fb7844eb
== README
This README would normally document whatever steps are necessary to get the
application up and running.
ls-tree git ls-tree master
git ls-tree master^
git ls-tree master^^
git ls-tree master~5
.gitignore
사용 예
application.yml 단일 파일
*.tmp tmp 확장자를 가진 모든 파일
experiments/ 디렉토리 전체
logs/*.log 특정 디렉토리의 특정 확장자 파일
git에서 이미 관리되고 있는 단일 파일을 제외하는 방법 git rm --cached development.log
--cached 옵션에 의해서 index에서는 제외되지만 working directory에는 남아 있는다.
echo "*.log" > .gitignore
git add .gitignore
git commit -m "Ignore all log files."
git에서 이미 관리되고 있던 중 .gitignore에 새로 지정된 모든 파일을 제외하는 방법 git rm -r --cached .
git add .
git commit -m ".gitignore is now working"
Logging
git log
git log --oneline
git log --pretty=oneline
git log --pretty=format:"%h %ad- %s [%an]"
git log --oneline -p
git log --pretty=oneline -p -p 옵션은 diff 결과를 같이 보여줌
git log --oneline --graph
git log --since=1.month.ago --until=2.weeks.ago
git log --since=2000-01-01 --until=2012-12-21
Tagging
모든 Tag 보기 git tag Tagging 하기 git tag -a v0.0.3 -m "version 0.0.3" 특정 Tag checkout git checkout v0.0.3 Remote에 Tag를 push git push --tags
Git Config
git config --global user.name "James Bond"
git config --global user.email bond007@gmail.com
git config --global color.status auto
git config --global color.branch auto
git config --global color.ui true
git config --global push.default simple (Github에 push를 할 때 현재 branch만을 push) git config --global rerere.enabled true
git config --global core.autocrlf input
git config --globalcore.editor subl
git config --global apply.whitespace nowarn
git config --global merge.tool opendiff (os x 에서만 사용)
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.s "status -s"
git config --global alias.lg "log --oneline --decorate --all --graph"
git config --global alias.mylog "log --pretty=format:'%h %s [%an]' --graph"
git config --global alias.lol "log --graph --decorate --pretty=oneline --abbrev-commit --all"
git config --list
git config의 결과는 ~/.gitconfig에 저장된다.
Git Help
git help config
git help commit
git help log
용어 정리
저장소(Repository) git clone 또는 git init을 통해 생성되는 최상위 개념의 저장소를 지칭한다. 가령 ~/work/git_demo/에서 git init을 하게되면 이 디렉토리가 Repository가 된다. Git 디렉토리(Git directory) Repository를 만들면서 생기는 .git/ 디렉토리를 말한다. 모든 Repository 마다 반드시 필요하며 이곳에 Git 오브젝트들이 저장된다. 작업 디렉토리(Working directory) .git/에 저장된 오브젝트들이 expand하면서(=checkout) 생기는 임시 작업 디렉토리이다. 우리 예에서는 ~/work/git_demo/.git/ 디렉토리를 제외한 ~/work/git_demo/**/*이 Working directory에 해당한다. 필요 시 expand 하면 되므로 Repository는 Working directory를 반드시 가질 필요는 없다. Git 오브젝트(Git object) Git 오브젝트에는 blob, tree, commit, tag 4 종류가 있으며 ~/work/git_demo/objects에 저장되는데 zlib으로 압축해서 SHA-1 값으로 참조(referencing)하게 된다. Blob Blob은 파일의 컨텐츠에 해당하는 오브젝트이다. 파일을 zlib으로 압축하고 이 결과를 다시 SHA-1 연산을 통해 160 bit(=20 Hex)로 표현한 값으로 참조한다. 컨텐츠만이 관심 영역이므로 파일명, 모드 등의 정보는 이 오브젝트를 통해서는 알 수 없다. Tree Tree는 디렉토리 구성 정보를 보여주는 오브젝트로서 Tree와 Blob의 메타 정보 - 파일명, 모드, 타입 등 - 를 zlib 압축해서 저장하고 SHA-1 값으로 참조한다. 만약 어떤 파일이 내용은 변하지 않고 파일 이름만 바뀌었다면 Git 입장에서는 Blob은 그대로 유지하고 Tree만 다시 계산이 이루어진다. Commit Commit은 git commit 명령에 의해 생성하는 오브젝트로서 최상위 Tree 오브젝트, 이전 Commit 오브젝트, Commit 메세지, 저자(author), 커미터(committer)에 대한 정보를 zlib 압축해서 SHA-1로 참조할 수 있게 저장한다. Tag Tag는 특정 commit을 영구적으로 태깅(tagging)하기 위해 git tag -a 명령으로 생성되는 오브젝트로서 그 Commit 오브젝트에 정보를 기지고 있다. .git/HEAD 현재 사용 중인 브랜치(branch)를 가리킨다.
cat .git/HEAD => ref: refs/heads/master
.git/refs/heads/master 이 브랜치(master)의 가장 최근 Commit를 가리킨다.
cat .git/refs/heads/master => 10d4882bdaa20bc9728d62f1b63ce3e4dc92ca20
.git/refs/remotes/origin/master origin(이란 이름의) 리모트에서 master(란 이름의) 브랜치의 가장 최근 Commit를 가리킨다. 리모트(remote)는 원격에 있는 컴퓨터나 서버에 있는 동일 Repository를 말한다.
cat .git/refs/remotes/origin/master => 6b9835577197235b1dde2f6b67cc42214622992e