DEV Community

Kaffu theine
Kaffu theine

Posted on • Updated on

How to download file using git http protocol v2

So to download file from git using git http protocol v2 is very simple but a little bit tricky, lets go into it.

First, request to <GIT_URL>/refs/info?service=git-upload-pack with header Git-Protocol: version=2 example:

curl -H "Git-Protocol: version=2" https://github.com/Hiyurigi/zenia-blog.git/info/refs?service=git-upload-pack
Enter fullscreen mode Exit fullscreen mode

The server will give you response:

001e# service=git-upload-pack
0000000eversion 2
0023agent=git/github-gf57b30a1e6ef
0013ls-refs=unborn
0027fetch=shallow wait-for-done filter
0012server-option
0017object-format=sha1
0000
Enter fullscreen mode Exit fullscreen mode

Let me explain what the response means...
Every request/response line to the git protocol is called PKT-LINE you can see the documentation Git Protocol Common.
The first 4-byte PKT-LINE is hex encoded string length example: 0012command=fetch thats mean this line have 18 character...
"Wait? that's 17 character long" the 18th character is \n the newline character is optional.
The response above is called Capability Advertisement.
Simply, the server give you their capability.

You can type request like this:

curl -X POST -H "Git-Protocol: version=2" --data-raw $'0014command=ls-refs\n0000' https://github.com/Hiyurigi/zenia-blog.git/git-upload-pack
Enter fullscreen mode Exit fullscreen mode

Or without newline like this:

curl -X POST -H "Git-Protocol: version=2" --data-raw $'0013command=ls-refs0000' https://github.com/Hiyurigi/zenia-blog.git/git-upload-pack
Enter fullscreen mode Exit fullscreen mode

Okay, lets go deeper...
After you get the server capability you can request using POST method to the <GIT_URL>/git-upload-pack to get the refs.
The command-request scheme is:

command-request = command
    capability-list
    delim-pkt
    command-args
    flush-pkt
command = PKT-LINE("command=" key LF)
command-args = *command-specific-arg
delim-pkt = 0001
flush-pkt = 0000
Enter fullscreen mode Exit fullscreen mode

example:

curl -X POST -H "Git-Protocol: version=2" --data-raw "0014command=ls-refs
0015agent=git/2.38.1
0017object-format=sha1
00010009peel
000csymrefs
000bunborn
0014ref-prefix HEAD
001bref-prefix refs/heads/
001aref-prefix refs/tags/
0000" https://github.com/Hiyurigi/zenia-blog.git/git-upload-pack
Enter fullscreen mode Exit fullscreen mode

Note: delim-pkt SHOULD NOT followed by a newline otherwise the request will failed

The server will give you back the hex-encoded hash of the refs in your repository
Example:

005238ec7c18271bd84bca6c0f55410d4da3a088877a HEAD symref-target:refs/heads/master
003f38ec7c18271bd84bca6c0f55410d4da3a088877a refs/heads/master
0000
Enter fullscreen mode Exit fullscreen mode

The next step is requestting the packfile, You can do that by send request to the same url with fetch command, like this

curl -X POST -H "Git-Protocol: version=2" --data-raw "0012command=fetch
0015agent=git/2.38.1
0017object-format=sha1
0001000ethin-pack
0010no-progress
000eofs-delta
0032want 38ec7c18271bd84bca6c0f55410d4da3a088877a
0009done
0000" https://github.com/Hiyurigi/zenia-blog.git/git-upload-pack
Enter fullscreen mode Exit fullscreen mode

For more information about fetch command you can read the documentation Git Protocol V2 Fetch
The server will response you with packfile binary data, the next step is unpacking the packfile, i will do that in the next part...

Thanks for reading

Author: Hiyurigi

Top comments (0)