您的位置:首页 > 其它

Git-基本概念

2014-05-30 00:00 190 查看

Git Object

git object,git 对象,用于存放信息,并且具有一定的结构.

每一个 git object 都被 40 位的 SHA1 值唯一索引.即可以通过 40 位 SHA1 值来访问对应的 git object.

不同类型的 git object

commit object,用于保存一个提交相关的信息,如提交者,提交时间,提交的说明...,commit object 的结构如:

$ 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,目录树信息,保存着在该目录下子目录,与文件的信息.其结构如下:

对于子目录,则存放着子目录名,子目录的状态信息,子目录对应的 tree object 的 SHA1 值.

对于文件,则存放着文件名,文件的状态信息(如: 文件的最后一次修改时间...),文件对应的 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.

# 通过 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 忽略文件的编写

以'#'开头的行为注释行.

每行放置一个模式,满足模式的文件/目录将被忽略.可用的通配符:

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

如果模式最后面是'/',则表明满足模式的目录,而不忽略满足模式的文件.

如果模式的最前面是'!',则表示不忽略匹配该模式的文件/目录.

如果模式的最前面是'/',则表明仅忽略当前目录下满足模式的文件/目录,而不忽略子目录下满足模式文件/目录.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: