Let's       Git !

陸勇盛 (David Lu)

yungshenglu1994@gmail.com

@CS.NCTU

AUG 14, 2018

  • Graduated student @CS.NCTU

    • SDN/NFV, Wireless Sensing.

    • Speaker, ModernWeb'18 & DigitalOcean Hsinchu

  • 以嘗試 結合不同的工具 為樂

  • 土砲 很有興趣!

    • ​e.g., TaiwanEX, docoGen, papoGen, CrossyRoad EX etc.

  • Recent in P4 and Neural Network
    “趕快想辦法畢業!”

About

David Lu

Slides Link

Let's       Git !

陸勇盛 (David Lu)

yungshenglu1994@gmail.com

Outline

  • 關於 Git 一定要知道的事

  • 寫給新手的 Git

  • 新手練習

  • Git 進階篇

  • 好用的資源

關於

一定要知道的事

過去的悲劇

  • 問題來了!

    • 最新版哪一個?

    • ​除了自己,還有誰知道這些檔案的差別?

    • 分組共作怎麼辦?

以前,你是區分不同版本的檔案呢?

檔名? e.g., Report_latest.txt, Report_new.txt, Report_new1.txt, Report_final.txt, etc.

日期? e.g., Report_0820.txt, Report_08201.txt, Report_082001.txt, etc.

             為此而生!

What is            ?

  • 分散式版本控制系統

    • 為了方便管理 Linux kernel 而開發的
       

  • 樹狀概念,保存所有修改紀錄

    • 回覆過去的狀態

    • 版本之間的差異比較
       

  • 友善的共作環境

    • ​i.e., 避免覆蓋別人修改的悲劇

Why using            ?

  • 團隊合作不衝突!

    • 「貢獻度」
       

  • 備份與追蹤

    • 不要在                             式的命名
       

  • 開源世代

    • 分享與改進才能不段進步!

Report_new1.txt

你可能聽過的名詞

GitLab

Bitbucket

GitBook

Lots of tool support

And so on...

寫給新手的

Repository

Repository 字典解釋:倉庫;知識庫。

  • 記錄檔案或目錄狀態的地方!

    • 儲存修改的歷史記錄
       

  • Git 上的基本單位
     

  • Local v.s. Remote

    • Local - 個人使用,存在於個人機器上

    • Remote - 多人共享,存在於專用的伺服器上

      • e.g., GitHub, GitLab, Bitbucket, etc.

Keyword 1.

Commit

Commit 字典解釋:做 (違法或錯誤的事);犯 (罪、錯);提交

  • 記錄修正處 以示負責

    • 文字說明 (i.e., commit message) 修改的地方

    • 養成寫好 commit message 的習慣!
       

  • 時間序排列儲存到 repository 中

    • ​產生一組識別碼 (i.e., commit ID) 作為 commit 的命名

    • e.g., 14123c8877e6ebdc220e205d92fc70feaf06dab1

Keyword 2.

安裝

詳細請參考:Git官方文件
  • Windows / MacOS

    • 下載 Git:連結在此

    • 安裝過程「全部選取預設」即可
       

  • Linux



     

  • Git 版本

# For Debian / Ubuntu install command
$ sudo apt-get install git-all
# For Fedora / CentOS install command
$ sudo yum install git-all

Step 0.

$ git --version
git version 2.7.1

初始設定

  • 開啟終端機 (terminal)

    • Windows - 開啟        Git Bash

    • Mac / Linux - 開啟終端機
       

  • Git config

    • 記錄在用戶的目錄下的                      檔案

    • 設定使用者名字電子信箱

$ git config --global user.name "<NAME>"
$ git config --global user.email "<EMAIL>"
# List your Git config
$ git config -l
user.name=<NAME>
user.email=<EMAIL>

Step 1.

Tips - control + T / ctrl + T

.gitconfig

Tips - 查看 Git config 使用                               

