SlideShare a Scribd company logo
Git
N.C Wu
1
大綱
• 前言
• Git與svn
• Git特性
• Git的歷史背景
• Git概念
• Git安裝
• Git基本指令
• Git分支與合併
• Git的可逆性
• Git協同開發
• Git改寫
• Git GUI
• 結論
• 參考資料
2
版本控制
3
想必大家都用過svn
一定知道版控的好處
4
版本控制
• 因為有紀錄,不怕東西改爛
• 因為有紀錄,不怕檔案遺失
• 讓協同開發變得簡單了
• 誰把code改爛了
• 區分各種版本(正式版、測試版……)
5
Git?
都用svn了還不夠嗎?
6
svn Git
類型 中央式
需連線
server爆掉就GG
分散式
可離線
人人都有一份
協同方式 中央集權 各種working flow
紀錄方式 紀錄檔案差異 快照配合參照
commit方式 會直接送到server 只在local端,需額外下指令
送到remote端
分支 (branch) 相關檔案複製一份 (慢) 利用參照 (reference)
只佔41 bytes (快)
合併 (merge) Two-way merge Three-way merge
檔案完整性 無法檢查 (bad) 利用SHA1檢查 (good)
直接操作子目錄 可以 只能間接,或用submodule
操作方式 比較簡單 比較複雜
有些指令名稱一樣,但概念不一樣
7
紀錄方式:差異 v.s. 快照+參照
紀錄檔案的改變內容
若檔案內容有變動
就把內容一併存下,
否則參照不變
等於是檔案系統了
存A,B, C
存C2
參照B
存A1, C1 存A2, B1 存B2, C3
參照A1, B 參照C2 參照A2 8
合併方式:Two-way v.s. Three-way
Only you and me
You and me plus our base
9
檔案完整性 (Integrity)
• SHA1 hash algorithm:
• 24b9da6552252987aa493b52f8696cd6d3b00373
• a-z + 0-9 (40個字串)
• 根據檔案內容計算而來
• 檔案變動,字串也會變動
• 檔案損毀,字串也會變動
• 如此可確保檔案的完整性
10
Git的歷史背景
- jserv〈我愛Git〉p.60 – p.65
11
心動了嗎?來學Git吧
12
Git「部份」指令一覽
• git init
• git status
• git add
• git commit
• git diff
• git branch
• git rebase
• git merge
• git push
• git pull
• git stash
• …
what the fuxk??
13
Git指令幫手(--help)
• $ git 指令名稱 –help
• 但……根本不是寫給人看的
• $ git init –help
14
Git指令 v.s. svn指令
• 可能有些指令名稱一樣……
• 但意義完全不一樣
• Git != svn
• 請放下svn的概念來學習git
• 否則會很痛苦
15
Git指令是奇怪名字的graph操作指令,
包含創立刪除節點、移動指標
16
Graph? 好熟悉的名字啊!
17
Graph簡單定義
• 可以去的地方 – 節點(node)
• 可以去的方式 – 邊 (edge)
台北
桃園
新竹
台中
客運
客運
客運飛機
18
台北捷運graph版
19
Git是Directional Acyclic Graph
• Directional (有方向的邊)
• A->B與B->A不一樣
• Acyclic (無法形成環狀的邊)
• 例如不可以是A->B->C->D->A
20
Git有參照(reference)
• reference (參照)
• 變數,存的是某個節點 (node) 的位置
• 利用參照變數走訪graph
• 由於是DAG,走訪的方向固定:往初始點(root)移動
• branch A如何走?
• branch B如何走?
• branch C如何走?
21
Git的三個區域
工作區 暫存區 儲存倉
22
Staging Area? WHY?
• working directory可能很亂,多一層保護也不錯
• 讓使用者選擇這次想要被存的程式片段
23
Git = Graph操作 + 參照 + 三個區域
24
Try it in 15 minutes
• https://try.github.io/
• 線上coding網站
• 可以讓你粗淺的掌握git指令概念
• 可能指令打完你還是不知道在幹麻
25
Git安裝
• 官網下載 (連結)
• 點Windows
26
Git安裝
• 點Next
27
Git安裝
• 點Next
28
Git安裝
• 選第二個或第三個
29
Git安裝
• 選第一個
30
Git安裝
• 選第一個
31
Git安裝
• 選第一個
32
Git安裝
• 有點無所謂(隨便)
33
Git初始設置
• 設定使用者與email (一定要)
• 選「開始」-> 搜尋「Git Bash」
$ git config --global user.name “English name"
$ git config --global user.email company@mail.com
• 也可以設定編輯器
$ git config --global core.editor "'C:/Program Files
(x86)/Notepad++/notepad++.exe' -multiInst -nosession"
• 設定檔在家目錄下: .gitconfig
• 參考文件
34
Git基本指令
• git init
• git status
• git add
• git commit
• 晚一點會講GUI!!
command again??
35
Git基本指令
• $ git init
• 把資料夾變成git工作區
• 會多一個.git資料夾
• git資料都在裡面
• 刪除等同於沒版本控制 (別亂刪)
• 試著創立一個有git的版控環境
36
Git基本指令
• 隨便創個文字檔案
• 輸入$ git status
• 再用$ git add filename
• 再輸入$ git status
• 最後$ git commit,輸入內容
• 恭喜,完成第一筆commit!
37
以Git三區域解釋基本指令
• $ git status
• 查看三區域是否一致,並給提示指令
• $ git add filename
• 同步working directory與staging area
• $ git commit
• 把staging area的資料送入repository
38
新增檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
一開始空空如也,所以三個都一樣
查看狀態不會有任何提示
39
新增檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
新增一個檔案A
A
40
新增檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
git發現暫存區並沒有這個檔案,
以git status查看狀態後,會提示是否要add
A
41
新增檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
指令git add A,可同步至暫存區
A A
42
新增檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
git發現存倉跟暫存區不一致,
以git status查看狀態後,會提示是否要commit
A A
43
新增檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
git commit,可同步暫存區與儲存倉庫區
A A A
44
新增檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
三者又都一樣了,所以下git status時,不會有提示
A A A
45
如果想知道graph長怎樣
• $ git log
• $ git log –graph
• 建議用GUI看graph
c1 commit編號 (65585d….)
commit人 (N.C Wu …)
commit日期 (Mon Apr …)
commit訊息 (commit1)
46
修改檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
修改A的內容,順便新增一檔案B
A A A
47
修改檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
此時工作區又與暫存區不同了,下git status會有新的提示
A’ A A
B
48
修改檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A A
B
提示內容:A有修改(modified),B沒追蹤(untracked)
如何把修改後版本與沒追蹤的檔案加到暫存區?
$ git add A B
49
修改檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
新增後,工作區又與暫存區同步了
A’ A’ A
B B
50
修改檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A’ A’
B B B
$ git commit後,暫存區又能與存倉同步
51
再看graph
• $ git log –graph –oneline --decorate
• 建議用GUI看graph
c1
commit編號 (65585…)
commit人
commit日期
commit訊息
c2
commit編號 (fdb59…)
commit人
commit日期
commit訊息
52
不想加入版控的檔案或資料夾
• 不該加入版本控制中的檔案
• log檔、個人環境設定檔、密碼檔、編譯檔等
• 利用.gitignore,忽略不想被追蹤的檔案
• 把不想被追蹤的檔案名稱加到裡面
• 可以用glob pattern ( *.log )
• 資料夾也可以加 ( target/ )
53
commit時機?commit訊息?
• 1件事1個commit
• 做的事情要可以用一句話來描述
• 練習時先亂寫commit訊息也沒關係
• 後面會教git進階用法
• 參考連結
54
恭喜學會git基礎指令
55
git – branch & merge篇
56
參照(reference)
• 變數,存的是某個節點 (node) 的位置
• 變數,存的是某個commit (node) 的編號
• 利用參照變數走訪graph
• 利用參照變數列出過去的commit ($ git log)
• 一直列出到root為止
57
參照(reference)
• 變數,存的是某個commit (node) 的編號
• 利用參照變數列出過去的commit ($ git log)
c1
commit編號 (65585…)
commit人
commit日期
commit訊息
c2
commit編號 (fdb59…)
commit人
commit日期
commit訊息
58
參照(reference)
• 變數,存的是某個commit (node) 的編號
• 利用參照變數列出過去的commit ($ git log)
• master是參照變數,存的內容是fdb5910…. (c2編號)
c1 c2 master
59
參照(reference)
• 變數,存的是某個commit (node) 的編號
• 利用參照變數列出過去的commit ($ git log)
• master是參照變數,存的內容是fdb5910…. (c2編號)
• 利用HEAD紀錄目前使用的參照變數
c1 c2 master
head = master
60
參照(reference)
• 變數,存的是某個commit (node) 的編號
• 利用參照變數列出過去的commit ($ git log)
• master是參照變數,存的內容是fdb5910…. (c2編號)
• 預設的參照,名字就叫master
• 可以改名
• 利用HEAD紀錄目前使用的參照變數
• 指向某個參照,一開始指向master
• 利用HEAD切換不同參照
c1 c2 master
head = master
61
參照(reference)
• 變數,存的是某個commit (node) 的編號
• commit之後,都會指向最新的commit編號
• master
• 預設的參照,名字就叫master
• 也可以改名
• HEAD
• 指向某個參照,一開始指向master
• 利用HEAD達成切換不同參照
62
git指令與graph概念對照
• reference (參照)
• 變數,存的是某個commit (node) 的編號
• 利用參照變數列出過去的commit ($ git log)
• branch (分支)
• 其實就是參照變數 (ex, master)
Git指令是奇怪名字的graph操作指令,
包含創立刪除節點、移動指標
63
參照(reference)
• 變數,存的是某個commit (node) 的編號
• commit之後,都會指向最新的commit編號
• master
• 預設的參照,名字就叫master
• 也可以改名
• HEAD
• 指向某個參照,一開始指向master
• 利用HEAD達成切換不同參照
讓我們把名字換一下 64
分支(branch)
• 變數,存的是某個commit (node) 的編號
• commit之後,都會指向最新的commit編號
• master
• 預設的分支,名字就叫master
• 也可以改名
• HEAD
• 指向某個分支,一開始指向master
• 利用HEAD達成切換不同分支
其實都一樣 65
參照(reference) = 分支(branch)
66
branch指令
• 創造新的branch
• $ git branch branch_name
• 列出本地端所有的branch
• $ git branch
• 星星表示目前所在的分支
• 切換head到不同的branch
• $ git checkout branch_name
c1 c2 master
head = uccu
uccu
67
1) 在uccu上新增笑話文件,然後commit
2) 在master上新增檔案C,然後commit
任務:
68
69
70
再看graph
• branch
• commit之後,都會指向最新的commit編號
• 在master branch新增C
• 在uccu branch新增joke.txt
• 會發生什麼事?
c1 c2 master
head = uccu
uccu
71
再看graph
• $ git log –graph –oneline --decorate
master
head = master
uccu
65585.. 4583a.. 9f7c08..
bd1cd..
72
不同分支的log有所不同
73
master
head = master
uccu
65585.. 4583a.. 9f7c08..
bd1cd..
branch真的很便宜
• branch 等同於 reference
• 新增一個參照變數,佔硬碟多大容量?
• 41 bytes (40個字串 + 1個換行符號)
• branch存放在哪裡?
• .git/refs/heads/
• 以master branch為例
74
動動腦時間:branch該如何使用?
75
branch使用情境
• 修bug / hotfix
• refactoring (重構)
• 開發新功能 (feature)
• 測試、實驗
• 怕把程式搞爛的時候,就可以開branch
• 保存資訊
• 就像玩遊戲存檔一樣
• 現場demo的時候,快速切換版本
• 上次的Junit就是這麼做的
76
動動腦時間:幹麻一定要開分支?
我一直在master上開發不行嗎?
77
branch優點
• 方便協同開發
• 就算是一個人,也會有手忙腳亂的時候……
• 正在開發某個新功能時,忽然發現以前的code有bug
• 還是要開分支啊
78
branch缺點
• 話說天下大勢,分久必合,合久必分
• 《三國演義》
• 情人總分分合合……
• 《我們的歌》王力宏
• 說合就合?有這麼簡單?
79
合併方式
1) 合併uccu到master上
2) 合併master到uccu上
有差?沒差?
成龍好忙
80
中國合併台灣
台灣合併中國
當然不一樣啊!!!
81
merge(合併) 指令
• 合併uccu到master上
• head -> master ($ git checkout master)
• git merge uccu
• 合併master到uccu上
• head -> uccu ($ git checkout uccu)
• git merge master
(選我正解)
(通常不這麼做)
82
Demo (master合併ucccu)
83
從graph看merge
• 合併uccu到master上
master
uccu
65585.. 4583a.. 9f7c08..
bd1cd..
head = uccu
84
先切換分支到master
從graph看merge
• 合併uccu到master上
master
uccu
65585.. 4583a.. 9f7c08..
bd1cd..
head = master
85
接著合併uccu
從graph看merge
• 合併uccu到master上
master
uccu
65585.. 4583a.. f60d7..
bd1cd..
9f7c08..
head = master
86
git指令與graph概念對照
• merge branch (合併分支)
• 其實就是創造一個有兩個邊的節點
• 目前所在的分支(參照),合併後會自動指向此節點
• 當然也會同步兩邊的資料
Git指令是奇怪名字的graph操作指令,
包含創立刪除節點、移動指標
87
刪除branch
• 合併之後可以刪除uccu branch
• git branch –d uccu
• 此時硬碟減少了41byte
master
65585.. 4583a.. f60d7..
bd1cd..
head = master
9f7c08..
uccu
88
合併衝突 (merge conflict)
• 有時候並不是那麼順利
• File1.txt的內容 (three-way merge)
base master feature1
add content new content add content
line 2
<<<<<<< HEAD
new content
=======
add content
line 2
>>>>>>> feature1
<<<<<< HEAD指到的分支
xxxxxx
======
======
xxxxx
>>>>>> 準備併進來分支
89
Demo
90
解決衝突
• 逃避法(還原法)
• git merge –abort
• 好像什麼事都沒發生過一樣
• 常規法
• 用編輯器解決「>>>> =====」與「===== <<<<<」之間
的程式碼(人工判斷)
• 判斷後存檔且加入暫存區 (git add file_name)
• commit後即合併 (git commit)
91
為什麼不把master合併到uccu?
92
在feature上合併master 在master上feature
93
非線性歷史
線性歷史
94
commit history
• 越清楚越好讀
• 越清楚越好找 (bisect)
• 越清楚越好還原(revert)
95
真實世界其實一團混亂
當需要用到master branch的資料時,也只能merge master嗎?
96
rebase (另一種merge)
97
rebase – 單字解釋
• rebase = re + base
98
rebase – graph原理
• rebase = 重新找起點 (尋根之旅)
• 起點 = 原本的邊所形成的路徑
• rebase = 改變原本路徑,並以某個節點為新起點
• feature1原本的路徑
• c2 -> c1 -> c0
99
c1 c2
b1
c0
master
feature1
rebase – graph原理
• rebase =改變原本路徑,並以某個節點為新起點
• feature1原本的路徑
• c2 -> c1 -> c0
• 現在以master為新起點,改變feature1的路徑
c1 c2
b1
c0
master
feature1
100
rebase – graph原理
• rebase =改變原本路徑,並以某個節點為新起點
• feature1原本的路徑
• c2 -> c1 -> c0
• 現在以master為新起點,改變feature1的路徑
• 綠c2 ->綠c1 -> b1 -> c0
c1 c2
b1
c0
master
feature1
c1 c2
101
rebase – graph原理
• 以master為新起點,改變feature1的路徑
• 綠c2 ->綠c1 -> b1 -> c0
• 複製一份新的節點,意味著commit資料相同
• 除了commit編號不同
• 舊有的節點還在,只是沒有參照
c1 c2
b1
c0
master
feature1
c1 c2
102
rebase 指令
• $ git rebase master
• 在某個branch上
• 以master為新起點,改變路徑
• 案例示範
• 發現bug需要快速修改,開了hotfix分支
• bug改完,但是master也已經增加了新的commit
• 此時不合併(merge),改用rebase
• hotfix以master為新起點,改變路徑 (git rebase master)
• 再從master合併hotfix (git merge hotfix)
103
Demo
104
Demo小細節
• 雖然內容相同,但commit編號改變了
• 多了a7f7134
• 原本的bb3092d也還在,只是沒有參照
rebase前 rebase後 105
Demo小細節
• fast-forward??
• 快轉,直接往前進
• 何時發生?
• 分支接續著master時
• 兩分支的節點可直接相連
106
rebase示範
107
以最新的節點當作新起點,改變路徑
紀錄歷史過程不同
但是結果相同
merge v.s. rebase
108
rebase v.s. merge
• 透過rebase與merge才能達到linear history
• 主幹(master) 合併分支 (gti merge branch_name)
• 以主幹為起點,改變分支路徑 (git rebase master)
• 所以不把master合併到uccu
• uccu需參考master,適時改變起點
109
恭喜學會git中級指令
110
git指令是否可逆?
111
git的世界是可逆的
1. 檔案
• git status會給提示
• git checkout commit_number file_name
• git reset commit_number file_name
2. commit
• git reset [--參數] commit_number
• --soft
• --mixed (預設)
• --hard
• git revert commit_number
3. git reflog
112
取消修改檔案 (工作區 <- 暫存區)
113
取消修改檔案 (工作區<- 暫存區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
修改A的內容,順便新增一檔案B
A A A
114
取消修改檔案 (工作區<- 暫存區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
此時工作區又與暫存區不同了,下git status會有新的提示
A’ A A
B
115
取消修改檔案A (工作區<- 暫存區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A A
B
$ git checkout -- A
116
取消修改檔案A (工作區<- 暫存區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A A A
B
$ git checkout -- A
從暫存區同步檔案A到工作區
117
取消修改檔案B (工作區<- 暫存區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A A A
B
走火入魔了嗎?直接刪掉就好啦 XD
B呢?
118
取消修改檔案 (暫存區<-存倉區)
119
取消修改檔案 (暫存區<-存倉區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
修改A的內容,順便新增一檔案B
A A A
120
取消修改檔案 (暫存區<-存倉區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A A
B
新增修改過的A’與B到暫存區
$ git add A B
121
取消修改檔案 (暫存區<-存倉區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A’ A
B
此時出現新提示
B
122
取消對A檔案的修改 (暫存區<-存倉區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A’ A
B
$ git reset head A
B
123
取消對A檔案的修改 (暫存區<-存倉區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A A
B
$ git reset head A
B
把head的檔案A,同步到暫存區
head 目前指到的分支(ex, master)
工作區跟暫存區的內容是不一樣的!
124
取消對B檔案的修改 (暫存區<-存倉區)
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A A
B
$ git reset head B
B
125
取消修改檔案
(工作區 <- 暫存區 <-存倉區)
此動作不可逆,請小心
126
取消修改檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
修改A的內容,順便新增一檔案B
A A A
127
取消修改檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A A
B
新增修改過的A’與B到暫存區
$ git add A B
128
取消修改檔案
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A’ A
B B
129
取消對A檔案的修改
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A’ A’ A
B B
$ git checkout head A
130
取消對A檔案的修改
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
A A A
B B
把head的檔案A,同步到暫存區與工作區
head 是目前指到的分支(ex, master)
A’完全消失了,沒救!
$ git checkout head A
131
另類用法
• HEAD~1 = HEAD的前一個commit
• HEAD~2呢? 前兩個
• git checkout head~1 A
• 工作區與暫存區的檔案A被換掉
• 檔案A變成前一個commit的版本
• git reset head~1 A
• 暫存區的檔案A被換掉,變成前一個commit的版本
• 工作區的檔案A維持現狀
132
不安全
較安全
取消commit
133
取消commit
• 留下痕跡的取消
• revert (還原)
• 不留痕跡的取消
• reset (重設)
• 三種: soft, mix, hard
134
revert (還原)
• 過去的某個commit新增了一個檔案
• 現在想把「新增這個檔案」的動作還原
• $ git revert 9358db
• 或 $ git revert HEAD~1
• 兩者相同
c2f39..
merge xxx
9358db..
add file3
a7f13..
hoxfix1
master head = master
135
revert demo
136
revert (還原)
• 過去的某個commit新增了一個檔案
• 現在想把「新增這個檔案」的動作還原
c2f39..
merge xxx
9358db..
add file3
a7f13..
hoxfix1
head = master
master
a7f13..
revert “add file3”
master
137
reset (重設)
• $ git reset [參數] commit_number
• --soft
• 移動head
• 存倉區內容會因此改變
• --mixed (預設)
• 移動head + 同步暫存區內容
• 存倉區與暫存區的內容會改變
• --hard
• 移動head + 同步暫存區內容 + 同步工作區內容
• 存倉區、暫存區與工作區的內容皆會改變
• 沒救了,無法回復
138
reset –soft demo
• $ git reset –soft HEAD~2
• 移動head到前面第二個commit
reset –mixed demo
• $ git reset HEAD~2
• 移動head到前面第二個commit ,且同步暫存區
reset –hard demo
• $ git reset –hard HEAD~2
• 移動head到前面第二個commit ,且同步暫存區
與工作區
reset --hard
• 真的沒救嗎?
• 沒有commit過的資料100%沒救
• 38eb946上面的資料有救,但……如何存取?
c1 c2c0
master
eb43b.. 9e5e6a.. 38eb94..
head = master
142
git核心概念
• 一般而言,只會越存越多commits
• 不會主動刪除任何commits
• 只會定時清理參照走不到的節點 (garbage collect)
143
git垃圾車
• 定時清理參照走不到的節點 (gc)
• 參照概念複習
• 利用參照變數列出過去的commit ($ git log)
• 一直列到root (起點) 為止
• c1 -> c0
• c2參照走不到,以後會被gc
• 所以現在還有救
• 但如何存取?
c1 c2c0
master
eb43b.. 9e5e6a.. 38eb94..
head = master
144
救星reflog
• git reflog
• 版本控制中的版本控制
• 紀錄HEAD的歷史過程(commit, merge, branch, …)
• 資料只存在使用者的電腦 (不是每台都有)
• 如何存取c2?
• 重新把參照指向該節點
• 或新增指向c2的分支
c1 c2c0
master
eb43b.. 9e5e6a.. 38eb94..
head = master
145
救星reflog
• 重新把參照指向c2 或 新增指向c2的分支
• 如果記得commit編號
• git reset –hard 38eb94 或 git branch br_name 38eb94
• 如果不記得commit編號
• git reflog 可查詢歷史紀錄
• 接著直接還原該歷史紀錄
• git reset –hard commit_number
c1 c2c0
master
eb43b.. 9e5e6a.. 38eb94..
head = master
146
demo
147
reflog
• commit在還沒被gc前,還是存在的
• 資料存放在.git/logs/
• 如果手殘把logs刪掉
• 可以用git fsck檢查存倉
• 參考文件
148
git可逆一覽表
149
git – 協同開發篇
150
git 概念複習
• 還記得我們說過git是分散式版本控制嗎?
• 意味著不是中央集權
• 人人都有資料
• 資料分散在各處
• 如何同步分散在各處的資料?
• git clone (複製)
• git push (推)
• git fetch (取)
• git pull (拉)
151
分散式版本控制
• 雖然不是中央集權,但依然有中央的概念
• 方便開發者們存取資料
• 以shared repo為中心,同步開發者們的commit
• 依照不同工作流程,有不同存取方式
152
git三區域
工作區
(working directory)
暫存區
(staging area)
儲存倉庫區
(repository)
153
git三區域 + 遠端存倉區
工作區
(wd)
暫存區
(staging area)
本地存倉區
(local repo)
遠端存倉區
(remote repo)
git push
git fetch
git pull
概念上是fetch + merge,但名字叫做pull
154
git三區域 + 遠端存倉區
155
git三區域 + 遠端存倉區
156
指令概念解說
• 無中生有
• git clone URL(https/ssh)
157
指令概念解說
• 有資料,但需要同步
• 上傳本地資料到遠端
• git push (推)
• 下載遠端最新資料
• git fetch (取)
• 下載且合併最新遠端資料
• git pull (拉)
• 資料包含commit與branch
• 歷史紀錄是不會被同步的 (reflog)
158
讓我們把名字換一下
git指令對照graph
• 同步不同存倉之間的graph
• 同步本地graph到遠端存倉
• git push (推)
• 同步遠端graph,但不變更本地graph (no merge)
• git fetch (取)
• 同步遠端graph且變更本地graph (merge)
• git pull (拉)
• graph包含commit與branch
• 無法參照的節點(node) 不會被上傳或下載
159
一樣是在操作graph
只是在同步本地與遠端的graph
Git指令是奇怪名字的graph操作指令,
包含創立刪除節點、移動指標
160
建立對應關係
1. 無中生有時
• git clone之後已經建立對應關係
2. 先有本地端,接著才建立遠端時 (要先push一次)
• 連上遠端網站
• 建立新的repo
• 建立local repo與remote repo的關聯性
161
建立對應關係
• .git/config中敘述了本地與遠端的對應關係
• 遠端預設的名字叫做origin (可以改)
• 也可以多個遠端
162
對應關係
本地有master,遠端當然也有master囉
163
remote_name / br_name (例如: origin/master)
還是在操作graph (fetch為例)
164
branch對應
• 新增本地端分支A,且對應到遠端某分支A
• $ git branch br_name remote_name/br_name
• $ git branch A origin/A
• 在本地新增一個分支B,如何上傳此分支?
• $ git push remote_name br_name
• $ git push origin B
165
上傳(push)會失敗嗎?
• 當大家都想push到同一個分支,且push內容不同時
c1
x
c0
origin/master
c1c0
yc1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
166
上傳(push)會失敗嗎?
• 當大家都想push到同一個分支,且push內容不同時
• 甲先上傳 => ok沒問題
c1c0
origin/master
c1c0
c1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
x
x
y
origin/master
167
上傳(push)會失敗嗎?
• 當大家都想push到同一個分支,且push內容不同時
• 乙接著上傳 => 衝突! (conflict) => 失敗,不給傳
c1c0
origin/master
c1c0
c1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
x
y
origin/master
x
168
push衝突時
• 如何解決衝突?
• 強制上傳?
c1c0
origin/master
c1c0
c1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
x
y
origin/master
x
169
push衝突時
• 如何解決衝突?
• 乙強制上傳!(x被蓋掉)
c1c0
origin/master
c1c0
c1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
y
x origin/master
origin/master
y
170
push衝突時
• 如何解決衝突?
• 結果就爆炸了!
• 甲會認為遠端是x,但實際上是y
c1c0
origin/master
c1c0
c1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
y
x origin/master
origin/master
y
171
push衝突時
• 如何解決衝突?
• 請用rebase or merge
c1c0
origin/master
c1c0
c1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
y
x origin/master
origin/master
y
172
push衝突時
• 規範好的工作流程
• 不要在master上開發,針對不同議題創造不同分支
• x議題 -> 開x分支 -> push x分支
• y議題-> 開y分支 -> push y分支
• 專案擁有者確認無誤後,會合併到master
• 何時使用強制(force) push?
• 該分支只有你在用 (或是你創造的分支)
• 分支被別人搞爛時,只有你的版本是正常時
173
上傳原則
• 已經上傳的資料不能再被強制修改
• 否則會影響已經下載資料的開發者們
• 請用rebase或merge
174
處理上傳衝突示範
• 甲先上傳
c1
x
c0
origin/master
c1c0
yc1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
175
處理上傳衝突示範
• 甲先上傳
• git origin master => ok沒問題
c1c0
origin/master
c1c0
c1c0
遠端
甲電腦
乙電腦
x != y
甲/master
乙/master
x
x
y
origin/master
176
處理上傳衝突示範
• 換乙上傳
• git origin master => git表示衝突,不給傳
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
177
處理上傳衝突示範
• 乙需取得remote的資料
• git fetch
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
x
origin/master
178
處理上傳衝突示範
• 這時候看是要rebase或是merge
• rebase跟merge的差異 (複習)
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
x
origin/master
179
merge版
• $ git merge origin/master
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
x
origin/master
會多一個節點 180
merge版
• 接著上傳
• git push origin master
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
x
origin/master
y
連帶多了一堆節點
181會多一個節點
pull = fetch + merge
• git pull origin master 等同於
• git fetch + git merge origin/master
• 雞婆的幫你merge了
• 加上—rebase就變成rebase
182
rebase版
• rebase = 改變原本路徑,並以某個節點為新起點
• 以origin/master為新起點,改變master的路徑
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
x
origin/master
183
rebase版
• $ git origin/master master
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
x
origin/master
y
會複製一份新的!
184
rebase版
• 再上傳一次
• git push origin master
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
x
origin/master
會複製一份新的!
185
y
rebase版
• 再上傳一次
• git push origin master => ok了
c1c0
origin/master
c1c0
遠端
乙電腦
x != y
乙/master
x
y
x origin/master
會複製一份新的!
186
y
y
merge v.s. rebase again
c1c0
origin/master
merge版本的遠端
x
y
c1c0
rebase版本的遠端
x
origin/master
187
y
恭喜git畢業了
188
push之前可以做的壞好事
(git 精髓篇)
189
常常會發生的事情
• commit後才發現剛剛打錯字
• 已經送出的commit 可以改錯字嗎?
• 誤打誤撞把某個功能生出來
• commit紀錄一片混亂,全世界只有自己看得懂
• 已經送出的commit可以重新編排嗎?
190
修改 (amend)
• git commit –amend
• 忘記加入某個檔案
• 忘記刪除某個檔案
• 程式碼的註解有錯字
• commit訊息打錯字
• ………
• 使用範圍僅限於最新提交的commit
• for c2 only
c1 c2 master
191
amend demo
192
git概念
• git不會主動幫你刪除任何節點
• 除了倒垃圾時間 (gc)
c1 c2 master
c1 c2
masterc3
amend之前
amend之後 commit編號不一樣
存的內容也不一樣
193
多重修改 (rebase –i)
• 除了最新的commits,也想修改較舊的commits
• 除了c3,也想修改c2, c1
• 可以作到的程度
• 更改commit訊息
• 合併c1, c2
• 交換c1, c2的位置
• 在c1與c2之間多一個commit
• 只留下c3
• 建議開一個新的分支來做實驗
c1 c3 masterc2
194
rebase --i
• rebase = 改變原本路徑,並以某個節點為新起點
• rebase –i HEAD~3 (或輸入c0 number)
• 修改自己路徑上最後三個commits
• 以c0為新起點,改變自己的路徑
c0是新起點 headhead~1
head~3
c1 c3 masterc2c0
head = master
head~2
195
rebase --i
• rebase –i HEAD~3 (或輸入c0 number)
• 修改自己路徑上最後三個commits
• 以c0為新起點,改變自己的路徑
• 其實就是換一條線而已
c1 c3
master
c2c0
head = master
c1 c3c2
196
c0是新起點
rebase --i
• rebase –i HEAD~3 (或輸入c0 number)
• 幫你處理選擇的節點 (c1, c2, c3)
• 依照不同選項,處理方式有所不同
c1 c3
master
c2c0
head = master
c1 c3c2
197
c0是新起點
rebase --i
• rebase –i HEAD~3 (或輸入c0 number)
• 幫你處理選擇的節點 (c1, c2, c3)
• 改變commit紀錄訊息
c1 c3
master
c2c0
head = master
c1 c3c2
198
c0是新起點
rebase --i
• rebase –i HEAD~3 (或輸入c0 number)
• 依照不同選項,處理方式有所不同
• 刪除c2
c1 c3
master
c2c0
head = master
c1 c3
199
c0是新起點
rebase --i
• rebase –i HEAD~3 (或輸入c0 number)
• 依照不同選項,處理方式有所不同
• 合併c1, c2 (squash)
c1 c3
master
c2c0
head = master
c1’ c3
200
c0是新起點
rebase --i
• rebase –i HEAD~3 (或輸入c0 number)
• 依照不同選項,處理方式有所不同
• 交換c1, c2的位置
c1 c3
master
c2c0
head = master
c2 c3c1
201
c0是新起點
rebase --i
• rebase –i HEAD~3 (或輸入c0 number)
• 依照不同選項,處理方式有所不同
• 在c1, c2之間多一個commit
c1 c3
master
c2c0
head = master
c1 c3c2c4
202
c0是新起點
git rebase --i
• --i = 互動模式 (interactive)
• pick, reword, edit, squash, fixup, exec, drop
• 記得開一個分支來做實驗
203
關於git改寫歷史
• push之前才可以改寫歷史,否則……
• push之後想改怎麼辦?
• 利用revert修改
• 增加新的commit修改
204
關於git改寫歷史
• commit history
• 越清楚越好讀
• 越清楚越好找 (bisect)
• 越清楚越好還原(revert)
• 真實情況是一片混亂,歷史紀錄看起來卻不是
205
恭喜成為git一代宗師了
206
武功再棒也比不上洋槍 (GUI篇)
207
好的工具帶你上天堂
• TortoiseGit (連結)
• 設計上偏向svn的操作方式
• Eclipse內建 (連結)
• 請下載EE版的Eclipse,已內建
• 同步率有bug (誤差)
• SourceTree (連結)
• 個人推薦
• GUI只實作Git大部分的功能
• 會有只能手動打指令的時候
• 了解底層概念與指令還是有必要的
GUIGit
208
SourceTree
209
Eclipse – Git plugin
• 選項叫「Team」不叫Git (有事嗎?)
210
Eclipse – Git plugin
• 許多選項的視窗是分開的
• 個人是覺得比較麻煩一點
• 有時候會秀逗
• 需要重開或是記得按「重新整理」
211
TortoiseGit
• 設計方式偏svn
• 連帶影響使用者以svn思維使用git
• 但是Git不是svn,沒有必要
212
GUI
• 個人建議是使用SourceTree
• 提供完整的圖形界面
• 若不習慣Git,一開始可以用烏龜git
• Eclipse用來寫程式
• 建立一套自己熟悉的工作流程
213
一些沒有講到但也很重要……
• 比較檔案差異 (git diff file_name)
• GUI可以直接看差異
• 只commit檔案中的某些差異 (git add –p file_name)
• GUI可以作到
• 替commit加上tag (git tag commit_number)
• GUI可以作到
214
一些沒有講到但也很重要……
• Pull Request (一種遠端merge分支的方式)
• 跟使用的git server有關 (配合fork)
• 還沒commit的程式碼,但又要切換分支時……
• $ git stash可以暫存 ($ git stash pop存取暫存)
• 或是直接開分支暫存,之後再還原
• Git底層的實作方式
• 利用blob, tree, commit, tag, ref達成
• 有空自己去看參考資料吧
• 可參考jserv的〈我愛Git〉p.30 - 36
215
Git總表 – 連結
216
結語
• git概念 = 操作graph + 參照 + 三區域
• 說穿了不值錢啊~
• 概念比指令還重要!
• 利用已知事物學習未知事物
217
參考資料
• love git (jserv)
• Git 線上教材 (ihower)
• 連猴子都能懂的git入門指南
• git 30天教材 (Will)
• think like a git
• git magic
• Git for Computer Scientists
• Git from bottom
• rebase & merge concept
218
參考資料
• atlassian git tutorials
219

More Related Content

What's hot (20)

PDF
Yet another introduction to Git - from the bottom up
Wen-Tien Chang
 
PDF
初心者 Git 上手攻略
Lucien Lee
 
PDF
Git in a nutshell
Nelson Tai
 
PDF
幸福快樂的完美結局
Anna Su
 
PPTX
Git & Sourcetree 介紹
Adison wu
 
PDF
Git tutorial for windows user (給 Windows user 的 Git 教學)
Cloud Tu
 
PPTX
Mercurial簡介與教學
芳本 林
 
PPTX
工程師必備第一工具 - Git
Alan Tsai
 
PDF
Linux Binary Exploitation - Heap Exploitation
Angel Boy
 
ODP
Git basis - usage
Eason Cao
 
PDF
Git Tutorial
Drake Huang
 
PPTX
Git &amp; git hub v1.2
Chris Chen
 
PDF
Add mailinglist command to gitolite
琛琳 饶
 
PPTX
Git 入門與實作
奕浦 郭
 
PDF
Linux Binary Exploitation - Stack buffer overflow
Angel Boy
 
PDF
Binary exploitation - AIS3
Angel Boy
 
PDF
Git 版本控制 (使用教學)
Jui An Huang (黃瑞安)
 
PDF
Git 入门实战
icy leaf
 
PDF
110824 knoss-windows系统机制浅析
Zoom Quiet
 
PDF
連哈秋都懂的Git教學
hydai
 
Yet another introduction to Git - from the bottom up
Wen-Tien Chang
 
初心者 Git 上手攻略
Lucien Lee
 
Git in a nutshell
Nelson Tai
 
幸福快樂的完美結局
Anna Su
 
Git & Sourcetree 介紹
Adison wu
 
Git tutorial for windows user (給 Windows user 的 Git 教學)
Cloud Tu
 
Mercurial簡介與教學
芳本 林
 
工程師必備第一工具 - Git
Alan Tsai
 
Linux Binary Exploitation - Heap Exploitation
Angel Boy
 
Git basis - usage
Eason Cao
 
Git Tutorial
Drake Huang
 
Git &amp; git hub v1.2
Chris Chen
 
Add mailinglist command to gitolite
琛琳 饶
 
Git 入門與實作
奕浦 郭
 
Linux Binary Exploitation - Stack buffer overflow
Angel Boy
 
Binary exploitation - AIS3
Angel Boy
 
Git 版本控制 (使用教學)
Jui An Huang (黃瑞安)
 
Git 入门实战
icy leaf
 
110824 knoss-windows系统机制浅析
Zoom Quiet
 
連哈秋都懂的Git教學
hydai
 

Similar to Git introduction (20)

PDF
Introduction to git
Bo-Yi Wu
 
PPTX
Git and git hub
唯 李
 
PDF
Learning to Use Git | WeiYuan
Wei-Yuan Chang
 
PDF
為自己學 Git
昀 李
 
PDF
Git 版本控制系統 -- 從微觀到宏觀
Wen-Tien Chang
 
PPTX
大家應該都要會的工具 Git 從放棄到會用1-基礎篇
Alan Tsai
 
PPTX
Git入門介紹
mudream4869
 
PDF
Git由超淺入超深
羊 小咩 (lamb-mei)
 
PDF
寫給大家的 Git 教學
littlebtc
 
PDF
Git and Github basic with SourceTree
Chu-Siang Lai
 
PDF
How to Use Git?
newegg
 
PDF
Intro to Git 投影片
Tony Yeh
 
PDF
如何與 Git 優雅地在樹上唱歌
Mu Chun Wang
 
PPTX
GIT實務操作與理論
鵬 大
 
PDF
Git 簡介(古時候的簡報備份)
Hsin-lin Cheng
 
PDF
Git 經驗分享
Mu Chun Wang
 
PPTX
20150313 ian git
LearningTech
 
PPTX
Git raiders of junior
Kevin Chen
 
PPTX
Git使用入门
dpf2e
 
PDF
Git&Github Tutorial
Ting Wen Su
 
Introduction to git
Bo-Yi Wu
 
Git and git hub
唯 李
 
Learning to Use Git | WeiYuan
Wei-Yuan Chang
 
為自己學 Git
昀 李
 
Git 版本控制系統 -- 從微觀到宏觀
Wen-Tien Chang
 
大家應該都要會的工具 Git 從放棄到會用1-基礎篇
Alan Tsai
 
Git入門介紹
mudream4869
 
Git由超淺入超深
羊 小咩 (lamb-mei)
 
寫給大家的 Git 教學
littlebtc
 
Git and Github basic with SourceTree
Chu-Siang Lai
 
How to Use Git?
newegg
 
Intro to Git 投影片
Tony Yeh
 
如何與 Git 優雅地在樹上唱歌
Mu Chun Wang
 
GIT實務操作與理論
鵬 大
 
Git 簡介(古時候的簡報備份)
Hsin-lin Cheng
 
Git 經驗分享
Mu Chun Wang
 
20150313 ian git
LearningTech
 
Git raiders of junior
Kevin Chen
 
Git使用入门
dpf2e
 
Git&Github Tutorial
Ting Wen Su
 
Ad

Git introduction