git tutorial
DESCRIPTION
c4Lab 2014 暑期訓練課程TRANSCRIPT
Git Tutorial
Jian-Long Huang
@c4Lab 14/7/17
2
什麼是版本控制 (version control) ?
在軟體開發的過程中,程式碼每天不斷的產生,過程中會
發生以下狀況:
1. 檔案被別人或自己覆蓋,甚至遺失
2. 想恢復昨天寫的版本
3. 想知道跟昨天寫的差在哪裡
4. 是誰改了這段程式碼,為什麼
5. 軟體發行需要分成維護版和開發版
3
常見檔案管理方式
直接修改法
複製貼上法
FTP 共同管理法
4
直接修改法
修改 修改
直接在原資料夾修改檔案內容
5
面臨問題
我這次到底修改了什麼
改錯檔案怎麼辦
檔案被我改壞掉,明天要 demo 給老闆怎麼辦
6
複製貼上法
每修改到一定次數就 copy 一次資料夾
複製 & 修改 複製 & 修改
7
面臨問題
這份複製是從那一份複製 copy 來的
這份複製改了什麼
每一份複製都有重複內容,很佔硬碟空間
8
多人協作?
9
FTP 共同管理法
用 FTP 來存放共同開發的檔案
10
面臨問題
誰修改了我的檔案
我改的東西,別人會不會也正在改
別人改了什麼
11
12
因此
我們希望有一種機制,可以幫助我們:
1. 可以隨時復原修改,回到之前版本
2. 多人協作時,不會把別人的東西蓋掉
3. 保留修改紀錄,以供查詢
4. 軟體發行時,可以方便管理不同版本
13
什麼是 Git ?
開源的分散式版本控制系統
Distribution Version Control System (DVCS)
14
Git 簡史
Linus Torvalds 發明
基於 BitKeeper 經驗設計
目的是管理 Linux Kernel 原始碼
2005/4/3 誕生
2005/4/6 第一版發布
2005/6/16 開始管理 Linux Kernel 原始碼
15
誰在用 Git ?
Git
X.org
PostgreSQL
Wine
Fedora
Samba
Eclipse
Qt
Ruby on Rails
Gnome
Debian
Perl
16
Git 特性
分散式版本控制
非線性開發模式
內容定址 (content-addressable) 檔案系統
17
集中式
18
分散式
19
集中式版本控制系統的缺點
沒有網路就不能開發
做什麼事情都要排隊
單點故障風險 (Single point of failure)
20
分散式版本控制系統的優點
參與 Git 開發的每個人,都擁有完整的開發歷史紀錄
當開發人員第一次將 Git 儲存庫複製 (clone) 下來後,完
全等同於這份 Git 儲存庫的完整備份
不需要網路連線就可以獨立運作
當主機損毀時,皆可透過任何一個客戶端先前複製的資
料還原到伺服器
21
非線性開發模式
每個人可以按照自己的步調開發
開分支和合併都相當容易
23
內容定址檔案系統
將檔案內容經過 SHA1 運算所得到一個雜湊值當作檔案
路徑名稱
內容一樣的檔案可以 reuse
24
其他 SCM 的版本儲存方式
只儲存差異的部份
25
Git 的版本儲存方式
利用有向無環圖 (DAG)建立快照(snapshot) ,相同內容只會有一份紀錄
26
儲存庫 (repository)
用來儲存所有版本的一個空間(在 Git 是一個資料夾與
一堆檔案)
建立儲存庫: git init
產生 .git 資料夾,就是一個完整的 Git 儲存庫
27
工作目錄 (working directory)
別名working tree
我們正在準備開發的專案檔案,無論是新增檔案、修改
檔案、刪除檔案、檔案更名,都是在這個目錄下完成
使用 Git 相關指令的時候,也是在工作目錄下完成
28
Git 資料結構
Git 有兩種資料結構,分別是物件 (object) 和索引
(index)
29
Git物件
透過內容產生一組 SHA1雜湊值,然後依照這個雜湊值
所命名的一個檔案
所有物件經過 Zlib演算法進行壓縮,並儲存
在 .git/objects/ 目錄裡面,稱為物件資料庫
物件資料庫只會增加資料、不會減少
裡面的資料都是不可變 (immutable)
四種物件類型: blob、 tree、 commit及 tag
30
範例
一個 Ruby library專案
31
blob物件
記錄檔案內容
32
tree物件
記錄特定目錄下的資訊,包含檔名、對應
的 blob物件名稱以及其他 tree物件
33
commit物件
記錄提交訊息及所包含的 tree物件
(及上一層 commit物件名稱)
每一個 commit物件都是一個版本
34
commit物件內容第一次 commit
第二次以後的 commit ,包含上一層 commit物件名稱
35
tag物件
記錄一個 commit物件(或 blob、 tree
物件)及 tag名稱
37
物件名稱
由 SHA1 運算出來的值,稱為物件的絕對名稱
前面 4 碼 ~40 碼都可以代替絕對名稱
以下的指令都可以達到相同目的
git cat-f ile -p 07c1321be49815d53eb2413f0ad5286010ebb6cc
git cat-f ile -p 07c1
git cat-f ile -p 07c132
38
參照
物件絕對名稱的別名 (alias) 或指標
目的是方便記憶
每一個參照都對應到一個 Git物件絕對名稱
39
Git 參照
.git/refs/heads/(本地分支參照)
.git/refs/remotes/(遠端分支參照)
.git/refs/tags/(標籤)
分支參照指向該分支的最新 commit物件名稱
40
Git 內建參照
儲存在 .git/ 下
HEAD:指向目前分支或目前 commit物件名稱
ORIG_HEAD: 指向HEAD 的前一版
FETCH_HEAD:指向遠端儲存庫各分支的 HEAD
MERGE_HEAD: 執行合併工作時,指向合併來源的
commit物件名稱
41
開分支不用錢
建立分支 (branch) 和標籤 (tag) 事實上等於建立參照,
參考到已經建好的 commit物件名稱
不會有額外負擔(佔空間、耗資源等等)
42
Git索引
索引檔: .git/index
包含檔案路徑、對應的 blob物件和權限
記錄「有哪些檔案即將要被提交到下一個 commit 版本
中」
在提交的時候,索引檔內容用來產生 tree物件
43
操作索引檔
檢視: git ls-f iles
新增檔案: git add
移動檔案: git mv
移除檔案: git rm
檢視工作目錄狀態: git status
記錄變更: git commit
44
索引別名
index(索引)
cache(快取)
directory cache(目錄快取)
current directory cache(當前目錄快取)
staging area(等待被 commit 的地方)
staged f iles(等待被 commit 的檔案)
45
檔案的四種狀態
Untracked f iles
Changes not staged for
commit
Changes to be committed
Committed
索引 目前版本
46
git status
檢視檔案在索引和目前版本之間的差異
Untracked f iles索引和目前版本都沒有
Changes not staged for commit索引沒有
– new f ile: 目前版本沒有
– modif ied: 目前版本有
Changes to be committed索引有
– new f iles: 目前版本沒有
– modif ied: 目前版本有
47
git add
將工作目錄變更寫到索引檔中
git add -u: 僅將「更新」或「刪除」的檔案寫到索引檔
中
48
git rm
rm: 從檔案系統裡面刪除檔案,但未更新到索引檔中
git rm:刪除檔案同時也更新到索引檔
– 相當於 rm + git add -u
git rm --cached: 更新「刪除檔案」到索引檔,但保留工
作目錄下的實體檔案
49
git mv
將檔案重新命名並更新到索引檔
– 相當於 mv + git add -u
50
git commit
將檔案狀態為 Changes to be committed及Committed
的檔案提交變更成一個 commit物件
51
git ls-f iles
列出所有目前已經儲存在「索引檔」中的那些檔案路
徑,預設包含目前版本的所有檔案
52
安裝Git
yum install git-core
apt-get install git
Mac: http://sourceforge.net/projects/git-osx-installer/
Windows: http://msysgit.github.io/
53
Git GUI
GitX (Mac)
GitHub Windows (Win), SourceTree (Mac, Win)
TortoiseGit (Win)
SmartGit/Hg (Mac, Win and Linux)
54
基本設定
編輯~/.gitconf ig 或輸入以下指令
git conf ig --global user.name 'Your name'
git conf ig --global user.email '[email protected]'
git conf ig --global color.ui true
git conf ig --global core.editor 'vi'
55
建立儲存庫
mkdir git-demo
cd git-demo
git init
56
第一次 commit
touch README
git add README
git status
git commit -m 'First commit'
57
修改檔案
編輯 README 做些變更
git status
git diff
git add . (加入所有變更,但不包括刪除檔案)
git status
git diff --cached
git commit -m 'Update README'
58
建立新檔,刪除舊檔
git touch hello.sh
git rm README(或 rm README; git add -u .)
git status
git add hello.sh
git commit -m 'Remove README; add hello.sh'
git log
59
只 commit部份檔案
touch a.pl
touch b.pl
git add a.pl
git commit -m 'Add a.pl'
git add b.pl
git commit -m 'Add b.pl'
60
add 之後又修改內容
修改 hello.sh 做些變更
git add hello.sh
再次修改 hello.sh 做些變更
git commit -m 'Add contents to hello.sh'
– 這時 commit 內容只包含第一次修改的內容
61
重置索引
想把原本加入到索引檔的檔案恢復成尚未加入
(unstaged) 的狀態
git touch Temp
git add Temp
git status
git reset
git status
62
重置索引(二)
恢復被刪除或更新的檔案,需加 --hard
git rm hello.sh
git reset --hard
63
還原被改壞的檔案
想把改壞的檔案恢復到上一次 commit 的狀態
編輯 hello.sh 做些變更
git status
git checkout -- hello.sh
git status
cat hello.sh
git log
64
查詢歷史紀錄
git log
git log -10(限定輸出 10筆記錄)
65
比較版本差異
git diff(working tree比較當前版本)
git diff <SHA1>(working tree比較<SHA1>)
git diff <SHA1> <SHA1>(比較兩個版本)
git diff --stat <SHA1>
git diff --cached( staging area比較當前版本)
66
刪除 untracked 檔案
git clean -n(列出打算要清除的檔案)
git clean -f(刪除 untracked 檔案)
git clean -x (連 .gitignore列的檔案都刪除)
67
設定忽略清單
需手動建立 .gitignore 檔案來定義忽略清單
.gitignore所定義的檔名或路徑將不會被加入索引
https://github.com/github/gitignore
68
Git 分支—什麼時候用?
New features
Bug f ixes
重構
任何實驗
69
查看分支
預設是 master
git branch
master HEAD
70
建立分支
git branch develop
git branch
develop
master HEAD
71
在分支上建立不同版本
echo master >master.txt
git add master.txt
git commit -m 'Add master to master.txt'
develop
master HEAD
72
在分支上建立不同版本
git checkout develop(切換到 develop 分支)
develop
master
HEAD
73
在分支上建立不同版本
echo develop >develop.txt
git commit -m 'Add develop to develop.txt'
develop
master
HEAD
74
將 develop 合併到 master
git checkout master
git merge develop
develop
master HEAD
75
合併衝突 (merge CONFLICT)
兩個分支都在修改同一個檔案,內容不同時
衝突檔案內容會出現 <<<<< =====
>>>>>>
手動解決或 git reset --hard 放棄合併
76
Git遠端操作
事實上就是本地分支和遠端分支之間的合併
產生 ssh key: ssh-keygen -t rsa -b 4096 -C
'yourname@hostname'
將 ~/.ssh/id_rsa.pub 上傳到遠端伺服器
(GitHub、Gitolite)
77
上傳儲存庫到遠端伺服器
在 GitHub新增一個專案 git-demo
git remote add origin [email protected]:your_account/git-
demo.git
git push -u origin master(加 -u預設追蹤 origin 的
master 分支)
之後只需要打 git push進行分支合併
如果出現 ![rejected] 表示衝突,需先 git pull 合併
78
下載已經存在的儲存庫
SSH 協定
– 可以設定讀寫權限
– git clone [email protected]:your_account/git-demo.git
HTTPS 協定
– 只有讀取權限
– git clone https://github.com/your_account/git-demo.git
79
參考資料
Git Internals PDFhttps://github.com/pluralsight/git-internals-pdf
ihower Git教學http://ihower.tw/git/
30 天精通Git 版本控管https://github.com/doggy8088/Learn-Git-in-30-days
那些台灣軟體產業所缺少的–版本控制系統http://blog.ez2learn.com/2011/10/20/taiwan-software-lacking-of-vcs/
Pro Git http://git-scm.com/book/zh-tw/