$ git config -l
以終端機操作為例!

初始設定 (cont.)

  • 更多 Git config 設定 (optional)

    • 設定 Git 輸出顏色

       

    • 設定 Git 指令別名 (e.g, "checkout" 省略為 "co")

       

    • 中文檔名顯示修正 (For Git Bash on Windows)

# Set output color on Git
$ git config --global color.ui auto

Step 1.

# Set the alias of command "checkout" as "co"
$ git config --global alias.co checkout
# Fix the display of filename in Chinese on Git
$ git config --global core.quotepath off
以終端機操作為例!

建立 Repository

  • 初始化專案

    • 新建一個資料夾作為專案資料夾,並切換至該資料夾下

       

    • 建立 Git repository

Step 2.

# Create a folder for demo and change directory
$ mkdir Git_demo && cd Git_demo
# Initialize git repository
$ git init
Initialized empty Git repository in .../Git_demo/.git/
以終端機操作為例!

           狀態

  • Local Git status

Step 3.

目前的 workspace

​i.e., 還沒存檔

準備進入 repository
i.e., 暫存區

進入 repository
i.e., 存檔

           狀態 (cont.)

Step 3.

  • 新增一個檔案                   ,寫入以下內容:


     
  • 查看目前 Git repository 的狀態
README.md
# Git DEMO
This is my first repository using Git.
$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	README.md

nothing added to commit but untracked files present (use "git add" to track)

Tips - Untracked files 是未被 Git 追蹤的檔案

以終端機操作為例!

加入檔案至

  • Git add

    • 加入                   至 Git repository

       

    • 查看目前 Git repository 狀態

Step 4.

# git add <FILENAME>
$ git add README.md
README.md
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   README.md

Tips - 已加至 Git repository 的檔案

Tips - 加入所有檔案                            

$ git add .
以終端機操作為例!

提交檔案至

  • Git commit

    • 撰寫提交訊息 (commit message)



       

    • 查看目前 Git repository 狀態

       

Step 5.

# git commit -m "<COMMIT_MESSAGE>"
$ git commit -m "Initial commit"
[master (root-commit) e83c8d6] Initial commit
 1 file changed, 2 insertions(+)
 create mode 100644 README.md
$ git status
On branch master
nothing to commit, working directory clean

Tips - 目前無其他更新需要提交

Tips - 目前在 master branch 上

以終端機操作為例!

提交檔案至           (cont.)

  • Git log

    • 查看提交紀錄

Step 5.

$ git log
commit e83c8d6eed726b1bb8e83e58a53934c035759482
Author: <NAME> <<EMAIL>>
Date:   Tue Aug 16 09:57:47 2018 +0800

    Initial commit

Tips - 提交時間與訊息

Tips - 識別碼 (Commit ID)

以終端機操作為例!

Finish            on local!

接下來,如何上傳到遠端?

Remote Repository

  • 同步 本地端 與 遠端 的修改紀錄

    • 上傳 本地端 的 repository 所存的修改歷史
       

  • 多人共作,遠端作業
     

  • 程式碼代管平台

以 GitHub 為例!

建立遠端 Repository

Step 6.

以 GitHub 為例!

Tips - 使用學校信箱申請

Tips - 示範用公開或私密都可以

Tips - 一般為專案名稱

Git_demo

Tips - 描述專案的主旨

Tips - 示範用不要勾選

Tips - 示範用都設為 "None"

1

2

3

4

5

Tips - 按下即可複製

Tips - 尚未建立 local repository 用

Tips - 已存在 local repository

Tips - 從其他平台匯入程式碼

註冊遠端 Repository

Step 7.

  • Git remote

    • 在本地端註冊遠端的 repository



       

    • 註冊多個遠端的 repository

      • 可將程式碼放不同平台 (e.g., GitLab, Bitbucket, etc.)

      • 同一平台的不同遠端 repository

