Git basis
什麼是版本控制?
簡單來說 ...
沒有版本控制 (SCM) 的時候 ...
A
沒有版本控制 (SCM) 的時候 ...
A → A
沒有版本控制 (SCM) 的時候 ...
A → A → A
沒有版本控制 (SCM) 的時候 ...
A → A → A → A
沒有版本控制 (SCM) 的時候 ...
A → A → A → A → A
沒有版本控制 (SCM) 的時候 ...
A → A → A → A → A
改爛了怎麼辦?
版本控制
版本控制
A
版本控制
A → A''
版本控制
A → A'' → A'''
版本控制
A → A'' → A''' → A''''
版本控制
A → A'' → A''' → A'''' → A'''''
Anyway
簡單來說
紀錄檔案變動
改爛可以再回去 方便進行團隊協同開發 拿來備份檔案(?)
本機 Local version control
完全在本機 該怎麼控制? 協同開發?
FTP ( ? )
怎麼區分檔案? 檔案鎖死怎麼辦?
中控 Central version control
Server 紀錄全部的變動 什麼都要網路 掛了怎麼辦?
SVN
Distributed version control
大家都有整份紀錄
Server 掛了 照樣工作 獨立開發
亂成一團
Linux kernel
為了解決 kernel hackers 超大的資訊量 使用 BitKeeper 做為 scm
BitKeeper f#ck you
快速 簡潔好上手 支援非線性開發
fork 來 fork 去 完全分散
為了解決 Linux kernel 肥死人的資料量
紀錄檔案快照而不是紀錄檔案差異– 容量小
什麼事幾乎都在本機進行– 紀錄拉下來 (pull) 不需要網路也可以寫 code !
– 看 log 、提交 commit 都在本機運作
– 大大解決 svn 的缺點 sha checksum 確保檔案完整性
使用 Git 的熱門 project
Linux kernel jQuery node.js django cakePHP Rails bootstrap
https://git.wiki.kernel.org/index.php/GitProjects
Git usage
放 code 的倉庫 Repository
簡稱 repo
本地 (Local) 都會放一個 repo
– 在本機紀錄變動
– 可以看成每個 local 就是一個獨立的 server
遠端伺服器 (Server) 也會有一個 repo
– 紀錄團隊開發進度
len@len-desktop:~$ mkdir repolen@len-desktop:~/gitdemo$ git init repo
Initialized empty Git repository in /home/len/gitdemo/repo/.git/
.git 即可當作是 local repo裡面紀錄著檔案變動等等資訊
拉別人的 repo 下來
git clone git://github.com/jquery/jquery.git
len@len-desktop:~/gitdemo/repo$ touch a.c
a.c
#include <stdio.h>
int main() {
printf("Hello git");
return 0;
}
git status len@len-desktop:~/gitdemo/repo$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# a.c
# a.out
nothing added to commit but untracked files present (use "git add" to track)
git add 加入追蹤 len@len-desktop:~/gitdemo/repo$ git add a.c
len@len-desktop:~/gitdemo/repo$ git status
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a.c
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# a.out
其他常用指令 取消追蹤
– git rm (git add 的相反 )
提交變動– git commit
查看檔案狀態– git status
回復檔案狀態– git checkout
– git reset
git commit 提交變動
git commit -m 'initial repo'
[master (root-commit) af84a62] initial repo
1 files changed, 6 insertions(+), 0 deletions(-)
create mode 100644 a.c
git log 查看 commit log
git log --stat
commit af84a6279fa2968f2ba2ca6cd2211302281f814d
Author: Len <[email protected]>
Date: Thu Aug 2 14:44:53 2012 +0800
initial repo
a.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
git log 查看 commit log
git log --stat
commit af84a6279fa2968f2ba2ca6cd2211302281f814d
Author: Len <[email protected]>
Date: Thu Aug 2 14:44:53 2012 +0800
initial repo
a.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
每次提交的 SHA
git log 查看 commit log
git log --stat
commit af84a6279fa2968f2ba2ca6cd2211302281f814d
Author: Len <[email protected]>
Date: Thu Aug 2 14:44:53 2012 +0800
initial repo
a.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
git config --global user.name 'Len'
git config --global user.email '[email protected]'
git log 查看 commit log
git log --stat
commit af84a6279fa2968f2ba2ca6cd2211302281f814d
Author: Len <[email protected]>
Date: Thu Aug 2 14:44:53 2012 +0800
initial repo
a.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
Commit 訊息
git log 查看 commit log
git log --stat
commit af84a6279fa2968f2ba2ca6cd2211302281f814d
Author: Len <[email protected]>
Date: Thu Aug 2 14:44:53 2012 +0800
initial repo
a.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
檔案變動
上次的 commit 紀錄叫 HEAD
– 上上次的 commit 紀錄就是 HEAD^
– 上上上次的 commit 紀錄就是 HEAD^^
以此類推
Branch
預設的 branch 叫 master
在還沒開 branch 前我們的開發是這樣A → A'' → A''' → A'''' → A'''''
想測試新功能 想另外寫功能
緊急修 bug 專案部份拆散開發
開一個叫 dev 的 branch 用來開發新功能➢ git branch dev
切到 dev branch➢ git checkout dev
檔案好像沒變 O___Oa ?
a.c#include <stdio.h>
int main() {
printf("%d\n" ,test(777,2) );
return 0;
}
int test(int x,int y) {
return x*y;
}
➢ git add a.c➢ git status
# On branch dev
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a.c
git commit -m 'add test function'
[dev f777b13] add test function 1 files changed, 5 insertions(+), 1 deletions(-)
➢ git logcommit f777b13459e9459d8d990f50e3ca678cf4437308
Author: Len <[email protected]>
Date: Thu Aug 2 15:33:50 2012 +0800
add test function
commit af84a6279fa2968f2ba2ca6cd2211302281f814d
Author: Len <[email protected]>
Date: Thu Aug 2 14:44:53 2012 +0800
initial repo
別忘了我們在 dev branch 上
git checkout master
➢ git log
commit af84a6279fa2968f2ba2ca6cd2211302281f814d
Author: Len <[email protected]>
Date: Thu Aug 2 14:44:53 2012 +0800
initial repo
master 跟 dev 的進度是分開的
來看看線圖吧!
其實他已經岔開來了 ...
在 master 上面提交新的 commit
➢ git checkout master➢ touch b.c➢ git add b.c➢ git commit -m 'add b.c file'
很明顯的岔開來了!!!
我想要 master 跟 dev 合併
➢ git merge devMerge made by recursive.
a.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
發生了什麼事?
git logcommit b1acc389acfd6bbfaf4435cf59a5617b2b37fc8f
Merge: 5deb2bc f777b13
Author: Len <[email protected]>
Date: Thu Aug 2 15:57:21 2012 +0800
Merge branch 'dev'
commit 5deb2bcd68f956ce1d58856f3d5af1c21682b20c
Author: Len <[email protected]>
Date: Thu Aug 2 15:50:12 2012 +0800
add b.c file
commit f777b13459e9459d8d990f50e3ca678cf4437308
Author: Len <[email protected]>
Date: Thu Aug 2 15:33:50 2012 +0800
add test function
merge 產生的 log
git logcommit b1acc389acfd6bbfaf4435cf59a5617b2b37fc8f
Merge: 5deb2bc f777b13
Author: Len <[email protected]>
Date: Thu Aug 2 15:57:21 2012 +0800
Merge branch 'dev'
commit 5deb2bcd68f956ce1d58856f3d5af1c21682b20c
Author: Len <[email protected]>
Date: Thu Aug 2 15:50:12 2012 +0800
add b.c file
commit f777b13459e9459d8d990f50e3ca678cf4437308
Author: Len <[email protected]>
Date: Thu Aug 2 15:33:50 2012 +0800
add test function
master 的 commit log新增 b.c
git logcommit b1acc389acfd6bbfaf4435cf59a5617b2b37fc8f
Merge: 5deb2bc f777b13
Author: Len <[email protected]>
Date: Thu Aug 2 15:57:21 2012 +0800
Merge branch 'dev'
commit 5deb2bcd68f956ce1d58856f3d5af1c21682b20c
Author: Len <[email protected]>
Date: Thu Aug 2 15:50:12 2012 +0800
add b.c file
commit f777b13459e9459d8d990f50e3ca678cf4437308
Author: Len <[email protected]>
Date: Thu Aug 2 15:33:50 2012 +0800
add test function
dev 的 commit log放了 test function
檔案呢?– a.c
– b.c
a.c#include <stdio.h>
int main() {
printf("%d\n" ,test(777,2) );
return 0;
}
int test(int x,int y) {
return x*y;
}
a.c#include <stdio.h>
int main() {
- printf(“Hello git”);
+ printf("%d\n" ,test(777,2) );
return 0;
}
+ int test(int x,int y) {
+ return x*y;
+ }
沒錯! 線圖就長這樣
你一定會想
merge 超好用對吧!!!
BUT !!!
(人生中就是有很多 BUT )
Conflect
– 衝突到了
git 不知道該怎麼合併的時候 ...
衝突的檔案就會長這樣
<<<<<<< HEAD:index.html
<div id="footer">contact : [email protected]</div>
=======
<div id="footer">
please contact us at [email protected]
</div>
>>>>>>> iss53:index.html
這時候就得手動處理衝突
然後 commit
改爛了?
我想回到最後一次 commit 的狀態➢ git reset --hard HEAD
我想撈 a.c 最後一次 commit 的狀態➢ git checkout a.c
我想撈 commit log 的 sha 是 af84a
– 那時的 a.c 檔案狀態➢ git checkout af84a a.c
我只想改最後一次的 commit log➢ git commit --amend
我想回到 af84a➢ git reset --hard af84a
– (回不去 , 請愛用 branch 動作)
我想回到 af84a 但不想連同檔案狀態改變➢ git reset --soft af84a
Remote
預設的 remote branch 叫 origin
git remote add origin2 [email protected]
檢查遠端 server 的紀錄是否一致– 並且自動合併
➢ git pull➢ = git fetch + git merge
將本機的版本 push 到遠端更新➢ git push
– 在遠端新增 branch
➢ git push➢ git push origin➢ git push origin:
– 自動推到同名稱的 branch
➢ git push origin test:test
– 把 local 的 test branch 推到遠端的 test branch
– 若遠端不存在將自動建立➢ git push origin :test
– 刪除遠端的 test branch
協同開發
Demo
Q&A
Thanks !
Reference
http://git-scm.com/book
http://www.slideshare.net/littlebtc/git-5528339 http://blog.wu-boy.com/2012/02/how-to-use-git-version-control-for-new-beginner/ http://www.slideshare.net/tim518/loving-git2