Git-基本概念

Git Object

  • git object,git 對象,用於存放信息,而且具備必定的結構.linux

  • 每個 git object 都被 40 位的 SHA1 值惟一索引.便可以經過 40 位 SHA1 值來訪問對應的 git object.git

不一樣類型的 git object

  • commit object,用於保存一個提交相關的信息,如提交者,提交時間,提交的說明...,commit object 的結構如:shell

$ git cat-file -p master   # 顯示 master 引用的提交對象的內容.
tree b9335367560fcbb14669227c427d3020cb10362c  # 該提交對象對應的 tree object.
parent 11176be04831f5cd8c8947b4b0eaa182595ad069 # 該 commit object 的父提交對象
author WangXiaoWei <1258941862@qq.com> 1401371236 +0800 # 提交做者
committer WangXiaoWei <1258941862@qq.com> 1401428713 +0800 # 提交者

新增 protect 子命令 # 提交的註釋信息.

  • tag object,標籤對象,保存着標籤相關信息,結構如:函數

$ git cat-file -t afa17d1
tag         # afa17d1 指向着一個 tag object.
$ git cat-file -p afa17d1
object 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39 # 該 tag object 引用的 git object 的 SHA1 值.
type commit     # 用於代表上述 object 的類型,是一個 commit object.
tag v3.8-rc7    # 該 tag object 的名稱. 
tagger Linus Torvalds <torvalds@linux-foundation.org> 1360358456 +1100 
# 建立該 tag object 的做者以及時間.

Linux 3.8-rc7   # 該 tag object 的註釋.

  • blob object,文件對象,保存着一個文件的完整內容.如:測試

$ git cat-file -t  6f109854c5d4
blob  # 代表 6f109854c5d4 指向着一個 blob object
$ git cat-file -p  6f109854c5d4  # 顯示 blob object 的內容,就是文件內容.
/**
 * @file .
 * Created on: 2014年5月28日 下午3:20:44 Author: WangXiaoWei
 * 包含了 main.cc 函數中可能會使用到的函數原型.
 */

#ifndef MMAP_MAIN_H_
#define MMAP_MAIN_H_

int parse_cmdline(char *cmdline,char **argv,int argv_len);
int get_show_args(int argc,char **argv,int *off,int *len);
int get_unmap_args(int argc,char **argv,int *off,int *len);
int get_modify_args(int argc,char **argv,int *off,char **str);
int get_protect_args(int argc,char **argv,int *off,int *len,int *prot);
int str2int(const char *str,int *output);
char* prot2str(int prot,char *buf);

#endif /* MMAP_MAIN_H_ */

  • tree object,目錄樹信息,保存着在該目錄下子目錄,與文件的信息.其結構以下:spa

    • 對於子目錄,則存放着子目錄名,子目錄的狀態信息,子目錄對應的 tree object 的 SHA1 值.3d

    • 對於文件,則存放着文件名,文件的狀態信息(如: 文件的最後一次修改時間...),文件對應的 blob object 的 SHA1 值指針

$ git cat-file -t 4c58c57
tree # 代表 4c58c57 指向着一個 tree object.
$ git cat-file -p 4c58c57 # 該 tree object 的內容
100644 blob 42fa0d5626a9560d74d16b2df5250b300543b67e    .gitignore  # 文件
100644 blob c596b74b29d532246b3646086c77381076ad3c15    MAINTAINERS # 文件
100644 blob 8a8440a3578e1d3b2fde55625fbc506a5d2979e4    Makefile    # 文件 
100644 blob a24ec89ba4420ad38e8848422ca5f69baa5ffe1c    README      # 文件
040000 tree f1ef1ece9e8b963629398f632f041a8e94ac536d    arch        # 子目錄
040000 tree 0e2802a3add8c60f0d2f57b6662cdd2707a613d3    block       # 子目錄
040000 tree 62f2007ef4f418c65b33dec22f767ae7fd5ee7e2    crypto      # 子目錄

訪問 git object

  • 最基本,最底層的訪問方式: 經過 40 位 SHA1 值來訪問 git object.code

