跳至內容

git

本頁使用了標題或全文手工轉換
維基教科書,自由的教學讀本
維基百科中的相關條目:

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)。已提交表示該檔案已經被安全地儲存; 保存=>zh-mo:儲存在本地數據庫 中了;已修改表示修改了某個檔案,但還沒有提交儲存; 保存=>zh-mo:儲存;已暫存表示把已修改的檔案放在下次提交時要儲存; 保存=>zh-mo:儲存的清單中。

內部目錄結構

[編輯]

理解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物件; 對象=>zh-mo:物件

根目錄下的專用檔案

[編輯]

COMMIT_EDITMSG

[編輯]

上一次提交的資訊儲存; 保存=>zh-mo:儲存在這個檔案中。可用文字編輯器處理。

FETCH_HEAD

[編輯]

最後一次的Git命令fectch的操作資訊儲存; 保存=>zh-mo:儲存在這裏。可用於下次Git命令merge。

[編輯]

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

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

config

[編輯]

當前git倉庫的組態文件; 文檔=>zh-mo:文件,包含如果在本地倉庫管理與儲存數據,已知的遠端倉庫,本地用戶資訊,其他組態數據。

可用文字編輯器來編譯此文件; 文档=>zh-mo:文件,或者用Git命令config。

description

[編輯]

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

index

[編輯]

是緩衝(staging)區域。包含了緊湊形式的已經被staged的檔案改變資訊供下一次commit使用。

info/exclude

[編輯]

用戶的個人專用檔案,針對倉庫的個人副本。

info/refs

[編輯]

如果此檔案存在,倉庫的每個遠端或原生的分支,以及tags,除了在refs/headsrefs/tags有對應的單個檔案外,還在此檔案中有對應的一行。適用於大型倉庫。

ORIG_HEAD

[編輯]

改變當前分支的commit歷史的操作在本檔案中儲存; 保存=>zh-mo:儲存前一次HEAD的值,以允許從錯誤中恢復。

包含其它檔案的目錄

[編輯]

branches

[編輯]

未見使用

hooks

[編輯]

儲存; 存儲=>zh-mo:儲存鈎子的檔案夾。包含了git倉庫特定事件發生時要執行的指令碼。Git給出的指令碼,使用副檔名.sample

logs

[編輯]

儲存; 存儲=>zh-mo:儲存日誌(reflogs)的檔案夾。reflog用於記錄那些不儲存; 保存=>zh-mo:儲存在提交歷史中的事情,如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中的數據流與儲存級別

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值表示。

獲取和建立; 創建=>zh-mo:建立項目

[編輯]
  • 命令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

除錯; 調試=>zh-mo:除錯

[編輯]
  • bisect
  • blame
  • grep

電子郵件

[編輯]
  • am
  • apply
  • format-patch
  • send-email
  • request-pull

外部系統

[編輯]
  • svn
  • fast-import

管理

[編輯]
  • clean
  • gc
  • fsck
  • reflog
  • filter-branch
  • instaweb
  • archive
  • bundle

伺服器; 服務器=>zh-mo:伺服器管理

[編輯]
  • 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客戶端

[編輯]

參考文獻

[編輯]

外部連結

[編輯]