# git remote add origin <REPO_URL>
$ git remote add origin https://github.com/yungshenglu/Git_demo.git
以終端機操作為例!

Tips - 貼上從 GitHub 複製的位址

Tips - 通常第一個上傳的遠端 repository 會命名為 origin

註冊遠端 Repository (cont.)

Step 7.

以終端機操作為例!
  • 其他 Git remote 指令 (optional)

    • 顯示已註冊的遠端 repository
       

    • 顯示已註冊的遠端 repository 位址

       

    • 重新命名已註冊的遠端 repository 名稱

       

    • 修改已註冊的遠端 repository 位址

# git remote rename <OLD_NAME> <NEW_NAME>
$ git remote rename origin develop
# git remote set-url <REPO_NAME> <REPO_URL>
$ git remote set-url origin https://github.com/yungshenglu/git-demo-dev.git
$ git remote
# git remote get-url <REPO_NAME>
$ git remote get-url origin

推送提交

  • Git push

    • 同步 本地端 與 遠端 的修改歷史紀錄

以下操作以終端機為主!

Step 8.

# git push <REMOTE_REPO> <LOCAL_BRANCH>
$ git push origin master
Username: <USERNAME>
Password: <PASSWORD>
Counting objects: 3, done.
Writing objects: 100% (3/3), 270 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/yungshenglu/Git_demo.git
 * [new branch]      master -> master

Tips - 在 remote repository 建立 master branch 同步 local 與 remote

Tips - 輸入 GitHub 帳號與密碼

Tips - Push 其實就是上傳

Tips - 成功推送後,可到 GitHub 查看結果。

複製遠端 Repository

  • Git clone

    • 切換路徑至與                 同層

       

    • 複製​遠端的 repository 至本地端

Step 9.

以 GitHub 為範例!
# git clone <REPO_URL>
$ git clone https://github.com/yungshenglu/Git_practice.git
# Clone others repository may be asked to enter username and password
Username: <USERNAME>
Password: <PASSWORD>
...
Git_demo
$ cd ../ && ls
Git_demo

Finish            on remote!

如果發生衝突怎麼辦?

合併修改記錄

  • 不同步問題

Remote repository

Local repository

A

B

C

D

A

B

C

08/10

08/10

08/11

08/11

08/12

08/12

08/13

08/14

檔案已被修改過!

合併修改記錄 (cont.)

  • 解法:Git pull

Remote repository

Local repository

A

B

C

D

A

B

C

08/10

08/10

08/11

08/11

08/12

08/12

08/13

08/13

08/14

D

08/14

衝突發生?

自動合併

合併修改記錄 (cont.)

  • 解決衝突

    • 不是每次都可以合併

    • 本地端與遠端在相同地方發生修改記錄

      • ​Git 無法自動合併

<<<<<<< HEAD
# Git DEMO
=======
# Git DEMO 中文說明
>>>>>>>
This is my first repository using Git.

Tips - 在 == 上方的是本地端的修改內容

Tips - 在 == 下方的是遠端的修改內容

新手練習

複製遠端 Repository
再推送到自己的 GitHub

Lab 1

複製遠端 Repository

Step 1.

  • 開啟終端機 (terminal)

    • Windows - 開啟        Git Bash

    • Mac / Linux - 開啟終端機
       

  • Git clone

    • 複製​以下遠端的 repository 至本地端
       

    • 提示:複製遠端 repository

Tips - control + T / ctrl + T

https://github.com/yungshenglu/Git_intro
以下操作以終端機為主!
$ git clone <REPO_URL>

新增檔案

Step 2.

  • 在                     下新增一個檔案                        ,寫入以下內容:

     

    • 提示:查看目前 Git repository 的狀態

  • Git add

    • 加入                         至 Git repository

    • 提示:查看目前 Git repository 的狀態

  • Git commit

    • 撰寫提交訊息 (commit message)

    • 提示:查看目前 Git repository 的狀態

