git
git[1],是一個w:分散式版本控制軟體,最初由w:林納斯·托瓦茲(Linus Torvalds)創作,於2005年以w:GPL釋出。
git是用於Linux核心開發的版本控制工具。與w:CVS、w:Subversion一類的集中式版本控制工具不同,它採用了分散式版本庫的作法,不需要伺服器端軟體,就可以運作版本控制,使得原始碼的發布和交流極其方便。git的速度很快,這對於諸如Linux核心這樣的大專案來說自然很重要。git最為出色的是它的合併追蹤(merge tracing)能力。
git簡明用法
[編輯]實現原理
[編輯]git和其他w:版本控制系統(如CVS)有不少的差別,git本身關心檔案的整體性是否有改變,但多數的版本控制系統如CVS或w:Subversion系統則在乎檔案內容的差異。git拒絕保持每個檔案的版本修訂關係。因此檢視一個檔案的歷史需要遍歷各個history快照;git隱式處理檔案更名,即同名檔案預設為其前身,如果沒有同名檔案則在前一個版本中搜尋具有類似內容的檔案。
每個用戶都可有全部開發歷史的本地副本,changes從這種本地repository複製給其他開發者。這些changes作為新增的開發分支被匯入,可以與本地開發分支合併。
分支是非常輕量級的,一個分支僅是對一個commit的參照。
git是用C語言開發的,以追求最高的效能。git自動完成垃圾回收,也可以用命令git gc --prune
直接呼叫。
git儲存每個新建立的object作為一個單獨檔案。為了壓縮儲存空間占用, packs操作把很多檔案(啟發式類似名字的檔案往往具有類似內容)使用w:差分壓縮入一個檔案中(packfile),並建立一個對應的索引檔案,指明object在packfile中的偏移值。新建立的物件仍然作為單獨檔案存在。repacks操作非常費時間,git會在空閒時間自動做此操作。也可用命令git gc
來直接啟動repack。packfile與索引檔案都用SHA-1作為校驗和並作為檔名。git fsck
命令做校驗和的完整性驗證。
Git伺服器典型listenTCP port 9418.
檔案有三種狀態:已提交(committed),已修改(modified)和已暫存(staged)。已提交表示該檔案已經被安全地儲存在本地資料庫 中了;已修改表示修改了某個檔案,但還沒有提交儲存;已暫存表示把已修改的檔案放在下次提交時要儲存的清單中。
內部目錄結構
[編輯]理解Git的內部目錄結構對於理解Git是如何工作的有重要作用。
. └── .git/ ├── HEAD ├── branches/ ├── config ├── description ├── hooks/ │ ├── applypatch-msg.sample │ ├── commit-msg.sample │ ├── post-update.sample │ ├── pre-applypatch.sample │ ├── pre-commit.sample │ ├── prepare-commit-msg.sample │ ├── pre-push.sample │ ├── pre-rebase.sample │ └── update.sample ├── info/ │ └── exclude ├── objects/ │ ├── info/ │ └── pack/ └── refs/ ├── heads/ └── tags/
- objects:存放git物件
根目錄下的專用檔案
[編輯]COMMIT_EDITMSG
[編輯]上一次提交的資訊儲存在這個檔案中。可用文字編輯器處理。
FETCH_HEAD
[編輯]最後一次的Git命令fectch的操作資訊儲存在這裡。可用於下次Git命令merge。
HEAD
[編輯]指向當前被檢出的代碼(checked out code),也就是當前所在的工作分支。一般指向refs下的某檔案。
也可以進入"detached HEAD"狀態,這時你不在一個本地分支上,而是HEAD直接指向一個提交(commit)而不是一個分支。
config
[編輯]當前git倉庫的組態文件,包含如果在本地倉庫管理與儲存資料,已知的遠端倉庫,本地用戶資訊,其他組態資料。
可用文字編輯器來編譯此文件,或者用Git命令config。
description
[編輯]供倉庫瀏覽器工具使用,包含了當前專案(project)的描述。在非共享倉庫中通常不改變。
index
[編輯]是緩衝(staging)區域。包含了緊湊形式的已經被staged的檔案改變資訊供下一次commit使用。
info/exclude
[編輯]用戶的個人專用檔案,針對倉庫的個人副本。
info/refs
[編輯]如果此檔案存在,倉庫的每個遠端或原生的分支,以及tags,除了在refs/heads與 refs/tags有對應的單個檔案外,還在此檔案中有對應的一行。適用於大型倉庫。
ORIG_HEAD
[編輯]改變當前分支的commit歷史的操作在本檔案中儲存前一次HEAD的值,以允許從錯誤中恢復。
包含其它檔案的目錄
[編輯]branches
[編輯]未見使用
hooks
[編輯]儲存鉤子的檔案夾。包含了git倉庫特定事件發生時要執行的指令碼。Git給出的指令碼,使用副檔名.sample。
logs
[編輯]儲存日誌(reflogs)的檔案夾。reflog用於記錄那些不儲存在提交歷史中的事情,如rebases, fast-forward merges, resets等。每個分支有一個reflog。reflog不是倉庫的公開部分,它嚴格特定於局部副本倉庫,其資訊保留有限時間(確省為兩周)。可用於從錯誤中恢復。
objects
[編輯]所有的檔案、目錄列表、commits的儲存之地。
未包裝(unpacked)的物件存在其下的幾個目錄里,多個壓縮後的物件的包裝在一個包裝目錄里。自動執行的"git gc"會收集未包裝的物件壓縮後放入包裝目錄。
refs/heads
[編輯]每個本地分支的head commit對應單個檔案。另見info/refs
refs/remotes
[編輯]已經定義的每個遠端倉庫對應一個子目錄。在子目錄中,每個遠端分支定義了一個tip commit。
refs/tags
[編輯]Can contain one file defining the commit corresponding to each tag (but see info/refs above). 每個tag的commit對應單個檔案。另見info/refs
svn
[編輯]如果需要Git命令svn提交到一個Subversion伺服器.
物件
[編輯]Git有兩種資料結構:可變的索引(index或stage或cache)用於緩衝工作目錄資訊與下一次提交的版本資訊;不變的、僅追加的物件資料庫。
物件資料庫包含5類物件:
- blob:二進制大物件包含了一個檔案的全部內容。Blobs沒有適當的檔名、時間戳、或其他元資料。一個blob的內部名字是它的內容的hash。
- tree物件:等效於一棵目錄樹。包含全部包含的檔案路徑資訊以及檔案的模式(mode)、blob或tree物件的ID。tree物件是源樹(source tree)的快照。用[[:w:默克樹}}實現。由於並不包含目錄自身的資訊,所以git倉庫不記錄子目錄建立或刪除的資訊,僅記錄所包含的檔案。
- commit物件:指向一棵樹表示了commit之後源樹的狀態。commit物件連結tree物件在一起而成為history。commit物件 包含頂層源目錄的tree物件名字、一個時間戳、提交作者資訊、log資訊、0個或多個父commit物件的名字。
- tag物件是一個名字指向到一個commit,也可以增加關於另外物件的元資料。它可用於數位簽章,以保證特定版本的身分真實。
- branch物件是一個名字指向到一個commit,對於當前檢出的分支,在下一次commit時會自動修改branch物件指向最新的commit。
Blob, tree與commit物件用其內容的SHA-1 hash作為ID。物件放入它的hash值得前兩個字元標識的目錄中,其餘hash字元作為這個物件的檔名。
Git資料庫中不變參照的物件將會被垃圾回收清除。Git命令可以建立、移動、刪除參照。"git show-ref"列出所有參照。某些參照類型:
- heads: 參照一個本地物件,是commit的指標。每個head可以指任意一個這樣的指標。可以包含任意數量的heads。而"HEAD"(全部大寫),僅僅指的是當前有效的head。預設情況下,在每個倉庫下都有一個head,叫做master。
- remotes: 參照遠端repository中的一個物件
- stash: 參照一個還沒有committed的一個物件
- meta: 例如一個bare repository中的一個組態, 用戶權限; refs/meta/config命名空間等[2]
- tags:
提交的拓撲關係
[編輯]Git的提交作為圖的節點,父子關係作為圖的有向邊,那麼提交歷史構成有向無環圖(DAG)。
可達性與垃圾收集
[編輯]一個commit是可達的如果它被branch、tag、reflog條目指向,或是一個可達commit的父親。一棵tree是可達的如果它被一個可達的commit指向。一個blob是可達的如果被一棵可達的tree指向。此外的commit/tree/blob物件都是不可達的,通常是aborted commits、刪除掉的branches等的結果,白白占了儲存空間。
不可達的物件可用git命令gc
收回占用儲存空間。這通常可自動被呼叫。
Git 指令參考
[編輯]Git在內部有個指向目前版本的HEAD指標,表示當前的提交(commit)版本,上一個版本就是HEAD^,上上一個版本就是HEAD^^,往上100個版本可以寫成HEAD~100。提交(commit)版本也可以用SHA1的hash值表示。
獲取和建立項目
[編輯]- 命令git init [repName] 在一個目錄下建立指定名字的資料夾或資料夾已存在,並在資料夾中建立一個倉庫(repository).
- 命令git clone git://github.com/schacon/simplegit.git 複製該專案的全部記錄到本地;並複製該專案的master分支作為工作檔案。
基本快照服務
[編輯]- 命令git add指出下次commit包含哪個檔案。即把指定工作檔案加入快取 -A選項將增加工作目錄所有的檔案。-u選項僅處理緩衝中有的檔案。
- 命令git reset [-q] [<tree-ish>] [--] <paths>…
- 命令git reset [commit-object] [--hard] [--soft] [filename]:從分支[commit-object];如果用--soft選項,那麼工作目錄與快取都不變;如果不用--soft選項,那麼緩衝更改;如果用--hard選項,那麼工作目錄也更改。如果指定檔案,則該檔案更改。
- 命令git commit來建立一個commit object。新的commit object將會把當前的HEAD作為它的父親。commit執行後,HEAD將會指向新的commit object
- 命令git commit -A自動提交工作資料夾內所有修改的檔案(新建的檔案不包含在內)
- 提交訊息Tim Pope writes 第一行不應超出50字元。如需要進一步詳細解釋,第二行為空行,從第三行開始寫,每行不超過72列。使用縮排(hanging indent)。
- 命令git status列出當前工作檔案和HEAD比較,哪些檔案發生了改變。檔案有三種狀態:新的沒有被添加的檔案(可用git add命令添加)、修改的但是沒有被提交的檔案、已經被提交的檔案
- 命令git checkout -- <filename>:把工作區內的指定檔案恢復回到最近一次git commit或git add時的狀態。如果沒有--,就變成了「切換到另一個分支」的命令。
- 命令git reset HEAD <filename>:把指定檔案在暫存區的修改回退到工作區,並把指定檔案在暫存區的內容恢復回到最近一次git commit時的狀態。即把暫存區的修改復原掉(unstage),重新放回工作區。
- 命令git revert <commit>:復原指定的提交所做的改變,這些操作並作為一次新的提交。
- git log [head1]..[head2]:列出head2和head1和head2的公共祖先之間的更改紀錄檔。
- git reflog:記錄了所有的操作歷史
- 命令git mv 檔案重新命名。等效於git rm –cached orig; mv orig new; git add new
- 命令git rm <filename>:將檔案從快取區和工作目錄刪除。 如果要在工作目錄中留著該檔案,可以使用 git rm --cached
- 忽略特定檔案,針對命令
git status
與git add -A
(增加所有新檔案或修改過的檔案)。需要注意的是,用git add [filename]
增加到緩衝中的檔案或者已經提交的檔案,是不能忽略的。為忽略某些檔案,可把檔名(可帶萬用字元)寫入特定的兩個檔案之一:- .git/info/exclude — 這是用戶私有的,不是倉庫公開的資料。
- .gitignore — 由於這是在.git目錄之外,它可以被當作普通檔案上傳到倉庫。適合作為專案中所有用戶共同遵守的忽略檔案的定義。
安裝和組態
[編輯]- config
- help
分支與合併
[編輯]- git branch 檢視倉庫的所有分支
- git branch [new-head-name] [reference-to-commit-object]給指定的物件起一個新的名字
- git checkout -b [new-head-name] 建立一個分支並置為當前工作分支
- git branch -d [head-name] 刪除一個本地分支
- git push remote_rep :remote_branch_name 刪除一個遠端分支
- git branch -r
- git checkout [head-name]:設定head-name為當前的head,重寫目錄下面的所有檔案,就可以在其上開始新的工作
- git merge [head-name]:把head-name指定的commit物件合併到當前commit物件
- git cherry-pick:"複製"一個提交節點並在當前分支做一次完全一樣的新提交。
- git rebase [branch-name] 衍合是合併命令的另一種選擇。在[branch-name]重演當前分支的歷史,提交歷史是線性的。 本質上,這是線性化的自動的 cherry-pick。
--abort
刪除一個commit。 - mergetool
- git log --merge 用於合併衝突
- git log --graph --oneline --decorate --all [branch_name] ^[exclude_branch_name] 顯示一個分支的各個commit的資訊
- git diff --merge 3路diff
- stash
- git tag -a [mytag] [my-branch] 建立一個帶註解的標籤
共享和更新項目
[編輯]- git fetch [remote-alias] 更新/同步本地專案
- git pull [remote-alias] 相當於fetch加上merge
- git push [remote-alias] [branch] 分享本地改動。必須是遠端分支的fast-forwards才可以上傳;否則需要在本地先merge再上傳。
- git push origin :remoteBranchNameToDelete 刪除遠端分支
- git remote 管理遠端倉庫
- git remote -v 檢視遠端倉庫別名的實際連結位址
- git remote add [alias] [url] 添加一個遠端倉庫
- git remote rm [alias] 刪除一個遠端
- git remote show origin
- submodule
檢查和比較
[編輯]- git show <commit>:<filename> 展示某個提交版本的某個檔案的內容
- 命令git diff:列出當前工作目錄與當前快取之間的差別,產生的輸出相容於
diff -u
的輸出。- git diff --cached,列出當前快取與當前commit物件之間的差別
- git diff HEAD,列出當前工作目錄與當前commit物件之間的差別
- git diff [head1]..[head2]:列出head1 和head2之間的區別
- git diff [head1]...[head2](中間三個點):列出head1和head2以及他們所有的祖先之間的區別。
- git format-patch origin/master 建立origin與master之間的patch,產生的輸出相容於
diff -u
的輸出。 - git am: automatically apply it and save the commit
- git apply --stat P1.txt
- git apply --check P1.txt
- git am < P1.txt
- git merge-base [branchA] [branchB] 最近的共同祖先提交
- shortlog
- describe
修補
[編輯]- bisect
- blame
- grep
除錯
[編輯]- bisect
- blame
- grep
電子郵件
[編輯]- am
- apply
- format-patch
- send-email
- request-pull
外部系統
[編輯]- svn
- fast-import
管理
[編輯]- clean
- gc
- fsck
- reflog
- filter-branch
- instaweb
- archive
- bundle
伺服器管理
[編輯]- daemon
- update-server-info
管道指令
[編輯]- cat-file
- commit-tree
- count-objects
- diff-index
- for-each-ref
- hash-object
- ls-files
- read-tree
- rev-list
- rev-parse
- show-ref
- symbolic-ref
- update-index
- update-ref
- verify-pack
- write-tree
GIT GUI客戶端
[編輯]- GitHub Desktop:可用於第三方Git倉庫網站[3]
- Git for Windows
- w:TortoiseGit
- SourceTree
- GitEye
參考文獻
[編輯]- ↑ git - Definition and pronunciation. Oxford Learner's Dictionaries.
- ↑ Gerrit Code Review – Project Configuration File Format
- ↑ Using GitHub for Windows with non-GitHub repositories
外部連結
[編輯]- git官方網站(英文)
- git快速入門(英文)
- git Man Page(英文)
- git用戶手冊(英文)
- git Community Book(英文)
- 使用git管理原始碼
- git# (gitSharp)(英文)
- GNU Interactive Tools
- git從入門到精通P
- 連猴子都能懂的Git入門指南(正體中文)