现在的位置: 首页 > 综合 > 正文

git深度历险总结

2013年02月04日 ⁄ 综合 ⁄ 共 6145字 ⁄ 字号 评论关闭

内容来自http://www.infoq.com/cn/git-adventures%3bjsessionid=0d9801a1309fef34f6b960944e69b787/

 

一. 索引:
git索引:就是暂存区。有了它,可以把许多的内容修改一起提交。创建一个commit(对象),那么只针对暂存区,与工作区无关。这是我对git第一个很重要的概念的理解。
暂存区(staging area)一般存放在“git目录“下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)
暂存区有二个名称:stage or index
索引是一个二进制格式的文件,里面存放了与当前暂存内容相关的信息,包括暂存的文件名、文件内容的SHA1哈希串值和文件访问权限,整个索引文件的内容以暂存的文件名进行排序保存的。
$git ls-files --stage
100644 2d832d9044c698081e59c322d5a2a459da546469 0   readme.txt
同时会发现“git目录“里多出了”.git/objects/2d/832d9044c698081e59c322d5a2a459da546469”这 么一个文件,再执行“git cat-file -p 2d832d” 的话,就可以看到里面的内容正是“hello,world"。Git在把一个文件添加暂存区时,不但把它在索引文件(.git/index)里挂了号,而 且把它的内容先保存到了“git目录“里面去了。

二.git目录 (  .git | git directory | git仓库 )
Git把所有的历史提交信息全部存储在“Git目录”里,它就是一个Git项目的仓库;你对本地的源代码进行编辑修改后创建的提交也都会先保存在这里面,然后再推送到远端的服务器。
1) 当我们我把项目目录和“Git目录”一起拷到其它电脑里,它能马上正常的工作(所有的提交信息全都保存在Git目录 里);
2) 甚至可以只把“Git目录”拷走也行,但是要再签出(checkout)一次。
注:交接需要工作区+git目录,这样才完整。为了调试,git可以通过命令指定某个路径的git仓库。
git仓库除了config之外的主要内容:
COMMIT_EDITMSG # 保存着上一次提交时的注释信息
HEAD # 项目当前在哪个分支的信息,HEAD可以是多个分支的提交。但是某个时刻,HEAD只能对应某个分支的最近提交。
index # 索引文件,git add 后把要添加的项暂存到这里
info/ # 里面有一个exclude文件,指定本项目要忽略的文件 #,看一下这里
logs/ # 各个refs的历史信息
objects/ # 这个目录非常重要,里面存储都是Git的数据对象 包括:提交(commits), 树对象(trees),二进制对象#(blobs),标签对象(tags)。
refs/ # 标识着你的每个分支指向哪个提交(commit)。

注:该commit也就是object所包含的数据对象commits中的一个。
比如
$cat refs/heads/master
12c875f17c2ed8c37d31b40fb328138a9027f337   #该串就是commit对象对应的名字-SHA1字符串

三. SHA1较内容比较一大进步
SHA1是git设计中简化比较的重要思想: 只要对象里面 的内容不同,那么我们就可以认为对象的名字不会相同,反之也成立。
注1:Git是根据对象的内容生成“SHA1哈希串值”作为名字,只要内容一样,那么的对应的名字肯定是一样的,为什么这里面会不一样呢? Git确实根据内容来生成名字的,而且同名(SHA1哈希串值)肯定会有 相同内容,但是提交对象(commit)和其它对象有点不一样,它里面会多一个时间戳(timestamp),所以在不同的时间生成的提交对象,即使内容完全一样其名字也不会相同。
比如机器A的readme.txt的内容是"hello world",commit名是“12c875f17c2ed8c37d31b40fb328138a9027f337”, 机器B的readme.txt的内容也一要,生成的commit名是:4248e5305e394ad086996ed31d58515395650bd9

注2:
使用时一般不用把这个40个字符输全,只要把前面的5~8个字符输完就可以(前提是 和其它的对象名不冲突)
比如查看提交的内容
$ git cat-file  -p 4248e5
tree e7a75e980c7adc0d5ab1c49ecff082b518bb6cf8
author gaoyibo <ygao@tripadvisor.com> 1324813676 +0800
committer gaoyibo <ygao@tripadvisor.com> 1324813676 +0800

除了具体的commit名,还可以使用HEAD来表示当前版本,比如下面的名字用来查看当前版本所包含的BLOB对象
git cat-file -p HEAD | head -n 1 | cut -b6-15 | xargs git cat-file -p

提交“4248e5” 是引用一个名为“e7a75e”的树对象(tree)。一个树对象(tree)可以引用一个或多个二进制对象(blob), 每个二进制对象都对应一个文件。 更进一步, 树对象也可以引用其他的树对象,从而构成一个目录层次结构。

接着查看引用的树对象
$ git cat-file  -p e7a75e
100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    readme.txt

发现上面的树对象中只有刚才提交的一个文件readme.txt。
接着查看二进制的blob对象。
$ git cat-file  -p 3b18e5
hello world
上面的内容又象是回到了原点,没错,就是最初提交的内容。

提交对象、树对象和二进制对象是怎么在”Git目录“中存储的:所有的对象都使用SHA签名串值作为索引存储在”.git/objects”目录之下;SHA串的前两个字符作为目录名,后面的38个字符作为文件名。

