git[1],是一個w:分散式版本控制軟件,最初由w:林納斯·托瓦茲(Linus Torvalds)創作,於2005年以w:GPL釋出。

維基百科中的相關條目:

git是用於Linux內核開發的版本控制工具。與w:CVSw:Subversion一類的集中式版本控制工具不同,它採用了分布式版本庫的作法,不需要服務器端軟件,就可以運作版本控制,使得源代碼的發布和交流極其方便。git的速度很快,這對於諸如Linux內核這樣的大項目來說自然很重要。git最為出色的是它的合併追蹤(merge tracing)能力。

git簡明用法

編輯
主頁面:git/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。

指向當前被檢出的代碼(checked out code),也就是當前所在的工作分支。一般指向refs下的某文件。

也可以進入"detached HEAD"狀態,這時你不在一個本地分支上,而是HEAD直接指向一個提交(commit)而不是一個分支。

config

編輯

當前git倉庫的配置文檔,包含如果在本地倉庫管理與存儲數據,已知的遠程倉庫,本地用戶信息,其他配置數據。

可用文本編輯器來編譯此文檔,或者用Git命令config。

description

編輯

供倉庫瀏覽器工具使用,包含了當前項目(project)的描述。在非共享倉庫中通常不改變。

是緩衝(staging)區域。包含了緊湊形式的已經被staged的文件改變信息供下一次commit使用。

info/exclude

編輯

用戶的個人專用文件,針對倉庫的個人副本。

info/refs

編輯

如果此文件存在,倉庫的每個遠程或本地的分支,以及tags,除了在refs/headsrefs/tags有對應的單個文件外,還在此文件中有對應的一行。適用於大型倉庫。

ORIG_HEAD

編輯

改變當前分支的commit歷史的操作在本文件中保存前一次HEAD的值,以允許從錯誤中恢復。

包含其它文件的目錄

編輯

branches

編輯

未見使用

存儲鉤子的文件夾。包含了git倉庫特定事件發生時要運行的腳本。Git給出的腳本,使用擴展名.sample

存儲日誌(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

如果需要Git命令svn提交到一個Subversion服務器.

對象

編輯
 
Git中的數據流與存儲級別

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的操作

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 statusgit 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客戶端

編輯

參考文獻

編輯

外部連結

編輯