• 欢迎访问 winrains 的个人网站!
  • 本网站主要从互联网整理和收集了与Java、网络安全、Linux等技术相关的文章,供学习和研究使用。如有侵权,请留言告知,谢谢!

git操作(2):commit

Git winrains 来源:veedrin 1年前 (2019-08-30) 40次浏览

git是一个版本管理系统。它的终极目的就是将项目特定时间的信息保留成一个版本,以便将来的回退和查阅。
我们已经介绍了暂存区,暂存区的下一步就是版本库,而促成这一步操作的是git commit命令。

提交

暂存区有待提交内容的情况下,如果直接运行git commit命令,git会跳往默认编辑器要求你输入提交说明,你也可以自定义要跳往的编辑器。

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Initial commit
# Changes to be committed:
#	new file:   a.md

提交之后我们就看到这样的信息。

[master (root-commit) 99558b4] commit for nothing
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a.md

如果我就是不写提交说明呢?

Aborting commit due to empty commit message.

看到没有,提交信息在git中时必填的。
如果提交说明不多,可以加参数-m直接在命令后面填写提交说明。

$ git commit -m "commit for nothing"

你甚至可以将加入暂存区和提交一并做了。

$ git commit -am "commit for nothing"

但是要注意,和git add -u命令一样,未跟踪的文件是无法提交上去的。

重写提交

amend翻译成中文是修改的意思。git commit --amend命令允许你修改最近的一次commit。

$ git log --oneline
8274473 (HEAD -> master) commit for nothing

目前项目提交历史中只有一个commit。我突然想起来这次提交中有一个笔误,我把高圆圆写成了高晓松(真的是笔误)。但是呢,我又不想为了这个笔误增加一个commit,毕竟它仅仅是一个小小的笔误而已。最重要的是我想悄无声息的改正它,以免被别人笑话。
这时我就可以使用git commit --amend命令。
首先修改高晓松高圆圆
然后执行git add a.md命令。
最后重写提交。git会跳往默认或者自定义编辑器提示你修改commit说明。当然你也可以不改。

$ git commit --amend
commit for nothing
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# Date:      Thu Jan 3 09:33:56 2019 +0800
# On branch master
# Initial commit
# Changes to be committed:
#	new file:   a.md

我们再来看提交历史。

$ git log --oneline
8a71ae1 (HEAD -> master) commit for nothing

提交历史中同样只有一个commit。但是注意哟,commit已经不是之前的那个commit了,它们的校验和是不一样的。这就是所谓的重写。

tree对象和commit对象

commit操作涉及到两个git对象。
第一是tree对象。
它存储子目录和子文件的引用。如果只有blob对象,那版本库将是一团散沙。正因为有tree对象将它们的关系登记在册,才能构成一个有结构的版本库。
添加到暂存区操作并不会生成tree对象,这时项目的结构信息存储在index文件中,直到提交版本库操作,才会为每一个目录分别生成tree对象。
第二是commit对象。
它存储每个提交的信息,包括当前提交的根tree对象的引用,父commit对象的引用,作者和提交者,还有提交信息。所谓的版本,其实指的就是这个commit对象。
作者和提交者通常是一个人,但也存在不同人的情况。

objects

初始化一个git项目,新建一些文件和目录。

src/
src/a.md
lib/
lib/b.md

首先运行git add命令。我们清楚,这会在.git/objects目录下生成一个blob对象,因为目前两个文件都是空文件,共享一个blob对象。

.git/objects/info/
.git/objects/pack/
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391

现在我们运行git commit命令,看看有什么变化。

.git/objects/info/
.git/objects/pack/
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
.git/objects/93/810bbde0f994d41ef550324a2c1ad5f9278e19
.git/objects/52/0c9f9f61657ca1e65a288ea77d229a27a8171b
.git/objects/0b/785fa11cd93f95b1cab8b9cbab188edc7e04df
.git/objects/49/11ff67189d8d5cc2f94904fdd398fc16410d56

有意思。刚刚只有一个blob对象,怎么突然蹦出来这么多git对象呢?想一想之前说的commit操作涉及到两个git对象这句话,有没有可能多出来的几个,分别是tree对象和commit对象?
我们使用git底层命令git cat-file -t <commit>查看这些对象的类型发现,其中有一个blob对象,三个tree对象,一个commit对象。
这是第一个tree对象。

$ git cat-file -t 93810bb
tree
$ git cat-file -p 93810bb
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	b.md

这是第二个tree对象。

$ git cat-file -t 520c9f9
tree
$ git cat-file -p 520c9f9
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	a.md

这是第三个tree对象。

$ git cat-file -t 0b785fa
tree
$ git cat-file -p 0b785fa
040000 tree 93810bbde0f994d41ef550324a2c1ad5f9278e19	lib
040000 tree 520c9f9f61657ca1e65a288ea77d229a27a8171b	src

可以看到,提交时每个目录都会生成对应的tree对象。
然后我们再来看commit对象。

$ git cat-file -t 4911ff6
commit
$ git cat-file -p 4911ff6
tree 0b785fa11cd93f95b1cab8b9cbab188edc7e04df
parent c4731cfab38f036c04de93facf07cae496a124a2
author veedrin <veedrin@qq.com> 1546395770 +0800
committer veedrin <veedrin@qq.com> 1546395770 +0800
commit for nothing

可以看到,commit会关联根目录的tree对象,因为关联它就可以关联到所有的项目结构信息,所谓擒贼先擒王嘛。它也要关联父commit,也就是它的上一个commit,这样才能组成版本历史。当然,如果是第一个commit那就没有父commit了。然后就是commit说明和一些参与者信息。
我们总结一下,git add命令会为加入暂存区的内容或文件生成blob对象,git commit命令会为加入版本库的内容或文件生成tree对象和commit对象。至此,四种git对象我们见识了三种。
为啥不在git add的时候就生成tree对象呢?
所谓暂存区,就是不一定会保存为版本的信息,只是一个准备的临时场所。git认为在git add的时候生成tree对象是不够高效的,完全可以等版本定型时再生成。而版本定型之前的结构信息存在index文件中就好了。

作者:veedrin

来源:https://github.com/veedrin/horseshoe/blob/master/git/commit.md


版权声明:文末如注明作者和来源,则表示本文系转载,版权为原作者所有 | 本文如有侵权,请及时联系,承诺在收到消息后第一时间删除 | 如转载本文,请注明原文链接。
喜欢 (1)