README-CN.md
# Git DEMO 中文說明
* [YOUR_NAME](YOUR_GITHUB)
Git_intro
README-CN.md
以下操作以終端機為主!

建立遠端 Repository

  • 登入 GitHub 帳號,並新增 repository -

    • ​新增 repository 中的其他選項都使用預設即可。

  • Git remote

    • 修改本地端註冊遠端的 repository - 

    • 提示 1:顯示已註冊的遠端 repository

    • 提示 2遠端 repository 至本地端

Step 3.

以 GitHub 為例!
Git_intro
$ git remote add <REMOTE_REPO> <REMOTE_REPO>
Git_intro
$ git remote

推送提交

  • Git push

    • 同步本地端與遠端的修改歷史紀錄

    • 提示:推送本地端至遠端

       

  • GitHub 查看結果

以下操作以終端機為主!

Step 4.

$ git push <REMOTE_REPO> <BRANSH_NAME>

如何解決不同步問題?

Lab 2

線上修改與提交

以 GitHub 為例!

Step 1.

  • 開啟個人的 GitHub 並點開個人的 repository -

Git_intro

修改第 6 行為:

cout << "Hello NSS!" << endl;

將頁面滑至最下方:線上提交

Tips - 提交訊息 (commit message)

1

2

Tips - 撰寫較詳細的描述

Update main.cpp

3

Tips - 示範用使用預設

本地修改與提交

Step 2.

  • 開啟 repository                     中的

  • 編輯成以下內容






     

  • 本地端提交流程

    • 提示:Git add / Git commit / Git push

Git_intro
以下操作以終端機為主!
main.cpp
#include <iostream>

using namespace std;

int main(void) {
    cout << "Hello" << endl;
    return 0;
}

Tips - 將 "Hello World!" 改為 "Hello"

解決衝突

Step 3.

  • 衝突發生!

以下操作以終端機為主!
To https://github.com/<USERNAME>/Git_intro.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://github.com/<USERNAME>/Git_intro.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Tips - 不同步,拒絕推送遠端

Tips - 使用 Git pull

解決衝突 (cont.)

Step 3.

  • 衝突發生點

以下操作以終端機為主!

Tips - 衝突檔案是                 

remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/yungshenglu/Git_intro
 * branch            master     -> FETCH_HEAD
   d197eb9..e969789  master     -> origin/master
Auto-merging main.cpp
CONFLICT (content): Merge conflict in main.cpp
Automatic merge failed; fix conflicts and then commit the result.
main.cpp

解決衝突 (cont.)

Step 3.

  • 開啟檔案                  並修正衝突

    • 提示:在 === 上方是本地端的修改內容,在 === 下方是遠端修改內容








  • 本地端提交流程

以下操作以終端機為主!
main.cpp
#include <iostream>

using namespace std;

int main(void) {
<<<<<<< HEAD
    cout << "Hello" << endl;
=======
    cout << "Hello NSS!" << endl;
>>>>>>> e9697890f37e175c55ebca2447314a79e5b0c390
    return 0;
}

          進階篇

Branch

Branch 字典解釋:分支;支流;岔路

  • 分開儲存修改記錄,彼此不影響

    • 同一 repository 能同時進行多個修改
       

  • 第一次 commit 預設為 master branch
     

  • Branch 能再分開,也能合併

    • 當發生問題時,更容易找到問題的源頭

Keyword 3.

  Source: http://diagram.premamaz.com/github-workflow-diagram/

分支的運用

  • Integration branch

    • 主要的分支,即為「樹幹」

  • Topic branch

    • 其他的分支,即為「樹枝」

  Source: http://diagram.premamaz.com/github-workflow-diagram/

Tips - master 為 integration

建立分支

Step 1.

  • Git branch

    • 開啟終端機並切換路徑至                    下

    • 建立 issue 分支
       


    • 查看目前所有的分支
# git branch <BRANCH_NAME>
$ git branch issue
以終端機操作為例!
git-demo/
$ git branch
  issue
