Git basis - usage

Preview:

Citation preview

Git basis

~$ whoami

● Len

● Blog● len.hack-stuff.com

什麼是版本控制?

簡單來說 ...

沒有版本控制 (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 <a78965@gmail.com>

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 <a78965@gmail.com>

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 <a78965@gmail.com>

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 'a78965@gmail.com'

git log 查看 commit log

git log --stat

commit af84a6279fa2968f2ba2ca6cd2211302281f814d

Author: Len <a78965@gmail.com>

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 <a78965@gmail.com>

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 <a78965@gmail.com>

Date: Thu Aug 2 15:33:50 2012 +0800

add test function

commit af84a6279fa2968f2ba2ca6cd2211302281f814d

Author: Len <a78965@gmail.com>

Date: Thu Aug 2 14:44:53 2012 +0800

initial repo

別忘了我們在 dev branch 上

git checkout master

➢ git log

commit af84a6279fa2968f2ba2ca6cd2211302281f814d

Author: Len <a78965@gmail.com>

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 <a78965@gmail.com>

Date: Thu Aug 2 15:57:21 2012 +0800

Merge branch 'dev'

commit 5deb2bcd68f956ce1d58856f3d5af1c21682b20c

Author: Len <a78965@gmail.com>

Date: Thu Aug 2 15:50:12 2012 +0800

add b.c file

commit f777b13459e9459d8d990f50e3ca678cf4437308

Author: Len <a78965@gmail.com>

Date: Thu Aug 2 15:33:50 2012 +0800

add test function

merge 產生的 log

git logcommit b1acc389acfd6bbfaf4435cf59a5617b2b37fc8f

Merge: 5deb2bc f777b13

Author: Len <a78965@gmail.com>

Date: Thu Aug 2 15:57:21 2012 +0800

Merge branch 'dev'

commit 5deb2bcd68f956ce1d58856f3d5af1c21682b20c

Author: Len <a78965@gmail.com>

Date: Thu Aug 2 15:50:12 2012 +0800

add b.c file

commit f777b13459e9459d8d990f50e3ca678cf4437308

Author: Len <a78965@gmail.com>

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 <a78965@gmail.com>

Date: Thu Aug 2 15:57:21 2012 +0800

Merge branch 'dev'

commit 5deb2bcd68f956ce1d58856f3d5af1c21682b20c

Author: Len <a78965@gmail.com>

Date: Thu Aug 2 15:50:12 2012 +0800

add b.c file

commit f777b13459e9459d8d990f50e3ca678cf4437308

Author: Len <a78965@gmail.com>

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.support@github.com</div>

=======

<div id="footer">

please contact us at support@github.com

</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 0xlen@github.com

檢查遠端 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

Recommended