$ find .git/objects
.git/objects
.git/objects/2b
.git/objects/2b/b9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13
.git/objects/2d
.git/objects/2d/832d9044c698081e59c322d5a2a459da546469
.git/objects/58
.git/objects/58/b53cfe12a9625865159b6fcf2738b2f6774844
.git/objects/info
.git/objects/pack

当前master分支的的类型是“ 提交“
$cat refs/heads/master | xargs git cat-file -t
commit

“master”文件里面存有主分支(master)最新提交的“对象名”;我们根据这个“对象名”就可以可找到对应的树对象(tree)和二进制对象(blob),简而言之就是我能够按“名”索引找到这个分支里所有的对象。

下面命令主是查看主分支最新提交的内容:
$cat refs/heads/master | xargs git cat-file -p
tree 0bd1dc15d804534cf25c5cb53260fd03c84fd4b9
author liuhui998 <liuhui998@nospam.com> 1300697913 +0800
committer liuhui998 <liuhui998@nospam.com> 1300697913 +0800     project init

查看有哪些提交: 注意,只能看到提交对象的信息。对于merge等操作的信息无法看到。
$ git log
commit 58b53cfe12a9625865159b6fcf2738b2f6774844
Author: liuhui998 <liuhui998@nospam.com>
Date: Sat Feb 19 18:10:08 2011 +0800
project init
大家可以看到目前只有一个提交(commit)对象,而它的名字就 是:”58b53cfe12a9625865159b6fcf2738b2f6774844”。

示例:
1.git add readme.txt
2.修改本地文件
3.git status触发SHA1根据内容计算得到结果:

# On branch master
#
# Initial commit
#
# Changes to be committed: 加到暂存器但未提交。
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   readme.txt
#
# Changed but not updated: 修改但没有加到暂存区。
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   readme.txt
#

此时想放弃工作区中对readme.txt的修改。使用git checkout filename
4.git checkout -- readme.txt

什么时候触发SHA1计算:
git status

四。git clone与工作目录。

$mkdir temp  #会将*.git的*生成为temp下的目录做为工作目录
$git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
执行完上面的clone linux-2.6代码的的操作后,Git会从“Git目录”里把最新的代码签出(checkout)到“linux-2.6”这个目录里面。我们一般 把本地的“linux-2.6”这个目录叫做”工作目录“(work directory),它里面保存着你从其它地方clone(or checkout)过来的代码。当你在项目的不同分支间切换时,“工作目录”中的文件可能会被替换或者删除;“工作目录”只是保存着当前的工作,你可以修 改里面文件的内容直到下次提交为止。

git clone ssh_path dir  #dir表示不使用远程的文件夹名,而使用指定的文件夹名

完整的获取git仓库并checkout的操作:
rm -rf  daodao-site
sudo git clone   root@host1:/root/devbranches/snsconnect/snsconnect-daodaosite daodao-site
sudo chmod   755  ./daodao-site/
groups  #查看用户所在组
sudo chown -R   zhonghua:wheel  ./daodao-site

五。关于git diff branch

master readme.txt:
hello world

test readme.txt:
hello world
In test branch

如果分支切到了test上,执行下面的命令:
$ git diff master
diff --git a/readme.txt b/readme.txt
index 3b18e51..1d48c91 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
 hello world
+In test branch

注:上面表示当前分支test比比较分支master多了+的部分。

如果分支切到了master上,执行下面的命令:
$ git diff test
diff --git a/readme.txt b/readme.txt
index 1d48c91..3b18e51 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1 @@
 hello world
-In test branch

注:上面表示current branch :master比compare branch:test少了-的部分。

注:不论current branch在master还是test,执行git diff比较的是工作区与index。所以,没有比较结果。

六。git log

git log --graph查看commit,会显示merge信息。

通常的提交:
* commit 91fcdc112fdf92349871c4bcf22e8d6aaf3af9d4
| Author: TADevStand <root@tadev31.daodao.com>
| Date:   Fri Dec 23 15:54:53 2011 +0800
|
|     add daodao support when stub member post photo

看到merge之后的提交:
*   commit 893b71aa1e885cfa2440fa5dc1eb641693464ac1
|\  Merge: 005ab5c 8e9811b
| | Author: TADevStand <root@tadev31.daodao.com>
| | Date:   Fri Dec 23 14:31:44 2011 +0800
| |
| |     Merge branch 'sns' of app220:/root/devbranches/snsconnect/snsconnect-trsrc into sns

git log path

zhonghua@pts/ttys000 $ git log object/SNSObject.java
commit 86e30f3ca85efc7b3d37c0764044c94a9b56f379
Author: gaoyibo <ygao@tripadvisor.com>
Date:   Thu Dec 8 18:39:51 2011 +0800

    add more abstract class : SNSObject

commit 8c5e4b34ec49c03d29497724e2f7a4cfcba2327f
Author: gaoyibo <ygao@tripadvisor.com>
Date:   Fri Dec 9 16:57:14 2011 +0800

    add weibo.jar

commit 85f0281240d8e20810c733ef8cacba4549717b52
Author: gaoyibo <ygao@tripadvisor.com>
Date:   Thu Dec 8 18:39:51 2011 +0800

    add more abstract class : SNSObject

查看某个分支的提交情况。
git log SNS
commit d09066ac7c6ad6e5eb9e753663c6e59e74366c37
Author: TADevStand <root@tadev31.daodao.com>
Date:   Mon Dec 26 15:01:31 2011 +0800

    remove main method

 

 

【上篇】
【下篇】

抱歉!评论已关闭.