Git Smart HTTP Protocal Internals

Saito · 2012年06月19日 · 最后由 fsword 回复于 2012年06月20日 · 6082 次阅读

Git

fetch( include clone & pull ):

get_info_refs:

request:

GET: /info/refs?service=git-upload-pack

response:

001e# service=git-upload-pack\n000000a3f989f58785072b3b3ba66650d53a22cc29e79b24 HEAD\u0000multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed no-done\n0041f989f58785072b3b3ba66650d53a22cc29e79b24 refs/heads/features\n003ff989f58785072b3b3ba66650d53a22cc29e79b24 refs/heads/master\n0000

git_upload_pack:

request:

POST: /git-upload-pack

006fwant f989f58785072b3b3ba66650d53a22cc29e79b24 multi_ack_detailed no-done side-band-64k thin-pack ofs-delta\n0032want f989f58785072b3b3ba66650d53a22cc29e79b24\n0032want f989f58785072b3b3ba66650d53a22cc29e79b24\n00000009done\n

response:

0008NAK\n0021\x02Counting objects: 27, done.\n004b\x02Compressing objects:  11% (1/9)   \rCompressing objects:  22% (2/9)   \r0028\x02Compressing objects:  33% (3/9)   \r0028\x02Compressing objects:  44% (4/9)   \r0028\x02Compressing objects:  55% (5/9)   \r0028\x02Compressing objects:  66% (6/9)   \r0028\x02Compressing objects:  77% (7/9)   \r0028\x02Compressing objects:  88% (8/9)   \r0028\x02Compressing objects: 100% (9/9)   \r002c\x02Compressing objects: 100% (9/9), done.\n002c\x02Total 27 (delta 0), reused 0 (delta 0)\n0787\x01PACK\x00\x00\x00\x02\x00\x00\x00\e\x90\rx\x9C\x95\xCB\xCD\t\x021\x10@\xE1{\xAA\xC8]\x90Iv3? b\x0FV0&\x13]0\xAE\xC4,\xB6\xAF\x96\xE0\xE9\xC1\aot3O\"9*\x152\xC6KFF\fVC\xB5\xC4Z\x959\x94\x99\xB8\x12\x8A{j\xB7\xC7\xF00%\x12 D\xCD!C\xB8\xC44\x19$`\x12\xCC4\x03\x17\xE0(1\x89\xD3m\xDC\xD6\xEE\xCF\xBA\x8C\xD5\x1F^\xBF\xBC\xB7\xD3\xB5\xE9r\xDF\xE7\xB5\x1D}\x98f\x00\"\x8E\xD1\xEF\x80\x01\xDCW\xDB2\x86\xFD59-\xC5w\xD3f\xEE\x03\x8F\xBB<n\x91\rx\x9C\x95\x8B\xDB\t\x021\x10\x00\xFFSE\xFE\x05\xD9\\\xB2y\x80\x88=X\xC1f\xB3\xD1\x80\xF1$\xE6\xB0}\xCF\x12\xFC\x18\x06\x06f\x0E\x11\xBD$\xEFw0e_\x1D\xC7d0\x16\xBB\x10p\xE4%Z2\xC5D\x9F([\xF5\xA2!\xCF\xA9\xAB\rIr\x14\t\xC2Y\x10\x01jF\x0E)Kp\x80\x95\xAB\t\x9C\x1DZE\xDB\xBC\xAFC_\xA9\xCDU\x9F\xDE?}\xB6\xCB\xADS{\x1Cy\xEDgm\xAC\x03\b\x01!\xE9\x03D\x00\xB5\xD7\xDE\xE6\x94\xBF&E\xA5\xE8!T\xBA\xA8/a\x11>A\x91\rx\x9C\x95\x8BQ\n\x021\f\x05\xFF{\x8A\xFE\v\x92\xB6i\xBA\v\"\xDE\xC1\x13d\x9BT\x17\xAC+\xB5\x8B\xD7\xB7\x1EAx0\xCC\xC0\xEBM\xD5\x06O\xA1\xB89;\x87\xEA\x88s*\x98\x9C\xF3\x02~\x19[b^\"\x11\xB2\x98\x177}v\e\t\x85f\x8A@AR\x9A$\n\xE2\x10N\x9C\xB5@\xD1\x182\xA3\"\x18\xDE\xFB}k\xF6\xCAk\xDF\xEC\xE9\xFD\xC3g\xBF\xDC*\xAF\x8Fc\xDE\xEA\xD9\xBA\x80\x00)\xE1\xE4\xED\x01&\x003j]{\xD7\xBFN\x86ElS\x96\xAA\xE6\v\x11\xCA=\xAD\x94\rx\x9C\x95\xCBQ\n\xC20\f\x80\xE1\xF7\x9E\xA2\xEF\xC2\xC8\x966\xCB\x83\x88w\xF0\x04Y\x93\xE8\xC0:\xA9\x1D^_=\x82O?|\xF0\xF7f\x16\x89@\xD2\x82y.\x93/N\xCE\xC5\x99m2)\xC5\xBD\xA8\x81\xF8l#bxJ\xB3G\x8FZ\x04\x8D\x119/\xA0\xC49q\xCAD\xC6\x19\xD9h\x1Au\xF1D@nA\xF6~\xDBZ\xBC\xC8\xDA\xB7x|\xFD\xF2\xDE\xCF\xD7*\xEB}([=\xC5\x11\x13\xC0LL\x14\x0F\xC0\x00\xE1\xABu\xED\xDD\xFE\x9A\x82\xA8\xC6f\xA2\xD5\x86\xAA\xE1\x03\xFAy@4\x91\rx\x9C\x95\x8BA\n\x021\fE\xF7=E\xF7\x82d\xD2\xA6MA\xC4;x\x82\xB4Mu\xC0q\xA4v\xF0\xFA\x8EG\x90\xBFx\xF0\x1E\x7FtU\xEB\x8B\x17&\xE4\xD0\x1C\xE5\xAA\x98\xA5b\xA0)y\xA6=\xB8\x06\xAC)I.\xE6%]\x9F\xC3\xB6\xC4\xA9\x11G&\x88\x98\xDD>\t!\x10Tr\x82X\n&\x8D)\xA37\xB2\x8D\xFB\xDA\xEDU\xE6\xB1\xDA\xD3\xFB\x87\xCFv\xB9-2?\x8Ee]\xCEvr\x1E \x06F\xB2\a`\x00\xB3\xDBe\x1EC\xFF:\x19\xA9\xD5v\x95\xBA\xA8\xF9\x021\x88=\xAE\x91\rx\x9C\x95\x8BQ\n\x02!\x10@\xFF=\x85\xFFA\xCC\xA8\xEB\x8E\x10\xD1\x1D:\xC1\xE8\xCC\xD6B\xB6a.]?;B\xF0\xE0\xC1\x83\xD7\x9B\xAA\rT\x8A,\fS \x11`\n\x8E\b\x13\xCD\x89\x10\xBC\xBAi\xC1%\xE6\x92\xD0\xBC\xB8\xE9\xB3[AI\x9C3\xB3`\x8C\x03\xF2\x1A\x02E\xF4\x91a\xA41\x86,9%\xC3{\xBFo\xCD^y\xED\x9B=\xBD\x7F\xFA\xEC\x97[\xE5\xF5q,[=[\xF4\x01`\xF6\xE8\x9C=\x00\x01\x98Q\xEB\xDA\xBB\xFE5\x19\x16\xB1MY\xAA\x9A/*-=\x8D\x91\rx\x9C\x95\xCBM\n\x021\f@\xE1}O\xD1\xBD M\xD2\x9F\x19\x10\xF1\x0E\x9E iS\x1D\xB0\xCEP;x}\xF5\b\xAE\x1E|\xF0FW\xB5a\xAE\xC4\x80$D(\x01UQ\xB3\a\xCAU$\xC9\xCC\x90\x04=\x00\x16\xB3q\xD7\xE7\xB0\xC9\v\x8AN\\9F/A\x93\x84\x90(!2\xC6\f~\x8E\x15\xA7\xAA\xCE\e\xDE\xC7}\xED\xF6\xCA\xCBX\xED\xE9\xF5\xCB{\xBF\xDC\x1A/\x8Fc^\xDB\xD9\x02y\xE7\x129\b\xF6\xE0&\xE7\xCCW\xDB2\x86\xFE5\x19.\xC5v\xE5\xD2\xD4|\x00i\xD9=\xF3\x96\rx\x9C\x95\x8C[\n\xC20\x10\x00\xFFs\x8A\xFD\x17d\x93\xE6U\x10\xF1\x0E\x9E`\x93\xDD\xD8\x82\xB1%M\xE9\xF5\xADG\xF0k``\xA67\x110\x85\x06\xAF}\x8C\xB9\xE8,F8\x12\xBB\x9C\x06G\x81I'\x8F\xEC\xB55%\xA9\x95\x9A|:dc\x8D\xC4\x88\x98\x84J@d\xB2\xC1\xB9\x92(`\xCC\xE8,\xFB1\x85\xB3R\xB4\xF7ii\xF0\xA4\xB9/p\xDB~8\xF6\xC7\xAB\xD2\xFC\xBE\xE6\xA5\xDEA\x0F\x161\x98\xD1\x8Dp\xC1s\xA8N[\xE7\xDE\xE5\xAFH\xAD\xFB6\xC1G\x0EhB\\E}\x012\xEC@\xD3\x91\nx\x9C\x95\xCBA\n\xC20\x10@\xD1}N1{\xA1$3M\x9A\x01\x11\xEF\xE0\t\xA6\xC9\xA8\x01c M\xF1\xFA\xDA#\xB8\xFA\xF0\xE0\x8F\xAE\nH\xAC\xC93\xA5 \xE8\x18u\t\xC9Z?\x93\xBF/s\\Q2\xC6U#\xA1\x91}<[\x87\x9B\x94\xD1\xE0\xBC\x1D\xF9\xEC\xD7G\x95\xF2\x9AR\xAB\x17pD\xCC\xCEc\fp\xB2\xD1Z\xF3\xD3Z\xC6\xD0\xBF&#9CWyW5_<\x850\x0E\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xD0\xBE\x1E\xC2\xEE\xBEf\xFA\xEDL\xF3T\xCE\x98\r\xFF&.\xBD\xB7\xA2\x06\x00\xE4\xF5\x0E\xCF\xB0\x01x\x9C+\xC9L\xCEN-\xE1*\x81\x02.\x006f\x069\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xB0\x9A{\xFE\xE8\x17\r'[\xD9\xFB\x12\x8E\x8A\xD2\x8Bu\xD2n[p\x03\x00\xE3\xC1\f\xA7?x\x9C+\xC9L\xCEN-\xE1*\x81\x00.\x00/\xC3\x05\xC5\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xF8\xBE\xE0i\x97\xA9\x97\xE6\xB20\xF1\xDB\xDFw\x84*V\xF2\xCA}\xE1\x06\x00\xF5\x1C\x0E!>x\x9C+\xC9L\xCEN-\xE1*\x01\x03.\x00)\x94\x05Q\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\x98\x94\x9F''P\xAE?\xBD+\xF6K\xD2\x94\x9A\x7FIjw\xBE\xFE\x05\x00\xE3\\\x0F8=x\x9C+\xC9L\xCEN-\xE1*\x01\x01.\x00#\xD9\x04\xDD\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa0\x17\x15\xCDV\xB4\xF8\x94\xAE\xE2q\xCF\xAB\xEE\xE4\xF6\x87\x93b$e\x00\xD2v\f\xD1<x\x9C+\xC9L\xCEN-\xE1*\x01\x02.\x00\x1E\x92\x04i\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\x98\xB3\xFE\xDC\xA5O\xD9\x97\x16/\x8B\x8D\xDB\xDC\xE9\xE7\x14\xD8\xFB\xEA\xEF\x1E\x00\f$\x11(;x\x9C+\xC9L\xCEN-\xE1*))\xE1\x02\x00\x19\xBF\x03\xF5\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMax\x13\xB4F\xF6\x8E\xAF\xBET\xFF\x94\xED\x8F/q\x1C0\xB51\xD5h\x03\x00\xED\xFA\r\xE1:x\x9C+\xC9L\xCEN-\xE1*)\xE1\x02\x00\x15`\x03\x81\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xB0x\xAB\xF5j\x9F\x9Et\xF3\xFF\xB5\xC7\x99\xB46\xF4X\xAF\x0F\xFD\xEE\x00\x00\xF1<\x0E\xD17x\x9C+\xC9L\xCEN-\xE1\x02\x00\ve\x02\x8F\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMax6\xF7\xD1\xECM\x17\xAF9{wk\xAE+\x8F\xBAq\xE8IO\xF0D\x00\v`\x10\xC50x\x9C\x03\x00\x00\x00\x00\x01\x198^\x9E\x03\xAA\x8D&\xFDb'\xF1\xB4wh\x8B:\xE9y0006\x01\xFB0000