* master

master

issue

HEAD

切換分支

Step 2.

  • Git checkout

    • 切換到 issue 分支


       

    • 如何建立新分支後並切換過去?

# git checkout <BRANCH_NAME>
$ git checkout issue
Switched to branch 'issue'
以終端機操作為例!

master

issue

HEAD

HEAD

# git checkout -b <BRANCH_NAME>
$ git checkout -b issue
issue
Switched to branch 'issue'

加入與提交至

  • Git add

    • 新增                   並加入至 Git repository


       

  • Git commit

    • 撰寫提交訊息 (commit message)

       

Step 3.

# git add <FILENAME>
$ git add test.cpp
test.cpp
以終端機操作為例!
# git commit -m "<COMMIT_MESSAGE>"
$ git commit -m "Add test.cpp"

master

issue

HEAD

issue

HEAD

合併分支

  • Git merge

    • 切換至 master 分支

       

    • 合併其他分支至當前所在的分支

Step 4.

# git merge <BRANCH_NAME>
$ git merge issue
Updating a08f752..9922f03
Fast-forward
 test.cpp | 0
 1 file changed, 0 insertions(+), 0 
deletions(-)
 create mode 100644 test.cpp
以終端機操作為例!

master

HEAD

issue

HEAD

# git checkout <BRANCH_NAME>
$ git checkout master

master

HEAD

Tips - Fast-forward 快轉合併

平行作業

Step 6.

以終端機操作為例!

issue1

master

HEAD

  • 建立兩個新的分支為 issue1 和 issue2

     

  • 切換至 issue1 分支

     

  • 查看目前所有的分支

$ git branch -d issue1
$ git branch -d issue2
$ git checkout issue1
Switched to branch 'issue1'
$ git branch
* issue1
  issue2
  master

issue2

HEAD

平行作業 (cont.)

Step 6.

以終端機操作為例!

issue1

master

  • 修改                   為以下內容





     

  • 將                   的修改加至 repository 並提交

#include <iostream>
using namespace std;

int main(void) {
    cout << "Hello world!" << endl;
    return 0;
}

issue2

HEAD

test.cpp
test.cpp
$ git add test.cpp
$ git commit -m "Hello world"

issue1

平行作業 (cont.)

Step 6.

以終端機操作為例!

master

  • 切換至 issue2 分支
     

  • 修改                   為以下內容





     

  • 將                   的修改加至 repository 並提交

#include <iostream>
using namespace std;

int main(void) {
    cout << "Hello NSS!" << endl;
    return 0;
}

issue2

HEAD

test.cpp
test.cpp
$ git add test.cpp
$ git commit -m "Hello NSS"

issue1

$ git checkout issue2

issue2

解決合併衝突

Step 7.

以終端機操作為例!

master

  • 切換至 master 分支

     

  • 合併 issue1 分支master 分支

     

  • 合併 issue2 分支master 分支

$ git merge issue1

HEAD

$ git merge issue2
Auto-merging test.cpp
CONFLICT (content): Merge conflict in test.cpp
Automatic merge failed; fix conflicts and then
 commit the result.

issue1

$ git checkout master

issue2

HEAD

master

HEAD

Tips - 合併衝突訊息 (conflict message)

解決合併衝突 (cont.)

Step 7.

以終端機操作為例!
  • 開啟                   會看到以下內容







     

  • 刪除                   中的以下內容

#include <iostream>
using namespace std;

int main(void) {
<<<<<<< HEAD
    cout << "Hello world!" << endl;
=======
    cout << "Hello NSS!" << endl;
>>>>>>> issue2
    return 0;
}
test.cpp

Tips - 在 == 上方master修改內容

Tips - 在 == 下方issue2修改內容

test.cpp
<<<<<<< HEAD
=======
>>>>>>> issue2

Step 7.

以終端機操作為例!
  • 加入並再次提交

     

