惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 【当耐特】
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tenable Blog
T
Tailwind CSS Blog
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
Webroot Blog
Webroot Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Cloudflare Blog
T
Threat Research - Cisco Blogs
V
Visual Studio Blog
Jina AI
Jina AI
V
V2EX
I
InfoQ
Latest news
Latest news
P
Proofpoint News Feed
T
Threatpost
Engineering at Meta
Engineering at Meta
P
Proofpoint News Feed
美团技术团队
The Register - Security
The Register - Security
L
LangChain Blog
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
GbyAI
GbyAI
Cloudbric
Cloudbric
Microsoft Azure Blog
Microsoft Azure Blog
C
Cisco Blogs
U
Unit 42
Microsoft Security Blog
Microsoft Security Blog
MyScale Blog
MyScale Blog
V
Vulnerabilities – Threatpost
TaoSecurity Blog
TaoSecurity Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Recent Commits to openclaw:main
Recent Commits to openclaw:main
W
WeLiveSecurity
博客园 - 司徒正美
T
The Exploit Database - CXSecurity.com
小众软件
小众软件
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园_首页
N
News and Events Feed by Topic

依云's Blog

Wayfire支持不缩放Xwayland啦 - 依云's Blog 使用wayvnc远程访问无头Wayfire会话 - 依云's Blog pacfiles: 高速的 pacman -F 替代品 用 Android 手机当电脑的话筒 - 依云's Blog 使用 ffmpeg 对音频文件进行响度归一化 - 依云's Blog 使用 nftables 屏蔽大量 IP - 依云's Blog YubiKey 初体验 - 依云's Blog fcitx5 码表同步方案 - 依云's Blog 我正在使用的火狐扩展(2024年版) - 依云's Blog 使用 PipeWire 实现自动应用均衡器 如果你发现你的 OOM Killer 在乱杀进程 使用 atuin 管理 shell 命令历史 btrfs 元数据满了怎么办 btrfs 翻车记 在 nspawn 里运行 docker Linux 上的字体配置与故障排除 新的 PaddleOCR 部署方案 使用 EasyEffects 调整 Bose 音箱的体验 让离线软件真正离线 我所讨厌的网页行为 tmux 状态栏优化 Google Chrome 中的字体设置 从 getmail6 到 offlineimap 微信消息通知的困扰 Qt 的字体渲染问题 Wayfire 迁移进展(四):不那么 high 的 DPI Wayfire 迁移进展(二):Xwayland HiDPI 以及 waybar Wayfire 迁移进展 不同情况下的图形效果 Wayland 初体验 纯 CSS 实现倒三角箭头 倾听蓝牙耳机的按键事件 使用 bwrap 沙盒 一次失败的 KDE 尝试 i3 的 scratchpad 处理逻辑 HiDPI 配置记录 让 QEMU 使用 SPICE 协议 Python 小版本升级是怎么 break 已有项目的 让 Arch Linux 系统和最新的镜像同步,从最快的镜像下载 tar 归档的权限问题 Linux 的环境变量怎么设 终端色彩总结 桥接无线网卡! Linux 的进程优先级与 nice 值 Intel GVT-g 初体验 自制大上 Paperlike HD「驱动」 Python 3.8 升级记录 Poker II 键盘调教记 红黑树到底是个什么树 gdb 不肯加载调试信息怎么办? NVIDIA PRIME 配置笔记 寻找最快的 GitHub IP 火狐远程调试火狐 fcitx 扩展:使用键盘粘贴选区(以及X选区原理科普) T470p 使用N卡运行 Xorg 系统在解析哪些域名呢? 正确的隐藏挂载点的方法 迁移系统到 SSD 使用 cgroups net_cls 来让 docker 走代理 使用 cgroups 限制指定进程的内存使用 在 Linux 下整理磁盘碎片 docker 里几个基本概念的简单类比 解析 zxinc IPv6 数据库 Ant Design 彩蛋事件之我见 通过 Cloudflare DNS 验证来申请 Let's Encrypt 证书 正确地上传至 PyPI 并展示文档 与 Android 进行 WLAN Direct 连接 获得高精度环形镜子一枚 每次修 Python 代码的 bug 的时候总会想念 Rust 永远不要 tail -f 管道 人生苦短,我用 skim XZ2C: 没有 root 的日子(也还过得去) 使用 iptables 透明代理 TCP 与 UDP Linux 下获取文件的创建时间 递归遍历目录:Python vs Go vs Rust 这个博客要死了 Windows 10 中配置网络共享 小米 Note 3 令人失望地方 小米 Note 3 入手体验 使用 VirtualBox 启动本地磁盘上的其它系统 大上 Paperlike HD 电子墨水屏开箱体验 加固 systemd 服务 嗨 Win10,这是我的浏览器 在 Linux 下设置录音笔的时间 我正在使用的火狐扩展 使用 Python 读取火狐的 cookies WireGuard: 简单好用的 VPN To hup or not to hup 书签搜索:藏在书签里的搜索引擎 使用 Prince 转换 HTML 文档给 Kindle 阅读 放弃 you-get,转投 youtube-dl 等连上互联网之后再来找我吧 改了一下 GTK 3 的默认主题 新的火狐,新的旅程 师者不师,学生不学 谁又用掉了我的磁盘空间?——魔改 ncdu 来对比文件树大小变化 NeWifi 3.2.1.5900 root swapview 更新 nodejs 子进程的正确用法(你应该忽视函数名) 电脑被盗事件
使用 git 底层命令创建提交
依云 · 2015-02-08 · via 依云's Blog

