- 浏览: 125149 次
- 性别:
- 来自: 上海
最新评论
-
l67721363:
受益匪浅,谢谢!~
重新认识Session(续)——自己动手做试验 -
shuminghuang:
写得很好,不过我对您的文件监控脚本也很感兴趣,不知道能否分享
做一次git的观众 -
doingjava:
LZ,写的很不错,这种逻辑也很有道理,测试方式很敬佩。
但是有 ...
重新认识Session(续)——自己动手做试验 -
trace:
感谢ls,找到了这么详细的解释!
做一次git的观众 -
yanwuhuan:
首先,我们发现index文件被改变了。但是,经过我仔细比对两次 ...
做一次git的观众
Git这个强大的版本管理系统,工作的时候默默注视着你的代码目录,所有的操作几乎都在.git目录中完成。今天我们来做一次git的观众,以便深入了解git的各个操作。
首先,新建一个目录:git-monitor,进入目录后,用下面的命令初始化一个git仓库:
然后,创建一个工作目录wp1,意思为working_copy_1,进入该目录,运行git init,以创建.git目录。
进入.git目录,会发现下列文件和目录:
这些都是git的演员。我们当观众的,就从监控这些文件开始。但是演员分主角、配角,和跑龙套的,在这些文件中,config是配置文件,内容不会变的;hooks中的文件是一些回调程序的例子,删掉都没关系;description文件只为某些git的web应用提供描述信息。它们都是跑龙套的,剩下的文件和目录有:
在后续的操作中,还有两位要上场,分别是index文件和logs目录,至此,主要演员表为:
要用肉眼盯着它们看,实在不容易,于是我写了个ruby小程序(下载链接在最后),用于监控这些目录,一旦目录和文件有变化,就在控制台上向我们报告。我把这个程序放到.git目录下,并把它跑起来。接下来,好戏就开演了。
回到wp1目录。新建一个文件file1.txt,然后看看监控程序,发现没有任何输出,说明git对刚才的操作没有响应。既然没反应,那我就接着操作,在file1.txt中加一行内容
再看看监控,还是没有反应。看来,只要我们不调用git命令,它就不会有反应。那我就调一个看看:
再看看监控,终于有反应了:
git add这个命令,根据`man git-add`的解释,是把某个文件加入到index。这个index实际上就是工作目录下文件和目录状态的一个快照(stage),每一次git提交所产生的tree对象,就是依据index文件产生的(对index同志的详细采访,可以参考[url=http://progit.org/book/zh/ch9-2.html]这里[/url])。
我们来看看产生的那个object到底是什么,根据git的规则,object的目录名加文件名,和起来是一个40字符的字符串,它是对文件内容进行SHA1 digest之后,用16进制编码得到的结果。此文件的内容是二进制的,要查看它,就要用下面的命令:
其中,-t这个参数是为了显示object类型,-p这个参数,是为了显示object的内容。显然,这个object就是刚才加进去的file1.txt,它是一个blob类型的对象,只存储文件内容和长度。
接下来,我把这次添加的内容提交一下(git commit -m 'commit by wp1, 1st time'),再看看监控,又有输出了,这次的内容还真丰富啊:
首先,我们发现index文件被改变了。但是,经过我仔细比对两次的index文件的二进制字节码后发现,它的内容并没有改变,所以可能是它的修改时间发生了改变。对此我想说的是:请高人指点!
再看后面新生成的两个文件,用我们上面的办法看看内容:
显然,第一个文件是个commit对象,第二个文件是个tree对象,从引用关系来看,是先生成的tree对象,再生成的commit对象。注意,这个commit对象没有parent引用。
再看看后面生成的refs,用git show-refs可以查看所有refs的内容
master当然指的是master分支,它的值指向刚才看到的commit对象
最后就是两个log文件。log文件虽然只是供人查看,但在git中的地位非同一般。先看看其内容:
可以看到,这两个文件的内容目前是一样的。这个文件记录了什么呢?它记录的是工作目录的状态变化。其中,那一串0表示,一起是从零开始的,因为git在初始化工作目录时,并没有创建任何对象,要表示初始状态,只好用40个0来表示了。后面那串,就是指向刚才的本次的commit对象。这条记录解释出来,就是:在1281230735 +0800时刻,由Kevin Fu做了一次提交,工作目录从初始状态,转到commit 1671ae8对应的状态。
这个时候,用过git的人可能会生疑问:用git log看到的输出不是这个样子的呀。说对了,git log的输出,并不是由这里的log文件产生的,我认为,它的内容是根据commit之间的关联关系,实时计算并显示出来的。而这里的logs,是git中的reflog,用git reflog命令可以查看:
这个内容,就跟上面的对应上了吧。为什么说这个log文件很重要呢?因为在git中,objects其实都是死的,绝大多数情况下,一旦创建就不会被修改,也不会被删除;当版本控制的内容发生变化时,只有新的objects被创建出来,没有旧的objects被改变。那么一堆死东西,如何实现灵活的版本变化呢?第一个就是靠不断变化的版本指针,比如HEAD以及refs/heads/master文件,第二个,就是靠记录工作目录变化情况的日志文件。有了日志文件,你想查看谁就查看谁,想往哪个版本跳就往哪个版本跳,想合并谁就合并谁。许多git命令,都是基于这个思想而设计的。
接下来,我再添加一个文件file2.txt,但不是在master branch中,而是新开一个branch: advanced,我们看看开分支的时候,监控有何变化:
除去那个index文件的变化,看看其他的文件。首先是HEAD文件,其内容变成了:refs/heads/advanced,说明HEAD已经移到了advanced分支上。再看看新产生的refs/heads/advanced文件:
可见目前它与master分支指向同一个commit。再来看看两个日志文件:
它果然把我的一举一动都记录下来了。在第二条记录里,两个sha1值是一样的,说明没有提交,只有指针的创建或改变。
再看看另一个log:
它说明了advanced分支是从零开始,转到commit 671ae8的。看来它一点都不含糊啊。
现在,我增加文件file2.txt,并添加以下内容,但分两次提交:第一次提交前两行,第二次提交后两行
显然,第一次提交将会产生3个objects:一个commit对象,一个file2.txt的blob对象,还有一个tree对象,另外,refs/heads/advanced会指向目前的这个commit对象,然后两个log文件(logs/HEAD和logs/refs/heads/advanced)会添加一些内容,我全部列在这里:
可以看到,这次的commit对象中多了parent的引用,就是指向上一次的commit。
接下来我提交第二部分的内容,其结果与刚才的分析相似,就不写了。提交之后,我转回master分支,将advanced分支中的内容合并进来,然后将master分支推送出去,我就可以下班了。
我们看看转回master分支时,监控都有哪些输出:
可见,除了那个index文件,HEAD文件的内容被该为:ref: refs/heads/master,logs/HEAD文件中添加了一行记录分支跳转的日志。
接下来我运行git merge advanced。合并完成后,看看监控的输出:
这里列出后三项的内容:
从分支的指向可以看到,它指到advanced分支对应的commit上去了;从logs的内容可以看到,本次的操作称为merge advanced: Fast-forword。除此之外,并没有产生任何object,连commit都没有,这是因为在合并之后,git分析出当前的目录树结构与advanced分支中的目录树是一样的,所以只是简单的把master的指针指向advanced分支。
OK,在下班之前,我还是要看看master分支中的代码,确保没有什么坏代码被交上去。但是,我的神,file2.txt中有一个TODO,这要是被老板看见了,还不要我晚上加班啊!我能把它删掉再提交吗?不能啊,老板要是往回看一个版本,不就找出来了!因此,当务之急就是,把master的版本指针退回去,让它指向原来的1671ae8这个版本。git reset这个命令可以帮到我。
可以看到,master的head是真的退回去了,reflog中的记录,稍候再说。现在只要把advanced中想要的那个提交弄过来,就万事大吉了。git cherry-pick这个命令这是用来做这个的。
看,TODO果然是没有了!在这里我用的--ff参数,是要告诉git,只需要做fast-forword就可以了,因为35ba29e这个commit的parent,正是先前的master的head(1671ae8)。
OK,我可以把master分支推送到远程仓库里去了。在推之前,我需要把远程仓库加进来。这里我就用一个本地的仓库来代替远程的吧。
可见,这一步的操作就是新建了一个remote master分支的ref,然后添加了一个logs文件。看来所有的事情都办妥了,那就下班吧。
但是老板还没有下班,而是正准备做code review。他把代码checkout下来:
他的reflog文件中,完全没有我刚才操作的内容。看来,git是不会提交reflog到仓库中的。
OK,写到这里,今天的git剧就要谢幕了。相关文件在后面下载,大家可以重播。如果你有使用git的好的case,也可以分享给大家,Thank you!
我觉得2L 根本没看文章 就直接下拉回复了 。。。
哎 有点伤人
是的,因为没听说过这么个东西
楼主很强大,不会被伤到哈
没听说过就敢回复。真N。
前公司的一个项目.现在看到你这篇后,想起来的.通配符没用问题的,这个我们是参考别人的,而且也是几经修改.应该是这个git rm /path/to/the/file.txt --cached的原因,当时没有删掉.谢谢,哈哈.
git有日志的,而且可以装一个小工具gitk,很好用的.
我觉得2L 根本没看文章 就直接下拉回复了 。。。
哎 有点伤人
是的,因为没听说过这么个东西
楼主很强大,不会被伤到哈
我觉得2L 根本没看文章 就直接下拉回复了 。。。
哎 有点伤人
--------------------------
文章写得挺好 受教了
对不起,我的帖子没能解决你的问题,不过你的问题很简单,你google一下:git vs cvs vs svn,第一页的文章足以让你了解其中的区别。
但是我这篇帖子,是深入讲解git原理的。如果你有兴趣使用git,看一些简单的教程,再看看我讲的原理,再把我打包的文件down下来自己做一做,日常碰到的git问题就能迎刃而解了。
当然,如果你找到讲得更清晰明白的文章,欢迎把链接贴在回帖中。
首先,新建一个目录:git-monitor,进入目录后,用下面的命令初始化一个git仓库:
$> git init --bare git-monitor.git
然后,创建一个工作目录wp1,意思为working_copy_1,进入该目录,运行git init,以创建.git目录。
进入.git目录,会发现下列文件和目录:
HEAD config description hooks/ info/ objects/ refs/
这些都是git的演员。我们当观众的,就从监控这些文件开始。但是演员分主角、配角,和跑龙套的,在这些文件中,config是配置文件,内容不会变的;hooks中的文件是一些回调程序的例子,删掉都没关系;description文件只为某些git的web应用提供描述信息。它们都是跑龙套的,剩下的文件和目录有:
HEAD info/ objects/ refs/
在后续的操作中,还有两位要上场,分别是index文件和logs目录,至此,主要演员表为:
HEAD index info/ objects/ refs/ logs/
要用肉眼盯着它们看,实在不容易,于是我写了个ruby小程序(下载链接在最后),用于监控这些目录,一旦目录和文件有变化,就在控制台上向我们报告。我把这个程序放到.git目录下,并把它跑起来。接下来,好戏就开演了。
回到wp1目录。新建一个文件file1.txt,然后看看监控程序,发现没有任何输出,说明git对刚才的操作没有响应。既然没反应,那我就接着操作,在file1.txt中加一行内容
content added by wp1, 1st time
再看看监控,还是没有反应。看来,只要我们不调用git命令,它就不会有反应。那我就调一个看看:
$> git add .
再看看监控,终于有反应了:
Created file: index (in dir: git-monitor/wp1/.git) Created file: c2/a04aa8cba9ba9a7a2fb8c9ecf74a3a0fc5e3fc (in dir: git-monitor/wp1/.git/objects)
git add这个命令,根据`man git-add`的解释,是把某个文件加入到index。这个index实际上就是工作目录下文件和目录状态的一个快照(stage),每一次git提交所产生的tree对象,就是依据index文件产生的(对index同志的详细采访,可以参考[url=http://progit.org/book/zh/ch9-2.html]这里[/url])。
我们来看看产生的那个object到底是什么,根据git的规则,object的目录名加文件名,和起来是一个40字符的字符串,它是对文件内容进行SHA1 digest之后,用16进制编码得到的结果。此文件的内容是二进制的,要查看它,就要用下面的命令:
$> git cat-file -t c2a04aa8cba9ba9a7a2fb8c9ecf74a3a0fc5e3fc blob $> git cat-file -p c2a04aa8cba9ba9a7a2fb8c9ecf74a3a0fc5e3fc content added by wp1, 1st time
其中,-t这个参数是为了显示object类型,-p这个参数,是为了显示object的内容。显然,这个object就是刚才加进去的file1.txt,它是一个blob类型的对象,只存储文件内容和长度。
接下来,我把这次添加的内容提交一下(git commit -m 'commit by wp1, 1st time'),再看看监控,又有输出了,这次的内容还真丰富啊:
Changed file: index Created file: 16/71ae856c149673436da08f1ba026469c3a918d (in dir: git-monitor/wp1/.git/objects) Created file: 30/c64c3a55b02f4c251565ef057d402f84751b56 (in dir: git-monitor/wp1/.git/objects) Created file: heads/master (in dir: git-monitor/wp1/.git/refs) Created file: HEAD (in dir: git-monitor/wp1/.git/logs) Created file: refs/heads/master (in dir: git-monitor/wp1/.git/logs)
首先,我们发现index文件被改变了。但是,经过我仔细比对两次的index文件的二进制字节码后发现,它的内容并没有改变,所以可能是它的修改时间发生了改变。对此我想说的是:请高人指点!
再看后面新生成的两个文件,用我们上面的办法看看内容:
$> git cat-file -p 1671ae856c149673436da08f1ba026469c3a918d tree 30c64c3a55b02f4c251565ef057d402f84751b56 author Kevin Fu <corntrace@email.com> 1281230735 +0800 committer Kevin Fu <corntrace@email.com> 1281230735 +0800 commit by wp1, 1st time $> git cat-file -p 30c64c3a55b02f4c251565ef057d402f84751b56 100644 blob c2a04aa8cba9ba9a7a2fb8c9ecf74a3a0fc5e3fc file1.txt
显然,第一个文件是个commit对象,第二个文件是个tree对象,从引用关系来看,是先生成的tree对象,再生成的commit对象。注意,这个commit对象没有parent引用。
再看看后面生成的refs,用git show-refs可以查看所有refs的内容
$> git show-refs 1671ae856c149673436da08f1ba026469c3a918d refs/heads/master
master当然指的是master分支,它的值指向刚才看到的commit对象
最后就是两个log文件。log文件虽然只是供人查看,但在git中的地位非同一般。先看看其内容:
$ cat logs/HEAD 0000000000000000000000000000000000000000 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281230735 +0800 commit (initial): commit by wp1, 1st time $ cat logs/refs/heads/master 0000000000000000000000000000000000000000 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281230735 +0800 commit (initial): commit by wp1, 1st time
可以看到,这两个文件的内容目前是一样的。这个文件记录了什么呢?它记录的是工作目录的状态变化。其中,那一串0表示,一起是从零开始的,因为git在初始化工作目录时,并没有创建任何对象,要表示初始状态,只好用40个0来表示了。后面那串,就是指向刚才的本次的commit对象。这条记录解释出来,就是:在1281230735 +0800时刻,由Kevin Fu做了一次提交,工作目录从初始状态,转到commit 1671ae8对应的状态。
这个时候,用过git的人可能会生疑问:用git log看到的输出不是这个样子的呀。说对了,git log的输出,并不是由这里的log文件产生的,我认为,它的内容是根据commit之间的关联关系,实时计算并显示出来的。而这里的logs,是git中的reflog,用git reflog命令可以查看:
$> git reflog 1671ae8 HEAD@{0}: commit (initial): commit by wp1, 1st time
这个内容,就跟上面的对应上了吧。为什么说这个log文件很重要呢?因为在git中,objects其实都是死的,绝大多数情况下,一旦创建就不会被修改,也不会被删除;当版本控制的内容发生变化时,只有新的objects被创建出来,没有旧的objects被改变。那么一堆死东西,如何实现灵活的版本变化呢?第一个就是靠不断变化的版本指针,比如HEAD以及refs/heads/master文件,第二个,就是靠记录工作目录变化情况的日志文件。有了日志文件,你想查看谁就查看谁,想往哪个版本跳就往哪个版本跳,想合并谁就合并谁。许多git命令,都是基于这个思想而设计的。
接下来,我再添加一个文件file2.txt,但不是在master branch中,而是新开一个branch: advanced,我们看看开分支的时候,监控有何变化:
$> git checkout -b advanced (monitor outputs) Changed file: index Changed file: HEAD Created file: heads/advanced (in dir: /Users/corntrace/git-monitor/wp1/.git/refs) Created file: refs/heads/advanced (in dir: /Users/corntrace/git-monitor/wp1/.git/logs) Changed file: HEAD (in dir: /Users/corntrace/git-monitor/wp1/.git/logs)
除去那个index文件的变化,看看其他的文件。首先是HEAD文件,其内容变成了:refs/heads/advanced,说明HEAD已经移到了advanced分支上。再看看新产生的refs/heads/advanced文件:
$> git show-ref 1671ae856c149673436da08f1ba026469c3a918d refs/heads/advanced 1671ae856c149673436da08f1ba026469c3a918d refs/heads/master
可见目前它与master分支指向同一个commit。再来看看两个日志文件:
$ cat logs/HEAD 0000000000000000000000000000000000000000 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281230735 +0800 commit (initial): commit by wp1, 1st time 1671ae856c149673436da08f1ba026469c3a918d 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281236136 +0800 checkout: moving from master to advanced
它果然把我的一举一动都记录下来了。在第二条记录里,两个sha1值是一样的,说明没有提交,只有指针的创建或改变。
再看看另一个log:
0000000000000000000000000000000000000000 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281236136 +0800 branch: Created from HEAD
它说明了advanced分支是从零开始,转到commit 671ae8的。看来它一点都不含糊啊。
现在,我增加文件file2.txt,并添加以下内容,但分两次提交:第一次提交前两行,第二次提交后两行
content added by wp1, 1st time additional content added by wp1, 1st time too # TODO: implement a feature # I plan to do ...
显然,第一次提交将会产生3个objects:一个commit对象,一个file2.txt的blob对象,还有一个tree对象,另外,refs/heads/advanced会指向目前的这个commit对象,然后两个log文件(logs/HEAD和logs/refs/heads/advanced)会添加一些内容,我全部列在这里:
$> git show-ref 35ba29ec8f31d5372b75d7be6b1ec7f03c0fb666 refs/heads/advanced 1671ae856c149673436da08f1ba026469c3a918d refs/heads/master $> git cat-file -p 35ba29ec8f31d5372b75d7be6b1ec7f03c0fb666 tree 9c1c4549a869ede4d5f85c93594c1c23c311122f parent 1671ae856c149673436da08f1ba026469c3a918d author Kevin Fu <corntrace@email.com> 1281251100 +0800 committer Kevin Fu <corntrace@email.com> 1281251100 +0800 commit by wp1 for file2.txt, 1st time $> git cat-file -p 9c1c4549a869ede4d5f85c93594c1c23c311122f 100644 blob c2a04aa8cba9ba9a7a2fb8c9ecf74a3a0fc5e3fc file1.txt 100644 blob baa4a1630ce88a9198b5eda885884aadab795806 file2.txt $> git cat-file -p baa4a1630ce88a9198b5eda885884aadab795806 content added by wp1, 1st time additional content added by wp1, 1st time $> cat logs/HEAD 0000000000000000000000000000000000000000 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281230735 +0800 commit (initial): commit by wp1, 1st time 1671ae856c149673436da08f1ba026469c3a918d 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281236136 +0800 checkout: moving from master to advanced 1671ae856c149673436da08f1ba026469c3a918d 35ba29ec8f31d5372b75d7be6b1ec7f03c0fb666 Kevin Fu <corntrace@email.com> 1281251100 +0800 commit: commit by wp1 for file2.txt, 1st time $> cat logs/refs/heads/advanced 0000000000000000000000000000000000000000 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281236136 +0800 branch: Created from HEAD 1671ae856c149673436da08f1ba026469c3a918d 35ba29ec8f31d5372b75d7be6b1ec7f03c0fb666 Kevin Fu <corntrace@email.com> 1281251100 +0800 commit: commit by wp1 for file2.txt, 1st time
可以看到,这次的commit对象中多了parent的引用,就是指向上一次的commit。
接下来我提交第二部分的内容,其结果与刚才的分析相似,就不写了。提交之后,我转回master分支,将advanced分支中的内容合并进来,然后将master分支推送出去,我就可以下班了。
我们看看转回master分支时,监控都有哪些输出:
Changed file: index Changed file: HEAD Changed file: HEAD (in dir: /Users/corntrace/git-monitor/wp1/.git/logs)
可见,除了那个index文件,HEAD文件的内容被该为:ref: refs/heads/master,logs/HEAD文件中添加了一行记录分支跳转的日志。
接下来我运行git merge advanced。合并完成后,看看监控的输出:
Changed file: index Changed file: heads/master (in dir: /Users/corntrace/git-monitor/wp1/.git/refs) Changed file: HEAD (in dir: /Users/corntrace/git-monitor/wp1/.git/logs) Changed file: refs/heads/master (in dir: /Users/corntrace/git-monitor/wp1/.git/logs)
这里列出后三项的内容:
$> git show-ref 8227ae64f1f651669c6445d4c37909c8443df209 refs/heads/advanced 8227ae64f1f651669c6445d4c37909c8443df209 refs/heads/master $> cat logs/HEAD (猜都能猜出来,就省了吧) $> cat logs/refs/heads/master 0000000000000000000000000000000000000000 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281230735 +0800 commit (initial): commit by wp1, 1st time 1671ae856c149673436da08f1ba026469c3a918d 8227ae64f1f651669c6445d4c37909c8443df209 Kevin Fu <corntrace@email.com> 1281252267 +0800 merge advanced: Fast-forward
从分支的指向可以看到,它指到advanced分支对应的commit上去了;从logs的内容可以看到,本次的操作称为merge advanced: Fast-forword。除此之外,并没有产生任何object,连commit都没有,这是因为在合并之后,git分析出当前的目录树结构与advanced分支中的目录树是一样的,所以只是简单的把master的指针指向advanced分支。
OK,在下班之前,我还是要看看master分支中的代码,确保没有什么坏代码被交上去。但是,我的神,file2.txt中有一个TODO,这要是被老板看见了,还不要我晚上加班啊!我能把它删掉再提交吗?不能啊,老板要是往回看一个版本,不就找出来了!因此,当务之急就是,把master的版本指针退回去,让它指向原来的1671ae8这个版本。git reset这个命令可以帮到我。
$> git reset --hard 1671ae8 (monitor outputs) Changed file: index Changed file: heads/master (in dir: /Users/corntrace/git-monitor/wp1/.git/refs) Changed file: HEAD (in dir: /Users/corntrace/git-monitor/wp1/.git/logs) Changed file: refs/heads/master (in dir: /Users/corntrace/git-monitor/wp1/.git/logs) $> git show-ref 8227ae64f1f651669c6445d4c37909c8443df209 refs/heads/advanced 1671ae856c149673436da08f1ba026469c3a918d refs/heads/master $> cat logs/refs/heads/master 0000000000000000000000000000000000000000 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281230735 +0800 commit (initial): commit by wp1, 1st time 1671ae856c149673436da08f1ba026469c3a918d 8227ae64f1f651669c6445d4c37909c8443df209 Kevin Fu <corntrace@email.com> 1281252267 +0800 merge advanced: Fast-forward 8227ae64f1f651669c6445d4c37909c8443df209 1671ae856c149673436da08f1ba026469c3a918d Kevin Fu <corntrace@email.com> 1281253859 +0800 1671ae8: updating HEAD
可以看到,master的head是真的退回去了,reflog中的记录,稍候再说。现在只要把advanced中想要的那个提交弄过来,就万事大吉了。git cherry-pick这个命令这是用来做这个的。
$> git cherry-pick --ff 35ba29e (此时这里居然没有任何输出,git的作者们太高估用户了!来看看monitor outputs) Changed file: index Changed file: heads/master (in dir: /Users/corntrace/git-monitor/wp1/.git/refs) Changed file: HEAD (in dir: /Users/corntrace/git-monitor/wp1/.git/logs) Changed file: refs/heads/master (in dir: /Users/corntrace/git-monitor/wp1/.git/logs) $> git show-ref 8227ae64f1f651669c6445d4c37909c8443df209 refs/heads/advanced 35ba29ec8f31d5372b75d7be6b1ec7f03c0fb666 refs/heads/master $> cat file2.txt content added by wp1, 1st time additional content added by wp1, 1st time
看,TODO果然是没有了!在这里我用的--ff参数,是要告诉git,只需要做fast-forword就可以了,因为35ba29e这个commit的parent,正是先前的master的head(1671ae8)。
OK,我可以把master分支推送到远程仓库里去了。在推之前,我需要把远程仓库加进来。这里我就用一个本地的仓库来代替远程的吧。
$> git remote add origin /path/to/git-monitor.git (这一步monitor无输出) $> git push origin master (monitor outputs) Created file: remotes/origin/master (in dir: /Users/corntrace/git-monitor/wp1/.git/refs) Created file: refs/remotes/origin/master (in dir: /Users/corntrace/git-monitor/wp1/.git/logs) $> git show-ref 8227ae64f1f651669c6445d4c37909c8443df209 refs/heads/advanced 35ba29ec8f31d5372b75d7be6b1ec7f03c0fb666 refs/heads/master 35ba29ec8f31d5372b75d7be6b1ec7f03c0fb666 refs/remotes/origin/master $> cat logs/refs/remotes/origin/master 0000000000000000000000000000000000000000 35ba29ec8f31d5372b75d7be6b1ec7f03c0fb666 Kevin Fu <corntrace@email.com> 1281255166 +0800 update by push
可见,这一步的操作就是新建了一个remote master分支的ref,然后添加了一个logs文件。看来所有的事情都办妥了,那就下班吧。
但是老板还没有下班,而是正准备做code review。他把代码checkout下来:
$> git co /path/to/git-monitor.git && cd git-monitor $> git reflog 35ba29e HEAD@{0}: clone: from /Users/corntrace/git-monitor/git-monitor.git
他的reflog文件中,完全没有我刚才操作的内容。看来,git是不会提交reflog到仓库中的。
OK,写到这里,今天的git剧就要谢幕了。相关文件在后面下载,大家可以重播。如果你有使用git的好的case,也可以分享给大家,Thank you!
- git-monitor.tar.gz (15.4 KB)
- 下载次数: 121
评论
13 楼
shuminghuang
2012-07-06
写得很好,不过我对您的文件监控脚本也很感兴趣,不知道能否分享
12 楼
trace
2010-11-16
感谢ls,找到了这么详细的解释!
11 楼
yanwuhuan
2010-11-16
首先,我们发现index文件被改变了。但是,经过我仔细比对两次的index文件的二进制字节码后发现,它的内容并没有改变,所以可能是它的修改时间发生了改变。
----
正好用过这个选项。
看git help config的输出,里面core.trustctime是管这个的,
core.trustctime
If false, the ctime differences between the index and the working copy are ignored; useful when the inode change time is regularly modified by something outside Git (file system crawlers and some backup systems). See git-update-index(1). True by default.
这个选项关闭的话,似乎对git“闪电般的速度”有所影响,但影响非常有限。对有需要的人,这个还是无所谓的
----
正好用过这个选项。
看git help config的输出,里面core.trustctime是管这个的,
core.trustctime
If false, the ctime differences between the index and the working copy are ignored; useful when the inode change time is regularly modified by something outside Git (file system crawlers and some backup systems). See git-update-index(1). True by default.
这个选项关闭的话,似乎对git“闪电般的速度”有所影响,但影响非常有限。对有需要的人,这个还是无所谓的
10 楼
linginfanta
2010-08-16
太强大了吧。我还是svn好了。
9 楼
esmiles
2010-08-16
qinglangee 写道
whywhy36 写道
qinglangee 写道
写这么一大堆
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
我觉得2L 根本没看文章 就直接下拉回复了 。。。
哎 有点伤人
是的,因为没听说过这么个东西
楼主很强大,不会被伤到哈
没听说过就敢回复。真N。
8 楼
orcl_zhang
2010-08-11
trace 写道
楼上所说的.gitignore问题,能否说得详细一些?
如果是通配符匹配的问题,可以看看别人的.gitignore文件,比如这个http://github.com/facebook/three20/blob/master/.gitignore
如果是某个文件已经在git版本控制中了,又想ignore它,就需要先 git rm /path/to/the/file.txt --cached 把它删掉,然后再写入.gitignore中
如果是通配符匹配的问题,可以看看别人的.gitignore文件,比如这个http://github.com/facebook/three20/blob/master/.gitignore
如果是某个文件已经在git版本控制中了,又想ignore它,就需要先 git rm /path/to/the/file.txt --cached 把它删掉,然后再写入.gitignore中
前公司的一个项目.现在看到你这篇后,想起来的.通配符没用问题的,这个我们是参考别人的,而且也是几经修改.应该是这个git rm /path/to/the/file.txt --cached的原因,当时没有删掉.谢谢,哈哈.
git有日志的,而且可以装一个小工具gitk,很好用的.
7 楼
qinglangee
2010-08-10
whywhy36 写道
qinglangee 写道
写这么一大堆
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
我觉得2L 根本没看文章 就直接下拉回复了 。。。
哎 有点伤人
是的,因为没听说过这么个东西
楼主很强大,不会被伤到哈
6 楼
whywhy36
2010-08-10
qinglangee 写道
写这么一大堆
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
我觉得2L 根本没看文章 就直接下拉回复了 。。。
哎 有点伤人
--------------------------
文章写得挺好 受教了
5 楼
trace
2010-08-10
楼上所说的.gitignore问题,能否说得详细一些?
如果是通配符匹配的问题,可以看看别人的.gitignore文件,比如这个http://github.com/facebook/three20/blob/master/.gitignore
如果是某个文件已经在git版本控制中了,又想ignore它,就需要先 git rm /path/to/the/file.txt --cached 把它删掉,然后再写入.gitignore中
如果是通配符匹配的问题,可以看看别人的.gitignore文件,比如这个http://github.com/facebook/three20/blob/master/.gitignore
如果是某个文件已经在git版本控制中了,又想ignore它,就需要先 git rm /path/to/the/file.txt --cached 把它删掉,然后再写入.gitignore中
4 楼
orcl_zhang
2010-08-10
怎么没有介绍到.gitignore
之前项目里遇到过一个这样的问题.gitignore 失效,而且是有时候有用,有时候没用,一直不知道怎么解决.
之前项目里遇到过一个这样的问题.gitignore 失效,而且是有时候有用,有时候没用,一直不知道怎么解决.
3 楼
trace
2010-08-10
qinglangee 写道
写这么一大堆
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
对不起,我的帖子没能解决你的问题,不过你的问题很简单,你google一下:git vs cvs vs svn,第一页的文章足以让你了解其中的区别。
但是我这篇帖子,是深入讲解git原理的。如果你有兴趣使用git,看一些简单的教程,再看看我讲的原理,再把我打包的文件down下来自己做一做,日常碰到的git问题就能迎刃而解了。
当然,如果你找到讲得更清晰明白的文章,欢迎把链接贴在回帖中。
2 楼
yeaha
2010-08-10
楼上的回复挺让人扫兴的
1 楼
qinglangee
2010-08-10
写这么一大堆
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
既然是版本管理系统,怎么不跟CVS.SVN比较下,列下优点
相关推荐
2. **添加文件到暂存区**:使用`git add`命令将修改的文件放入暂存区,准备进行下一次提交。可以添加单个文件、多个文件或整个工作目录。 3. **提交版本**:通过`git commit`命令保存当前暂存区的状态为一个新版本...
1. **Git的基本理念**:Git的核心思想是版本管理和协作,它通过记录文件的每一次变更,实现了对项目历史的完整追踪。这种分布式模型使得每个开发者都可以拥有完整的项目副本,提高了数据的安全性和可靠性。 2. **...
相反,人们会说“我不会用 Git”、“git flow 很好吃”、“我每天都在用”、“我不能没有 Git 了”、“我男朋友没有用过” VCS,我要分手”不是目标观众。 虽然部分是为 Mac OS X 编写的,但如果能在命令行上使用 ...
【标题】"极市直播第63期:黄茹辉-极市计算机视觉开发者榜单(ECV2020)第一次线上集训" 涵盖了计算机视觉领域的专业知识,结合了深度学习技术和竞赛实践,旨在提升开发者的技术能力。这次直播活动由黄茹辉主讲,...
**在浏览器上运行Java程序 Doppio** Doppio 是一个开源项目,它允许开发者在浏览器环境中执行Java程序,无需安装...如果你对Java、JavaScript和Web技术有深入的兴趣,研究Doppio的源码无疑会是一次有价值的学习经历。
每一次失败都可能是成功的垫脚石,每一次挫折都促使我们变得更强大。 7. **付出与收获**:无论选择何种道路,都需要付出努力,IT行业尤其如此。程序员的"996"工作制就是付出艰辛的体现,而相应的,技术上的突破和...
于 2017-05-13,在上海举办的 "第 62 期开源中国源创会 " 的 "放码过来" 环节,我登台对 XXL-JOB 做了演讲,台下五百位在场观众反响热烈(图文回顾 )。我司大众点评目前已接入 XXL-JOB,内部别名《Ferrari》...
- 学习新的编程语言或框架:如果源码使用了你不熟悉的语言或库,这是一次学习的好机会。 - 研究设计模式:源码中可能体现了各种设计模式,比如单例模式、工厂模式等,这些都是软件工程的重要组成部分。 - 提升调试...
【描述】"powermill二次开发视频源码1.4节" 提示这是一个教学视频系列的第1.4部分,专注于讲解如何利用源代码进行PowerMill的二次开发。在这一节中,观众可以期待学习到具体的编程实践,包括代码结构、函数调用以及...
总的来说,这个毕业设计项目涵盖了软件工程的全过程,对于学习者来说是一次宝贵的实践经验,有助于提升其在实际项目中的问题解决能力和团队协作技巧。同时,超市管理系统的开发也是对信息技术如何赋能传统零售业的一...
7. **安全机制**:投票系统应防止重复投票,这可能通过限制每个用户只能投一次票或设置验证码等方式实现。此外,密码安全存储、防止SQL注入也是重要的安全考虑。 8. **前端界面**:虽然描述中没有明确提到,但通常...
在本压缩包“开心麻花影视作品分析的程序.zip”中,包含的是一份用于分析开心麻花影视作品的程序源代码。...同时,这也是一次深入理解数据科学工作流程的好机会,涵盖了数据获取、清洗、分析和可视化的全过程。
它的设计目标是“一次编写,到处运行”,这得益于Java虚拟机(JVM)的跨平台能力。 2. **Java语法基础**:PPT可能涵盖了Java的基本语法,如变量、数据类型、控制结构(条件语句、循环)、类与对象、封装、继承和...
这样的组织方式有利于逐步验证想法,减少一次性开发大量功能的风险。 深入到知识点,我们可以讨论以下几个方面: 1. **敏捷开发**:DEMO的发布是敏捷开发过程中的常见实践,它强调快速迭代和持续交付。每个DEMO都...
3. **互动体验**:“fishbowl”一词有时用于描述一种开放、透明的讨论形式,因此视频可能包含了一次公开讨论或研讨会,让观众能够参与到问题的解答和解决方案的构建中。 4. **开源项目**:如果"fishbowl-video-1-...
【描述】:“汇报总结—24”可能是这次汇报的主题或者是文件的序列号,暗示着这是一次关于特定主题的第24次汇报或者总结。通常,这种类型的文档会包含过去一段时间内的工作进展、遇到的问题、解决方案、成果展示以及...
8. **多平台支持**:由于TV-Browser是基于Java的,它可以运行在多种操作系统上,包括Windows、Mac OS X和Linux,体现了Java的“一次编写,到处运行”特性。 9. **社区参与**:开源项目依赖于社区的贡献,TV-Browser...
7. **安全与版权**:源码管理确保了知识产权的安全,版本控制系统如Git可以帮助团队协作,并追踪每一次改动。 尽管上述内容是基于电影行业的通用实践,但要了解具体项目的源码细节,我们需要更多关于这个“鬼屋大...
10. **版本控制**:开源库通常使用Git进行版本控制,这使得用户可以跟踪代码的变更历史,下载特定版本,甚至参与到项目的开发中去。 在【Tournamenter-master】这个压缩包中,包含了源代码、文档、示例项目和其他...
弹幕是网络视频文化中的一个重要组成部分,特别是在动画和直播领域,它允许观众在观看视频的同时发送即时评论,形成一种独特的社交互动。DPlayer支持弹幕的显示、发送和管理,用户可以通过设置不同的参数来调整弹幕...