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 repo len@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 SHA 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 git config --global user.name 'Len' initial repo a.c git 6 ++++++ | config --global user.email 'a78965@gmail.com' 1 files changed, 6 insertions(+), 0 deletions(-)
git log 查看 commit log  git log --stat commit af84a6279fa2968f2ba2ca6cd2211302281f814d Author:Commit 訊息 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(-)
 上次的 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("%dn" ,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 log commit 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 dev Merge made by recursive. a.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)  發生了什麼事?
git log commit b1acc389acfd6bbfaf4435cf59a5617b2b37fc8f Merge: 5deb2bc f777b13 Author: Len <a78965@gmail.com> merge 產生的 log 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
git log commit 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 master 的 commit log add b.c file 新增 b.c commit f777b13459e9459d8d990f50e3ca678cf4437308 Author: Len <a78965@gmail.com> Date: Thu Aug 2 15:33:50 2012 +0800 add test function
git log commit 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 dev 的 commit log add test function 放了 test function
 檔案呢? – a.c – b.c
 a.c #include <stdio.h> int main() { printf("%dn" ,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("%dn" ,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  http://www.slideshare.net/tim518/loving-git2

Git basis - usage

  • 1.
  • 2.
    ~$ whoami ● Len ● Blog ● len.hack-stuff.com
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
    沒有版本控制 (SCM) 的時候...  A → A → A → A
  • 9.
    沒有版本控制 (SCM) 的時候...  A → A → A → A → A
  • 10.
    沒有版本控制 (SCM) 的時候...  A → A → A → A → A  改爛了怎麼辦?
  • 11.
  • 12.
  • 13.
    版本控制 A → A''
  • 14.
    版本控制 A → A'' → A'''
  • 15.
    版本控制 A→ A'' → A''' → A''''
  • 16.
    版本控制 A → A''→ A''' → A'''' → A'''''
  • 17.
  • 18.
    簡單來說 紀錄檔案變動  改爛可以再回去  方便進行團隊協同開發  拿來備份檔案(?)
  • 19.
    本機 Local versioncontrol  完全在本機  該怎麼控制?  協同開發? FTP ( ? )  怎麼區分檔案?  檔案鎖死怎麼辦?
  • 20.
    中控 Central versioncontrol Server  紀錄全部的變動  什麼都要網路  掛了怎麼辦?  SVN
  • 21.
    Distributed version control  大家都有整份紀錄 Server 掛了  照樣工作  獨立開發  亂成一團
  • 23.
    Linux kernel  為了解決 kernel hackers 超大的資訊量  使用 BitKeeper 做為 scm
  • 24.
  • 25.
    快速  簡潔好上手  支援非線性開發 fork 來 fork 去  完全分散  為了解決 Linux kernel 肥死人的資料量
  • 26.
    紀錄檔案快照而不是紀錄檔案差異 – 容量小  什麼事幾乎都在本機進行 – 紀錄拉下來 (pull) 不需要網路也可以寫 code ! – 看 log 、提交 commit 都在本機運作 – 大大解決 svn 的缺點  sha checksum 確保檔案完整性
  • 27.
    使用 Git 的熱門project  Linux kernel  jQuery  node.js  django  cakePHP  Rails  bootstrap https://git.wiki.kernel.org/index.php/GitProjects
  • 28.
  • 29.
    放 code 的倉庫Repository  簡稱 repo  本地 (Local) 都會放一個 repo – 在本機紀錄變動 – 可以看成每個 local 就是一個獨立的 server  遠端伺服器 (Server) 也會有一個 repo – 紀錄團隊開發進度
  • 30.
    len@len-desktop:~$ mkdir repo len@len-desktop:~/gitdemo$git init repo Initialized empty Git repository in /home/len/gitdemo/repo/.git/ .git 即可當作是 local repo 裡面紀錄著檔案變動等等資訊
  • 31.
    拉別人的 repo 下來  git clone git://github.com/jquery/jquery.git
  • 32.
    len@len-desktop:~/gitdemo/repo$ touch a.c  a.c #include <stdio.h> int main() { printf("Hello git"); return 0; }
  • 33.
    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)
  • 34.
    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
  • 35.
    其他常用指令  取消追蹤 – git rm (git add 的相反 )  提交變動 – git commit  查看檔案狀態 – git status  回復檔案狀態 – git checkout – git reset
  • 36.
    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
  • 37.
    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(-)
  • 38.
    git log 查看commit log  git log --stat commit af84a6279fa2968f2ba2ca6cd2211302281f814d Author: Len <a78965@gmail.com> 每次提交的 Date: Thu Aug 2 14:44:53 2012 +0800 SHA initial repo a.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
  • 39.
    git log 查看commit log  git log --stat commit af84a6279fa2968f2ba2ca6cd2211302281f814d Author: Len <a78965@gmail.com> Date: Thu Aug 2 14:44:53 2012 +0800 git config --global user.name 'Len' initial repo a.c git 6 ++++++ | config --global user.email 'a78965@gmail.com' 1 files changed, 6 insertions(+), 0 deletions(-)
  • 40.
    git log 查看commit log  git log --stat commit af84a6279fa2968f2ba2ca6cd2211302281f814d Author:Commit 訊息 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(-)
  • 41.
    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(-)
  • 42.
    上次的 commit 紀錄叫 HEAD – 上上次的 commit 紀錄就是 HEAD^ – 上上上次的 commit 紀錄就是 HEAD^^  以此類推
  • 43.
  • 44.
    預設的 branch 叫 master  在還沒開 branch 前我們的開發是這樣 A → A'' → A''' → A'''' → A'''''
  • 45.
    想測試新功能  想另外寫功能  緊急修 bug  專案部份拆散開發
  • 46.
    開一個叫 dev 的 branch 用來開發新功能 ➢ git branch dev  切到 dev branch ➢ git checkout dev  檔案好像沒變 O___Oa ?
  • 47.
    a.c #include <stdio.h> int main() { printf("%dn" ,test(777,2) ); return 0; } int test(int x,int y) { return x*y; }
  • 48.
    git add a.c ➢ git status # On branch dev # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: a.c
  • 49.
    git commit -m'add test function' [dev f777b13] add test function 1 files changed, 5 insertions(+), 1 deletions(-)
  • 50.
    git log commit 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
  • 51.
    別忘了我們在 dev branch上 git checkout master
  • 52.
    git log commit af84a6279fa2968f2ba2ca6cd2211302281f814d Author: Len <a78965@gmail.com> Date: Thu Aug 2 14:44:53 2012 +0800 initial repo  master 跟 dev 的進度是分開的
  • 53.
  • 54.
    在 master 上面提交新的commit ➢ git checkout master ➢ touch b.c ➢ git add b.c ➢ git commit -m 'add b.c file'
  • 55.
  • 56.
    我想要 master 跟 dev 合併 ➢ git merge dev Merge made by recursive. a.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)  發生了什麼事?
  • 57.
    git log commitb1acc389acfd6bbfaf4435cf59a5617b2b37fc8f Merge: 5deb2bc f777b13 Author: Len <a78965@gmail.com> merge 產生的 log 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
  • 58.
    git log commitb1acc389acfd6bbfaf4435cf59a5617b2b37fc8f 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 master 的 commit log add b.c file 新增 b.c commit f777b13459e9459d8d990f50e3ca678cf4437308 Author: Len <a78965@gmail.com> Date: Thu Aug 2 15:33:50 2012 +0800 add test function
  • 59.
    git log commitb1acc389acfd6bbfaf4435cf59a5617b2b37fc8f 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 dev 的 commit log add test function 放了 test function
  • 60.
    檔案呢? – a.c – b.c
  • 61.
    a.c #include <stdio.h> int main() { printf("%dn" ,test(777,2) ); return 0; } int test(int x,int y) { return x*y; }
  • 62.
    a.c #include <stdio.h> int main() { - printf(“Hello git”); + printf("%dn" ,test(777,2) ); return 0; } + int test(int x,int y) { + return x*y; +}
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
    Conflect – 衝突到了  git 不知道該怎麼合併的時候 ...
  • 68.
    衝突的檔案就會長這樣 <<<<<<< 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
  • 69.
  • 70.
    改爛了?  我想回到最後一次 commit 的狀態 ➢ git reset --hard HEAD  我想撈 a.c 最後一次 commit 的狀態 ➢ git checkout a.c  我想撈 commit log 的 sha 是 af84a – 那時的 a.c 檔案狀態 ➢ git checkout af84a a.c
  • 71.
    我只想改最後一次的 commit log ➢ git commit --amend  我想回到 af84a ➢ git reset --hard af84a – (回不去 , 請愛用 branch 動作)  我想回到 af84a 但不想連同檔案狀態改變 ➢ git reset --soft af84a
  • 72.
  • 73.
  • 74.
    git remote addorigin2 0xlen@github.com
  • 75.
    檢查遠端 server 的紀錄是否一致 – 並且自動合併 ➢ git pull ➢ = git fetch + git merge
  • 76.
    將本機的版本 push 到遠端更新 ➢ git push – 在遠端新增 branch
  • 77.
    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
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
    Reference  http://git-scm.com/book  http://www.slideshare.net/littlebtc/git-5528339  http://blog.wu-boy.com/2012/02/how-to-use-git  http://www.slideshare.net/tim518/loving-git2