issue1

$ git add .
$ git commit -m "Merge issue2"
# On branch master
nothing to commit (working directory clean)

issue2

master

HEAD

解決合併衝突 (cont.)

master

HEAD

Tips - non fast-forward 非快轉合併

Step 8.

以終端機操作為例!
  • Git rebase

    • 取消上一步的合併,切換至 issue2 分支

       

    • master 分支進行 rebase

Rebase

$ git reset --hard HEAD~
$ git checkout issue2
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Hello world
Using index info to reconstruct a base tree...
<stdin>:13: new blank line at EOF.
+
warning: 1 line adds whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging test.cpp
CONFLICT (content): Merge conflict in test.cpp
Failed to merge in the changes.
Patch failed at 0001 Hello world

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".

Tips - 合併衝突訊息 (conflict message)

Step 8.

以終端機操作為例!

Rebase (cont.)

  • 開啟                   會看到以下內容







     

  • 刪除                   中的以下內容

#include <iostream>
using namespace std;

int main(void) {
<<<<<<< HEAD
    cout << "Hello world!" << endl;
=======
    cout << "Hello NSS!" << endl;
>>>>>>> issue2
    return 0;
}
test.cpp
test.cpp
<<<<<<< HEAD
=======
>>>>>>> issue2

Tips - 在 == 上方master修改內容

Tips - 在 == 下方issue2修改內容

Step 8.

以終端機操作為例!

Rebase (cont.)

  • Git rebase --continue

    • 加入並繼續 rebase 動作


       

    • 指令說明

      • 繼續 rebase 動作,使用

      • 取消 rebase 動作,使用

$ git add .
$ git rebase --continue
Applying: Hello world
--continue
--abort

issue1

issue2

master

HEAD

issue2

HEAD

Step 8.

以終端機操作為例!

Rebase (cont.)

  • 切換至 master 分支並合併 issue2 分支

     

issue1

master

HEAD

issue2

HEAD

$ git checkout master
Switched to branch 'master'
$ git merge issue2

master

Finish            branch on local!

接下來,遠端的分支如何操作呢?

Pull

  • 不同步問題 - ​遠端超前本地端,沒衝突直接合併

Remote repository

A

B

M

N

Local repository

A

B

master

origin/master

Remote repository

A

B

M

N

Local repository

A

B

master

origin/master

M

N

Git pull

自動合併

Pull (cont.)

  • 不同步問題 - ​遠端超前本地端,沒衝突直接合併

Remote repository

A

B

M

N

Local repository

A

B

master

origin/master

Remote repository

A

B

M

N

Local repository

A

B

master

origin/master

C

D

Git pull

Tips - 若有衝突,需先解決衝突再手動提交

沒有衝突?

C

D

E

master

Local repository

Fetch

  • 不同步問題 - ​遠端超前本地端,本地端建立遠端分支

Remote repository

A

B

M

N

Local repository

A

B

origin/master

Git fetch

Tips - pull = fetch + merge

master

C

D

HEAD

Local repository

M

N

A

B

master

origin/master

C

D

E

master

FETCH_HEAD

Push

  • Fast-forward 合併

    • 當衝突發生,push 會被拒絕
       

  • Non fast-forward 合併

    • Push 會被拒絕,以防止覆蓋

    • 必須先 pull 最新的遠端變更,在進行 push

Finish            branch on remote!

還有嗎?

當然有!

但是,等用到再自己學吧!

其它用法

  • Git tag 的操作

  • Git commit 進階操作

    • e.g., 修改, 取消, 刪除, 提取, etc.
       

  • 當然不只這些...

等有用到在自己學吧!

好用的資源

Tutorials

Useful Plugins for GitHub

INFO / 陸勇盛 (David Lu)

Thanks for listening!

Q & A

Let's Git

By David Lu

Let's Git

This slide is using for sharing basic tutorial on Git

  • 2,536