通常,创建 git 提交使用的是 git add、git commit 这些高层命令。这些命令有个特点:它们都需要工作区的存在,并且很可能会改变工作区里的文件。

如果没有工作区,或者工作区不能用的时候怎么办呢?比如想在服务器上的纯(旧称:祼)版本库里的钩子脚本里创建提交,在版本库被更新时自动生成点东西什么的。一个简单的解决方案是再克隆一份,然后在那边弄好了再 push 过来。但那样的话,你得区分一次 push 是不是由你的脚本自身触发的了。这当然是可行的,但是,不觉得直接操作纯版本库更有意思吗 O(∩_∩)O~

或者,如果你的工作区里有一个文件叫「test」,另一个文件叫「Test」,而你当前能使用的文件系统和/或操作系统是不区分文件名大小写的,这样可能就没有办法通过工作区做想要的改动了。

我之前也曾用 pygit2 来直接创建提交。那个还是比较基础的,还是需要工作区。这次让我向大家介绍一下我的新玩法,深入 git 底层,围观一下一个提交的诞生历程~~(其实是早就玩过了的,只是一直没有分享出来而已 >_<

首先,克隆一个版本库来玩儿。直接在已有的版本库里玩太危险了,万一不小心玩坏了就囧了(虽然也不是多大的问题,毕竟我有备份的嘛=w=

git clone --bare ~/.vim dotvim

读者想要一起玩的话,可以从网络克隆我的 vim 配置版本库,如

git clone --bare git://github.com/lilydjwg/dotvim dotvim

进去 dotvim 目录里 ls 一下,可以看到,只剩下以前在 .git 目录里会见到的文件了呢:

>>> ls
branches  config  description  HEAD  hooks  index  info  objects  packed-refs  refs

要创建的提交是在 master 分支上。我们先使用 ls-tree 命令看看这个分支上有哪些文件。ls-tree 其实是列出 tree 对象用的,加上 -r 参数就会递归地把 tree 对象里的 tree 对象给列出来,就像 -R 之于 ls 命令一样。

不过你给它提交(commit)对象也可以的啦。它会自动取这个提交所指向的 tree 对象:

git ls-tree -r master

相当于

git ls-tree -r 'master^{tree}'

嗯,分支名实际上是指向这个分支上的最后一个对象的符号引用。

我要把 vimrc 文件里的注释行全删掉。要想修改一个文件,就得先找到要修改的文件,而不像添加文件那样直接加进去就可以了。让我们把要修改的 vimrc 文件的 hash 值找出来:

old_vimrc=$(git ls-tree -r master | awk '$4 == "vimrc" { print $3 }')

当然这里是不必用 -r 的啦。写在这里方便嘛,下一次想改 plugin 目录下的东西可以直接改路径就可以了,不用担心要改其它可能会忘记的东西。

然后拿 cat-file 命令看看这个 blob 对象。cat-file 命令我用得挺多的,因为经常会想看看另一个分支、或者另一个提交里某个文件长什么样子。

git cat-file -p $old_vimrc

其实这里可以直接指定要显示的对象的,比如master:vimrc就是 master 对应的提交上的 vimrc 文件。如果使用 zsh 的话,冒号后边的路径部分也是可以补全的哦。这里为了阐述原理,就做「分解动作」了。

得到了文件内容,就可以修改了。修改完毕,使用 hash-object 命令将文件存入 git 对象数据库里。这一句命令相当于修改好文件之后再做 git add 操作。hash-object 会返回对象的 hash 值。我们得把它记下来。

new_vimrc=$(git cat-file -p $old_vimrc | sed '/^"/d' | git hash-object -w --stdin --path vimrc)

不管之前有没有,先删一下 index,也就是所谓的「staging area」。已经添加但是还未提交的目录树就存在这个文件里边了。

rm -f index

然后,创建我们需要的 index。得使用 ls-tree 命令列出所有文件的信息,然后把我们修改过的信息加到末尾,会自动覆盖之前已有的项。如果删除这个列表里的某些项的话,就相当于是删除了那些文件。如果添加原本不存在的项,就是添加文件了。

{git ls-tree -r master; echo -e "100644 blob $new_vimrc\tvimrc";} | git update-index --add --index-info

index 已经准备好了。我们把目录树写到 git 对象数据库里吧:

new_master_tree=$(git write-tree)

我们得到了一个新的 tree 对象的 hash 值。当然因为目录树是树状的,以上命令实际上会写入多个 tree 对象。我们只要有根 tree 对象的 hash 值就可以了。

该创建提交对象了:

commit=$(git commit-tree -p master -m '在没有工作区的情况下创建的提交' $new_master_tree)

提交对象创建好还不够。那只是一个提交对象而已,我们还没有更新分支的信息呢。我们把这个提交作为新的 master 分支的头:

git update-ref refs/heads/master "$commit"

大功告成!

可以使用git showgit log看看成果了哦~

当然,如果想要钩子脚本里使用的话,记得在修改前加锁哦。

参考资料