push:

get_info_refs:

GET: /info/refs?service=git-receive-pack

response:

001f# service=git-receive-pack\n00000074f989f58785072b3b3ba66650d53a22cc29e79b24 refs/heads/features\u0000 report-status delete-refs side-band-64k ofs-delta\n003fdca3e83385b0d685484566e8538e621dbf4606fe refs/heads/master\n0000

git_receive_pack:

request:

POST: /git-receive-pack

0084f379eb8ee7ecbe5500fb5c79be7405fcf17cb453 035790766ac1c01b253e0508796c7408d0829259 refs/heads/master\x00 report-status side-band-64k0000PACK\x00\x00\x00\x02\x00\x00\x00\x03\x91\rx\x9C\x95\x8B\xDB\t\x021\x10\x00\xFFSE\xFE\x05\xD9\\\xB2y\x80\x88=X\xC1f\xB3\xD1\x80\xF1$\xE6\xB0}\xCF\x12\xFC\x18\x06\x06f\x0E\x11\xBD$\xEFw0e_\x1D\xC7d0\x16\xBB\x10p\xE4%Z2\xC5D\x9F([\xF5\xA2!\xCF\xA9\xAB\rIr\x14\t\xC2Y\x10\x01jF\x0E)Kp\x80\x95\xAB\t\x9C\x1DZE\xDB\xBC\xAFC_\xA9\xCDU\x9F\xDE?}\xB6\xCB\xADS{\x1Cy\xEDgm\xAC\x03\b\x01!\xE9\x03D\x00\xB5\xD7\xDE\xE6\x94\xBF&E\xA5\xE8!T\xBA\xA8/a\x11>A\xA5\x02x\x9C340031Q(JML\xC9M\xD5\xCBMa\xB0\x9A{\xFE\xE8\x17\r'[\xD9\xFB\x12\x8E\x8A\xD2\x8Bu\xD2n[p\x03\x00\xE3\xC1\f\xA7?x\x9C+\xC9L\xCEN-\xE1*\x81\x00.\x00/\xC3\x05\xC5Wu\x8E\xD6\x88\xCB\x0F\xEA\x83\xA6\x97\xB2\xA3p\xA31\x9C\xFB\xC9\x18

response:

0030\x01000eunpack ok\n0019ok refs/heads/master\n00000000

原文链接:http://saito.im/note/Smart-HTTP-Protocal-Internals/

理解本身 Git 的传输协议很有意义。

例如:可以做基于 branch 的保护,shitty programmer 不能提交 master 之类的这种需求。(虽然我个人很不认同这种做法,我觉得团队第一要意就是信任.) 在自己拥有 Git HTTP 服务端的情况下,可以做 post 拦截。

在 push 中 POST: /git-receive-pack 里:

可以得知 push 的是 refs/heads/master\x00 . 做拦截就可以判断用户是否有 push master 的权限。然后允许或否。

#2 楼 @bhuztez 好吧,我自己本身是 Gitlab 的 core team member.

Gitlab 本身依赖 Gitolite 是很有问题的。我很早就跟 randx 沟通过了。

如果以后非要支持 SSH 的话,需要换一种方案。我自己是觉得可以直接用 HTTPS 全全替换。

Gitolite 本身的授权系统跟 Gitlab 自身的授权存在冗余。Gitolite 也不适合更大型一点的状况。

Gitlab 本身在其他方面是没有硬伤的。界面以及其他功能都挺完善的。

#3 楼 @Saito 不是的,如果你只是在协议头那里处理一下,有些东西还是没法搞的,比如像gerrit那样的 review 流程。我觉得只支持 HTTP 协议是很不靠谱的,HTTP 很明显的问题是,你上传大小是有限的,除非你自己用异步框架折腾个 HTTP server 起来只处理 git 请求。

#4 楼 @bhuztez 没用过 gerrit. 话说他的 review 流程是怎样的?

HTTP 这个问题之前已经解决过了。给 nginx 添加 chunkin 模块就好了,或者自己用 Rainbows! serve .

#4 楼 @bhuztez 上传大小不是 http 协议自身的缺点

#6 楼 @fsword 但是你一般情况下你就是会配置一下最大上传大小的。

#7 楼 @bhuztez 这个“一般”太不靠谱了,git server 肯定应该独立于其它 webapp 来搭建,在这个前提下,盲目设置一个最大上传大小是有些僵化思维的味道了

#8 楼 @fsword 假设你只有一个 IP...

#9 楼 @bhuztez 这个假设对于要做服务的人有些捉襟见肘了,而如果仅仅是开发环境,你又何必惧怕 nginx 上放的太开呢? 退一万步,如果想用一台机器先顶着,逐渐提高服务水平,还可以在 nginx 上分出不同的端口、domain 等等

http 最大的问题是没有完整性校验,不过 git 正好克服了这个问题

#10 楼 @fsword 我想的是,有人用 HTTP,默认配置不改就跑着了,之后就有可能碰到问题了。

#12 楼 @bhuztez 你说的情况也存在,不过如果开发者本身技术不过关,用什么都一样。我觉得 ruby 社区有两个特点,一个是比较 nice,但是另外也很推崇做事的专业性

#13 楼 @fsword

你说的情况也存在,不过如果开发者本身技术不过关,用什么都一样。

什么叫过关?我认为默认配置能跑起来很重要。

我觉得 ruby 社区有两个特点,一个是比较 nice,但是另外也很推崇做事的专业性

每个社区都是这么自认为的吧,这个简直就是废话。

#14 楼 @bhuztez 我一直以为你是 ray_linn 的马甲...

#15 楼 @hooopo 目测应该不是,ray_linn 大大喜欢科普 .Net .

#14 楼 @bhuztez Rack 是 Ruby WebServer 的基石。所有的 Web Application 几乎都是使用 Rack 来对接 WebServer 的。所以 Rack 能做的事情就很多。

Rack 自身实现了 chunked.rb 跟 content_length.rb 用来对付没有 length 头的问题。

https://github.com/rack/rack/tree/master/lib/rack

并且 Rack 在包装各种 WebServer 的 Handler 的时候为各种 WebServer 添加了这方面的支持。

thin: https://github.com/rack/rack/blob/master/lib/rack/handler/thin.rb#L2-3

mongrel: https://github.com/rack/rack/blob/master/lib/rack/handler/mongrel.rb#L3-4

所以几乎所有 Ruby 的 WebServer 基本都不会出现默认配置跑不起来的情况..

而会有问题的,都是 Proxy Server 的问题。例如 nginx 必须要携带 content_length 参数,否则会返回 411 Length Required 错误码。所以才要为 nginx build 一个 module, nginx 本身添加 module 也是很平常的事情。chunked 需求本身也挺平常的。

#18 楼 @Saito

nginx 本身添加 module 也是很平常的事情。

nginx 就是那个添加个模块也要重新编译一下的怪胎

#19 楼 @bhuztez 你要这么挑剔就写一个不需要重新编译的 nginx 啦

#20 楼 @hooopo 我可以选择不用第三方模块的...

#15 楼 @hooopo ray_linn 的火力可猛~ 谁挡杀谁~ 哈哈 ;)

#21 楼 @bhuztez nginx 的这个“添加模块也要重新编译”的特点可能是出于性能方面的考虑。这事见仁见智,如果部署和配置管理很强,那么这些问题无非就是一个配置项,如果没有条件做这些基础设施,同时对性能不敏感,那么可以用 apache 甚至直接用基于 ruby rack 的 web server,那也不是不行

需要 登录 后方可回复, 如果你还没有账号请 注册新账号