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入門指南(正體中文)