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