# 經過 40 位 SHA1 值來訪問其對應的 git object
$ git cat-file -t 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39   # 指向的 git object 的類型.
commit
$ git cat-file -s 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39   # 指向的 git object 的尺寸.
254
$ git cat-file -p 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39   # 指向的 git object 的內容. 
tree 8d490c389d08035d6c1a926d9b89b3b07f0edf7d
parent 39923134885759405e64cb9491a273a2bcd356ed
author Linus Torvalds <torvalds@linux-foundation.org> 1360358439 +1100
committer Linus Torvalds <torvalds@linux-foundation.org> 1360358439 +1100

Linux 3.8-rc7

  •  採用部分的 SHA1 值,沒必要將 40 位的哈希值寫全.即只採用開頭 n 位的哈希值(至少 4 位),如:對象

$ git cat-file -p 836dc9     # 使用開頭 6 位 SHA1 值.  
tree 8d490c389d08035d6c1a926d9b89b3b07f0edf7d
parent 39923134885759405e64cb9491a273a2bcd356ed
author Linus Torvalds <torvalds@linux-foundation.org> 1360358439 +1100
committer Linus Torvalds <torvalds@linux-foundation.org> 1360358439 +1100

Linux 3.8-rc7

對於 commit object ,能夠:

  • 使用 ^ 訪問該 commit object 的父提交.

  • 使用 ~n 訪問該 commit object 的祖先提交,如:

# master~2 等同於 master^^
$ git rev-parse master^^
68cb363a4ddc335fddf6e2ccb03e4a907ba7afbf
$ git rev-parse master~2
68cb363a4ddc335fddf6e2ccb03e4a907ba7afbf

  • 當一個 commit object 具備多個父提交時,使用 ^n 訪問該 commit object 的第 n 個父提交.如:

$ git cat-file -p master # 使用 master 來訪問其引用的 commit object.
tree 4c58c5747529b74502352b185515af43e26c0666
parent 77d92784b46549e00f7b99794cd566045ded62ba 
parent cf01f4eef9fe367ec0d85b38dd7214e29e376cdb
...
$ git rev-parse master^1 # 第 1 個父提交
77d92784b46549e00f7b99794cd566045ded62ba
$ git rev-parse master^2 # 第 2 個父提交
cf01f4eef9fe367ec0d85b38dd7214e29e376cdb

  • 使用 ^{tree} 來訪問該 commit object 對應的 tree object.

$ git cat-file -p master
tree b9335367560fcbb14669227c427d3020cb10362c
parent 11176be04831f5cd8c8947b4b0eaa182595ad069
author WangXiaoWei <1258941862@qq.com> 1401371236 +0800
committer WangXiaoWei <1258941862@qq.com> 1401428713 +0800

新增 protect 子命令
$ git rev-parse master^{tree} 
b9335367560fcbb14669227c427d3020cb10362c

  • 使用 :path 來訪問路徑爲 path 的 blob object/tree object,此時 path 爲相對路徑,相對於工做區的路徑.

# lib 爲相對路徑,其完整路徑爲:~/CCProject/linux/lib
~/CCProject/linux$ git cat-file -t master:lib 
tree
# 其完整路徑爲: ~/CCProject/linux/crypto/cryptd.c
~/CCProject/linux$ git cat-file -t master:crypto/cryptd.c 
blob

對於 tag object,能夠:

  • 使用 ^{} 來訪問標籤 tag 對應的 commit objec,如:

$ git cat-file -p v3.9
object c1be5a5b1b355d40e6cf79cc979eb66dafa24ad1
type commit
tag v3.9
tagger Linus Torvalds <torvalds@linux-foundation.org> 1367195769 -0700

Linux 3.9
$ git rev-parse v3.9^{} # v3.9 對應的 commit object.
c1be5a5b1b355d40e6cf79cc979eb66dafa24ad1

對於 tree object,能夠:

  • 使用 :path 來訪問 tree object 中 path 對應的 blob object/tree object.此時 path 爲相對路徑,至關於 tree object 的路徑.

