gitgit-http-backend

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


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?


Solution

  • 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