Differences between git-receive-pack/git-upload-pack and git-http-backend

1.3k Views Asked by At

To understand more about git, I try to write a very simple Git server using Python and Flask. I registered an endpoint and redirect the calls to git-http-backend. So far a simple pull works fine. Also simple/small pushes go through.

Now I stumbled over git-upload-pack and git-receive-pack, and I am wondering why or when I would need them? Are they used by git-http-backend in the background? I am not sure if I additionally have to support these commands too.

P.S. I try to wrap my head around SmartHTTP. Does it mean Full-Duplex? Or what is meant to be SmartHTTP vs Dumb? I don't exactly understand what is supposed to be smart if it also just receives and sends/pushes a file?

1

There are 1 best solutions below

2
On BEST ANSWER

I presented the smart http protocol in 2011 with Git 1.6.6.

But git-receive-pack and git-upload-pack would be involve even without HTTP, with for instance SSH URL.

I have to know about them because I often install Git on servers where I am not root.
That means the executable git is not in /usr/bin, but in /my/path/to/git/usr/bin

And whenever I do a git clone on my PC from that server (or a git ls-remote), I get:

bash: git-upload-pack: command not found

If I try a git push from my PC to that server:

bash: git-receive-pack: command not found

That is because, when you look at the usr/bin folder of a Git installation, you would see:

-rwxr-xr-x. 1 <auser> <agroup> 3.0M Dec 13  2019 git*
drwxr-xr-x. 5 <auser> <agroup>   45 Jun  8 14:35 ../
drwxr-xr-x. 2 <auser> <agroup>  107 Jun  8 14:35 ./
lrwxrwxrwx. 1 <auser> <agroup>    3 Jun  8 14:35 git-receive-pack -> git*
lrwxrwxrwx. 1 <auser> <agroup>    3 Jun  8 14:35 git-upload-pack -> git*
lrwxrwxrwx. 1 <auser> <agroup>    3 Jun  8 14:35 git-upload-archive -> git*

Meaning git-receive-pack and git-upload-pack are just symlink to git itself(!)

But, because of their naming convention (git-xxx), they are actually calling git with the command receive-pack or upload-pack.
(incidently, that works for any script git-xxx in your $PATH: you can then type git xxx, that will call your git-xxx script)

For my custom Git installation to work, I had to implement git-xxx wrappers:

Example:

/my/path/to/git/git-receive-pack:

#!/bin/bash

source "setenv"
"/my/path/to/git/usr/bin/git" receive-pack "$@"

With setenv setting the right PATH:

export PERLLIB=/my/path/to/git/usr/share/perl5/vendor_perl:/my/path/to/git/opt/endpoint/perl-5.22.0/share/perl5/vendor_perl
export PATH=/my/path/to/git/usr/bin:/my/path/to/git/usr/libexec/git-core:$PATH
export LD_LIBRARY_PATH=/project/${USER}/refer/pcres/current/usr/lib64

And on the client (PC) side, I need, for a remote using the server with custom Git installation, to add:

git config --global remote.origin.uploadpack /my/path/to/git/git-upload-pack
git config --global remote.origin.receivepack=/my/path/to/git/git-receive-pack