~/CCProject/linux$ git cat-file -p master^{tree}
040000 tree f1ef1ece9e8b963629398f632f041a8e94ac536d    arch
...
~/CCProject/linux$ ls arch/
alpha  arm    avr32     c6x   frv      ia64     m32r  metag       mips     openrisc  powerpc  score  sparc  um         x86
arc    arm64  blackfin  cris  hexagon  Kconfig  m68k  microblaze  mn10300  parisc    s390     sh     tile   unicore32  xtensa
#frv 是一個相對路徑,相對於 f1ef1ece,其對應的完整路徑爲: ~/CCProject/linux/arch/frv.
~/CCProject/linux$ git cat-file -t f1ef1ece:frv         
tree
~/CCProject/linux$ git cat-file -t f1ef1ece:Kconfig
blob

引用

  • 引用,就是一個文件,文件內容爲它引用的 git object 的 SHA1 值.

# master 是一個引用,其對應的文件: .git/refs/heads/master 
$ cat .git/refs/heads/master 
48549924cecf749cbfbf697f6ee34f06c6db26a1

  • 能夠經過引用的全名來訪問引用,也能夠在不引發歧義下僅使用引用名,如:

$ git rev-parse refs/heads/master # master 引用的全名
48549924cecf749cbfbf697f6ee34f06c6db26a1
$ git rev-parse master            # 不引發歧義
48549924cecf749cbfbf697f6ee34f06c6db26a1
$ git tag -m"Test" master         # 建立一個名爲 master 的標籤
$ git rev-parse refs/tags/master  
85176002003cd5f11c349c61c9122e40c64d6578
$ git rev-parse master # 引發歧義,由於 master 既能夠是 refs/heads/master,也能夠是 refs/tags/master
warning: refname 'master' is ambiguous.
85176002003cd5f11c349c61c9122e40c64d6578

常見引用

  • .git/refs/ 引用空間,該目錄下全部文件都是引用.

    • heads/ 該目錄下全部文件都是對 commit object 的引用,又被稱爲分支.

    • tags/ 該目錄下全部文件都是對 commit object/tag object 的引用,又被稱爲標籤.

    • stash 該文件是對進度列表的引用(描述的不許確).

    • remotes/ 該目錄下存放着對遠程版本庫上分支的引用.

      • 遠程版本庫1 該目錄下存放着引用文件,都是對遠程版本庫1的分支的引用.

      • 遠程版本庫2 該目錄下存放着引用文件,都是對遠程版本庫2的分支的引用.

      • ...

.git/refs/remotes/origin:
總用量 24
-rw-r--r-- 1 root root 32  5月  2 23:58 HEAD
-rw-r--r-- 1 root root 41  5月 30 18:41 maint   # 對遠程版本庫 maint 分支的引用
-rw-r--r-- 1 root root 41  5月 30 18:41 master
-rw-r--r-- 1 root root 41  5月 30 18:41 next
-rw-r--r-- 1 root root 41  5月 30 18:41 pu
-rw-r--r-- 1 root root 41  5月 30 18:41 todo

  • .git/HEAD 一個引用文件,若當前處於分離頭指針的狀態,則 HEAD 文件中記錄着當前最後一次提交對應的提交 ID.不然指向着當前所處的分支.

$ cat .git/HEAD 
ref: refs/heads/master     # 代表當前處於 master 分支.
$ git checkout origin/next # 此時會進入分離頭指針狀態.
$ cat .git/HEAD 
5318336450357c9ecf6ffed2ca846e4c22dbfb7c # 代表當前處在分離頭指針狀態

分離頭指針

  • 進入分離頭指針狀態,就像處在一個無名分支上,此時能夠進行在常規分支下進行的操做,如:檢查,測試,提交.

    • 當進入分離頭指針狀態時,git 會進行提示,而且此時從 git status 的輸出中也能夠看的出來.

  • 當使用 git checkout <branch> 切換到一個其餘分支上時,在無名分支下所作的修改與提交會被丟棄.

  • 使用 git checkout -b <branch> 建立一個新的分支來追蹤當前提交,如:

