在git commit前,频繁的git add可能会产生不必要的悬空(dangling)对象

本文探讨了在使用Git管理项目时,频繁保存文件与只在提交前进行一次保存之间的权衡,以及如何通过合理的保存策略减少Git仓库中的垃圾对象。通过创建简单项目并进行文件操作,演示了在不同保存时机下的对象生成情况,揭示了频繁保存可能带来的性能损耗,并解释了Git自动清理机制。最后,提供了一种更高效的保存方法,即在提交前仅进行一次保存操作,以优化项目管理效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平时大家编辑文件,为了安全,可能会不自觉的频繁的进行保存动作,这是个好习惯。

在使用git管理项目时,如果我们在提交之前,对文件的每次修改都进行git add去更新index 文件,这个过程会产生不必要的垃圾对象,为减少垃圾对象其实完全可以在commit之前进行一次git add操作。 其实在多数情况下这不是个大问题, git gc 在达到一定条件下会清除这些悬空对象。


下面来验证以上的说法。

创建一个空的项目,

$ mkdir project

$ cd project

$ git init

$ vi  readme    # 添加一行文字并保存,比如“1111”

$ git add readme

$ git commit -m "1st commit"

此时来看仓库中的对象目录

$ tree .git/objects/

.git/objects/
├── 0e
│   └── b9495a6ee73ae496fbce6553682e719b012c54
├── 32
│   └── a76ac05dbd68ed630175aec403d7c1a71d0455
├── 5f
│   └── 2f16bfff90e6620509c0cf442e7a3586dad8fb
├── info
└── pack

来看看这几个对象:

32a7...是一个树对象,记录了一个blob对象的SHA-1哈希值及权限、名字等信息,树对象的就像是文件系统中的目录,记录多个文件以及目录(表现为子树)

$ git cat-file -t 32a7
tree
$ git cat-file -p 32a7
100644 blob 5f2f16bfff90e6620509c0cf442e7a3586dad8fbreadme


5f2f...是一个blob,这就是我们刚才的文件内容。5f2f...就是在上面的树对象中被引用的

$ git cat-file -t 5f2f
blob
$ git cat-file -p 5f2f
1111


0eb9...是一个提交对象,它记录一个树对象的哈希值,以及提交都的信息,关于这次提交的描述信息。

$ git cat-file -t 0eb9
commit
$ git cat-file -p 0eb9
tree 32a76ac05dbd68ed630175aec403d7c1a71d0455
author root <root@centos> 1384572308 +0800
committer root <root@centos> 1384572308 +0800


1st commit



接下来对readme文件进行修改并git add

$ vi readme #添加一行"2222"

$ git add readme 

$ tree .git/objects/

$ tree .git/objects/
.git/objects/
├── 0e
│   └── b9495a6ee73ae496fbce6553682e719b012c54
├── 32
│   └── a76ac05dbd68ed630175aec403d7c1a71d0455
├── 4f
│   └── 142ee300fd3f4fa2e89c76c76c0923d911f7ea
├── 5f
│   └── 2f16bfff90e6620509c0cf442e7a3586dad8fb
├── info
└── pack


6 directories, 4 files



此时发现多了一个对象4f142ee..., 查看它的类型的内容,这就是刚才的修改过的readme文件

$ git cat-file -t 4f14
blob
$ git cat-file -p 4f14
1111
2222


然后继续修改readme,并提交

$ vi readme #新加一行 "3333"

$ git add readme

$ git commit -m "2nd commit"

根据git log 的输出,我们多了一个2f3c...的提交对象,

$ git log
commit 2f3cb268bda33bbc1a63fecfb302065e9c73d951
Author: root <root@centos>
Date:   Sat Nov 16 11:31:13 2013 +0800


    2nd commit


commit 0eb9495a6ee73ae496fbce6553682e719b012c54
Author: root <root@centos>
Date:   Sat Nov 16 11:25:08 2013 +0800


    1st commit


再来查看2f3c这个提交对象,它指向一个树对象,488d

$ git cat-file -t 2f3c
commit
$ git cat-file -p 2f3c
tree 488d26500f021cb25799b6b295bb07da43c53a79
parent 0eb9495a6ee73ae496fbce6553682e719b012c54
author root <root@centos> 1384572673 +0800
committer root <root@centos> 1384572673 +0800


2nd commit



继续查看 树对象488d...,它指向一个blob对象e003,也就是我们的文件

$ git cat-file -t 488d
tree
$ git cat-file -p 488d

100644 blob e0037f05868f8aec30670b1c09de3ba6f22a30ecreadme



来看看我们的.git/objects目录,有点多,把上面出现过的总结发现,4f14这个对象没有被引用,它就是添加2222后git add所产生的对象,之后我们又添加了3333,产生了e003这个最终被引用的对象

$ tree .git/objects/
.git/objects/
├── 0e
│   └── b9495a6ee73ae496fbce6553682e719b012c54
├── 2f
│   └── 3cb268bda33bbc1a63fecfb302065e9c73d951
├── 32
│   └── a76ac05dbd68ed630175aec403d7c1a71d0455
├── 48
│   └── 8d26500f021cb25799b6b295bb07da43c53a79
├── 4f
│   └── 142ee300fd3f4fa2e89c76c76c0923d911f7ea
├── 5f
│   └── 2f16bfff90e6620509c0cf442e7a3586dad8fb
├── e0
│   └── 037f05868f8aec30670b1c09de3ba6f22a30ec
├── info
└── pack


9 directories, 7 files



用一张图总结,第二次提交前,对同一文件做了两次修改并立即add,第一次产生的对象现在不被引用,成了悬空对象,不过将来会被git gc所清除。



最后,也可以用git fsck来检查一下那些没有被引用的blob,tree,commit各类型的对象

$ git fsck
dangling blob 4f142ee300fd3f4fa2e89c76c76c0923d911f7ea


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值