Git基本概念
来源:互联网 发布:springmvc国际化对js 编辑:程序博客网 时间:2024/06/07 21:14
$ sudo apt-get install git-core 学习git之前,先安装好git分布式版本控制软件
并且准备好“gitk”,这一可视化的工具
GIT对象模型
SHA
所有用来表示项目历史信息的文件,是通过一个40个字符的(40-digit)“对象名”来索引的,对象名看起来像这样:
6ff87c4664981e4397625791c8ea3bbb5f2279a3
你会在Git里到处看到这种“40个字符”字符串。每一个“对象名”都是对“对象”内容做SHA1哈希计算得来的,(SHA1是一种密码学的哈希算法)。这样就意味着两个不同内容的对象不可能有相同的“对象名”。
这样做会有几个好处:
- Git只要比较对象名,就可以很快的判断两个对象是否相同。
- 因为在每个仓库(repository)的“对象名”的计算方法都完全一样,如果同样的内容存在两个不同的仓库中,就会存在相同的“对象名”下。
- Git还可以通过检查对象内容的SHA1的哈希值和“对象名”是否相同,来判断对象内容是否正确。
对象
每个对象(object) 包括三个部分:类型,大小和内容。大小就是指内容的大小,内容取决于对象的类型,有四种类型的对象:"blob"、"tree"、 "commit" 和"tag"。
- “blob”用来存储文件数据,通常是一个文件。
- “tree”有点像一个目录,它管理一些“tree”或是 “blob”(就像文件和子目录)
- 一个“commit”只指向一个"tree",它用来标记项目某一个特定时间点的状态。它包括一些关于时间点的元数据,如时间戳、最近一次提交的作者、指向上次提交(commits)的指针等等。
- 一个“tag”是来标记某一个提交(commit) 的方法。
几乎所有的Git功能都是使用这四个简单的对象类型来完成的。它就像是在你本机的文件系统之上构建一个小的文件系统。
安装与初始化
Git 配置
使用Git的第一件事就是设置你的名字和email,这些就是你在提交commit时的签名。
$ git config --global user.name "Scott Chacon"$ git config --global user.email "schacon@gmail.com"
执行了上面的命令后,会在你的主目录(home directory)建立一个叫 ~/.gitconfig 的文件.内容一般像下面这样:
[user] name = Scott Chacon email = schacon@gmail.com
译者注:这样的设置是全局设置,会影响此用户建立的每个项目.
如果你想使项目里的某个值与前面的全局设置有区别(例如把私人邮箱地址改为工作邮箱);你可以在项目中使用git config 命令不带 --global 选项来设置. 这会在你项目目录下的.git/config 文件增加一节[user]内容(如上所示).
日期标识符
The Ref Log that git keeps will allow you to do some relative stuff locally,such as:
Git的引用日志(Ref Log)可以让你做一些‘相对'查询操作:
master@{yesterday}master@{1 month ago}
上面的第一条命令是:'master分支的昨天状态(head)的缩写‘. 注意: 即使在两个有相同master分支指向的仓库上执行这条命令, 但是如果这个两个仓库在不同机器上, 那么执行结果也很可能会不一样.
译者注:因为两个不同机器上的仓库的历史一般很难相同.
顺序标识符
这种格式用来表达某点前面的第N个提交(ref).
master@{5}
上面的表达式代表着master前面的第5个提交(ref).
多个父对象
这能告诉你某个提交的第N个直接父提交(parent). 这种格式在合并提交(merge commits)时特别有用, 这样就可以使提交对象(commit object)有多于一个直接父对象(direct parent).
译者注:假设master是由a和b两个分支合并的,那么 master^1
是指分支a, master^2
就是指分支b.
master^2
波浪号
波浪号用来标识一个提交对象(commit object)的第N级嫡(祖)父对象(Nth grandparent). 例如:
master~2
就代表master所指向的提交对象的第一个父对象的第一个父对象(译者:你可以理解成是嫡系爷爷:)). 它和下面的这个表达式是等价的:
master^^
你也可以把这些‘标识符'(spec)叠加起来, 下面这个3个表达式都是指向同一个提交(commit):
master^^^^^^master~3^~2master~6
树对象指针
如果大家对第一章Git对象模型还有印象的话, 就记得提交对象(commit object)是指向一个树对象(tree object)的. 假如你要得到一个提交对象(commit object)指向的树对象(tree object)的sha串名, 你就可以在‘树名'的后面加上'{tree}'来得到它:
master^{tree}
二进制标识符
如果你要某个二次制对象(blob)的sha串名,你可以在'树名'(treeish)后添加二次制对象(blob)对应的文件路径来得到它.
master:/path/to/file
区间
最后, 你可以用".."来指两个提交(commit)之间的区间. 下面的命令会给出你在"7b593b5" 和"51bea1"之间除了"7b593b5外"的所有提交(commit)(注意:51bea1是最近的提交).
7b593b5..51bea1
这会包括所有 从 7b593b开始的提交(commit).译者注: 相当于 7b593b..HEAD
7b593b..
使用Git Grep进行搜索
用git grep 命令查找Git库里面的某段文字是很方便的. 当然, 你也可以用unix下的'grep'命令进行搜索, 但是'git grep'命令能让你不用签出(checkout)历史文件, 就能查找它们.
例如, 你要看 git.git 这个仓库里每个使用'xmmap'函数的地方, 你可以运行下面的命令:
$ git grep xmmapconfig.c: contents = xmmap(NULL, contents_sz, PROT_READ,diff.c: s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);git-compat-util.h:extern void *xmmap(void *start, size_t length, int prot, int flaread-cache.c: mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,refs.c: log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);sha1_file.c: map = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, fd, 0);sha1_file.c: idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);sha1_file.c: win->base = xmmap(NULL, win->len,sha1_file.c: map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fsha1_file.c: buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);wrapper.c:void *xmmap(void *start, size_t length,
如果你要显示行号, 你可以添加'-n'选项:
$>git grep -n xmmapconfig.c:1016: contents = xmmap(NULL, contents_sz, PROT_READ,diff.c:1833: s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd,git-compat-util.h:291:extern void *xmmap(void *start, size_t length, int prot, intread-cache.c:1178: mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_refs.c:1345: log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);sha1_file.c:377: map = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, fd, 0);sha1_file.c:479: idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fdsha1_file.c:780: win->base = xmmap(NULL, win->len,sha1_file.c:1076: map = xmmap(NULL, *size, PROT_READ, MAP_PRsha1_file.c:2393: buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fdwrapper.c:89:void *xmmap(void *start, size_t length,
如果我们想只显示文件名, 我们可以使用'--name-onley'选项:
$>git grep --name-only xmmapconfig.cdiff.cgit-compat-util.hread-cache.crefs.csha1_file.cwrapper.c
我们可以用'-c'选项,可以查看每个文件里有多少行匹配内容(line matches):
$>git grep -c xmmapconfig.c:1diff.c:1git-compat-util.h:1read-cache.c:1refs.c:1sha1_file.c:5wrapper.c:1
现在, 如果我们要查找git仓库里某个特定版本里的内容, 我们可以像下面一样在命令行末尾加上标签名(tag reference):
$ git grep xmmap v1.5.0v1.5.0:config.c: contents = xmmap(NULL, st.st_size, PROT_READ,v1.5.0:diff.c: s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd,v1.5.0:git-compat-util.h:static inline void *xmmap(void *start, size_t length,v1.5.0:read-cache.c: cache_mmap = xmmap(NULL, cache_mmap_size, v1.5.0:refs.c: log_mapped = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfdv1.5.0:sha1_file.c: map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, v1.5.0:sha1_file.c: idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fdv1.5.0:sha1_file.c: win->base = xmmap(NULL, win->len,v1.5.0:sha1_file.c: map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, v1.5.0:sha1_file.c: buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd
我可以看到"1.5.0版"和当前版本间一些区别: 在“1.5.0版"中, xmmap没有在wrapper.c中出现.
我们也可以组合一些搜索条件, 下面的命令就是查找我们在仓库的哪个地方定义了'SORT_DIRENT'.
$ git grep -e '#define' --and -e SORT_DIRENTbuiltin-fsck.c:#define SORT_DIRENT 0builtin-fsck.c:#define SORT_DIRENT 1
我不但可以进行“与"(both)条件搜索操作,也可以进行"或"(either)条件搜索操作.
$ git grep --all-match -e '#define' -e SORT_DIRENTbuiltin-fsck.c:#define REACHABLE 0x0001builtin-fsck.c:#define SEEN 0x0002builtin-fsck.c:#define ERROR_OBJECT 01builtin-fsck.c:#define ERROR_REACHABLE 02builtin-fsck.c:#define SORT_DIRENT 0builtin-fsck.c:#define DIRENT_SORT_HINT(de) 0builtin-fsck.c:#define SORT_DIRENT 1builtin-fsck.c:#define DIRENT_SORT_HINT(de) ((de)->d_ino)builtin-fsck.c:#define MAX_SHA1_ENTRIES (1024)builtin-fsck.c: if (SORT_DIRENT)
我们也可以查找出符合一个条件(term)且符合两个条件(terms)之一的文件行. 例如我们要找出名字中含有‘PATH'或是'MAX'的常量定义:
$ git grep -e '#define' --and \( -e PATH -e MAX \) abspath.c:#define MAXDEPTH 5builtin-blame.c:#define MORE_THAN_ONE_PATH (1u<<13)builtin-blame.c:#define MAXSG 16builtin-describe.c:#define MAX_TAGS (FLAG_BITS - 1)builtin-fetch-pack.c:#define MAX_IN_VAIN 256builtin-fsck.c:#define MAX_SHA1_ENTRIES (1024)...
译者注: 就是"与"条件搜索和"或"条件搜索可以组合使用.
Git的撤消操作 - 重置, 签出 和 撤消
Git提供了多种修复你开发过程中的错误的方法. 方法的选择取决于你的情况: 包含有错误的文件是否提交了(commited); 如果你把它已经提交了, 那么你是否把有错误的提交已与其它人共享这也很重要.
修复未提交文件中的错误(重置)
如果你现在的工作目录(work tree)里搞的一团乱麻, 但是你现在还没有把它们提交; 你可以通过下面的命令, 让工作目录回到上次提交时的状态(last committed state):
$ git reset --hard HEAD
这条件命令会把你工作目录中所有未提交的内容清空(当然这不包括未置于版控制下的文件 untracked files). 从另一种角度来说, 这会让"git diff" 和"git diff --cached"命令的显示法都变为空.
如果你只是要恢复一个文件,如"hello.rb", 你就要使用 git checkout
$ git checkout -- hello.rb
这条命令把hello.rb从HEAD中签出并且把它恢复成未修改时的样子.
译者:上面二行和原文有出入,经验证是原文有误,所以我据正确的重写了.
修复已提交文件中的错误
如果你已经做了一个提交(commit),但是你马上后悔了, 这里有两种截然不同的方法去处理这个问题:
- 创建一个新的提交(commit), 在新的提交里撤消老的提交所作的修改. 这种作法在你已经把代码发布的情况下十分正确.
2 你也可以去修改你的老提交(old commit). 但是如果你已经把代码发布了,那么千万别这么做; git不会处理项目的历史会改变的情况,如果一个分支的历史被改变了那以后就不能正常的合并.
创建新提交来修复错误
创建一个新的,撤消(revert)了前期修改的提交(commit)是很容易的; 只要把出错的提交(commit)的名字(reference)做为参数传给命令:git revert就可以了; 下面这条命令就演示了如何撤消最近的一个提交:
$ git revert HEAD
这样就创建了一个撤消了上次提交(HEAD)的新提交, 你就有机会来修改新提交(new commit)里的提交注释信息.
你也可撤消更早期的修改, 下面这条命令就是撤消“上上次”(next-to-last)的提交:
$ git revert HEAD^
在这种情况下,git尝试去撤消老的提交,然后留下完整的老提交前的版本. 如果你最近的修改和要撤消的修改有重叠(overlap),那么就会被要求手工解决冲突(conflicts), 就像解决合并(merge)时出现的冲突一样.
译者注: git revert 其实不会直接创建一个提交(commit), 把撤消后的文件内容放到索引(index)里,你需要再执行git commit命令,它们才会成为真正的提交(commit).
修改提交来修复错误
如果你刚刚做了某个提交(commit), 但是你又想马上修改这个提交; git commit 现在支持一个叫--amend的参数,它能让你修改刚才的这个提交(HEAD commit). 这项机制能让你在代码发布前,添加一些新的文件或是修改你的提交注释(commit message).
如果你在老提交(older commit)里发现一个错误, 但是现在还没有发布到代码服务器上. 你可以使用 git rebase命令的交互模式, "git rebase -i"会提示你在编辑中做相关的修改. 这样其实就是让你在rebase的过程来修改提交.
维护Git
保证良好的性能
在大的仓库中, git靠压缩历史信息来节约磁盘和内存空间.
压缩操作并不是自动进行的, 你需要手动执行 git gc:
$ git gc
压缩操作比较耗时, 你运行git gc命令最好是在你没有其它工作的时候.
保持可靠性
git fsck 运行一些仓库的一致性检查, 如果有任何问题就会报告. 这项操作也有点耗时, 通常报的警告就是“悬空对象"(dangling objects).
$ git fsckdangling commit 7281251ddd2a61e38657c827739c57015671a6b3dangling commit 2706a059f258c6b245f298dc4ff2ccd30ec21a63dangling commit 13472b7c4b80851a1bc551779171dcb03655e9b5dangling blob 218761f9d90712d37a9c5e36f406f92202db07ebdangling commit bf093535a34a4d35731aa2bd90fe6b176302f14fdangling commit 8e4bec7f2ddaa268bef999853c25755452100f8edangling tree d50bb86186bf27b681d25af89d3b5b68382e4085dangling tree b24c2473f1fd3d91352a624795be026d64c8841f...
“悬空对象"(dangling objects)并不是问题, 最坏的情况只是它们多占了一些磁盘空间. 有时候它们是找回丢失的工作的最后一丝希望.
其实这里最重要的一个命令就是:git fsck --lost-found,因为git中把commit删了后,并不是真正的删除,而是变成了悬空对象(dangling commit)。我们只要把把这悬空对象(dangling commit)找出来,用git rebase也好,用git merge也行就能把它们给恢复。
- Git基本概念
- git 【基本概念】
- GIT基本概念
- git基本概念
- git基本概念
- GIT 基本概念
- Git基本概念
- Git基本概念
- git基本概念
- Git基本概念图文详解
- Git的基本概念
- Git 基本概念解释
- Git 基本概念及常用命令
- git#3#基本概念
- GIT - 一些基本概念
- GIT基本概念总结
- 一.Git基本概念
- git基本概念与操作
- Spring--quartz中cronExpression配置说明
- 苹果mac电脑中brew的安装使用及卸载详细教程
- 随机数算法
- Win32控制台应用程序如何更换图标
- Activity的状态保存
- Git基本概念
- [Leetcode]Construct Binary Tree from Inorder and Postorder Traversal
- Mac下使用eclipse问题
- path的使用
- SKIP_BODY,SKIP_PAGE,EVAL_BODY_INCLUDE,EVAL_BODY_AGAIN
- 排序算法之冒泡排序 C++和PHP实现
- make: warning: Clock skew detected. Your build may be incomplete.
- ppt转换成pdf转换器怎么使用
- HDU 2553 N皇后问题 (回溯法 递归·非递归)