$ git checkout 49a5d7
Note: checking out '49a5d7'.
你正在處於分離頭指針的狀態.
若是你要是想建立一個新的分支來追蹤提交,你可使用:
  git checkout -b new_branch_name
HEAD 目前位於 49a5d7d... 新增 protect 子命令

$ git status
HEAD detached at 49a5d7d # 代表此時處於分離頭指針的狀態
nothing to commit, working directory clean

$ git checkout -b Test_Branch # 建立一個新的分支來追蹤提交.
切換到一個新分支 'Test_Branch'

$ git branch
* Test_Branch
  master

文件忽略

  • 文件忽略,對於 git 而言,忽略的文件就像從不存在同樣!如:

$ git status
 位於分支 master
 Untracked files:
       .cproject
       .project
       Debug/  
       checksum.cc
       log
       mmap
       test.cc
       test.h
       write.cc
nothing added to commit but untracked files present (use "git add" to track)

$ kate .gitignore 
# 編輯 .gitignore 文件,輸入如下內容:
# Debug/
# .*

$ git status
 位於分支 master
 Untracked files:
       # 能夠看出設置爲忽略的文件,沒有再出現
       checksum.cc
       log
       mmap
       test.cc
       test.h
       write.cc
nothing added to commit but untracked files present (use "git add" to track)
# 被忽略的文件也不會被 add 到.
$ git add -Av  
add 'checksum.cc'
add 'log'
add 'mmap'
add 'test.cc'
add 'test.h'
add 'write.cc'

  • 當文件已經添加到暫存區後,忽略將會無效.

實現文件忽略:

  • 經過編寫 .gitignore 文件.

    • 經過將 .gitignore 添加到版本庫中,可讓文件忽略在他人的工做區也有效,即由於 .gitignore 位於版本庫中,因此當他們 git clone 版本庫時,也會將 .gitignore 下載下來,因此文件忽略生效.

    • 也能夠在 .gitignore 文件中忽略自身,如上.這樣 .gitignore 就不會加入到版本庫中,就成爲了本地獨享式忽略文件.

    • .gitignore 文件只對當前目錄及其子目錄有效.

$ git status
位於分支 master
Untracked files:
      World
      a/World
nothing added to commit but untracked files present (use "git add" to track)

$ kate .gitignore
# 輸入:
# .*
# World

$ git status
位於分支 master
    # 文件 World a/World 均被忽略
nothing to commit, working directory clean

$ mv .gitignore a/
$ git status
位於分支 master
Untracked files:
    # 僅 a/World 被忽略,即 .gitignore 只對當前目錄及其子目錄有效
      World  
nothing added to commit but untracked files present (use "git add" to track)

  • 經過編寫  .git/info/exclude 文件.

    • 只能是獨享式忽略,而且僅侷限在一個版本庫中.

~/Gi$ cat .git/info/exclude 
.*
World

~$ git clone Gi/ Gi1
正克隆到 'Gi1'...
完成。
Checking connectivity... done

# 並無將 Gi 版本庫中的 .git/info/exclude 內容下載下來 
Gi1$ cat .git/info/exclude  
git ls-files --others --exclude-from=.git/info/exclude
...

  • 經過設置 core.excludesfile 屬性.

    • 只能是獨享式忽略,不過能夠經過 git config --system core.excludesfile 來做用於本地全部的版本庫中.

.gitignore 忽略文件的編寫

  • 以'#'開頭的行爲註釋行.

  • 每行放置一個模式,知足模式的文件/目錄將被忽略.可用的通配符:

    • * 表示任意多的任意字符; ? 表示任意一個字符;

  • 若是模式最後面是'/',則代表知足模式的目錄,而不忽略知足模式的文件.

  • 若是模式的最前面是'!',則表示不忽略匹配該模式的文件/目錄.

  • 若是模式的最前面是'/',則代表僅忽略當前目錄下知足模式的文件/目錄,而不忽略子目錄下知足模式文件/目錄.

相關文章
相關標籤/搜索