[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: git: how to figure out with a script what the last commit on remote repo is without fetching it



On Mon, Sep 08, 2014 at 11:58:35PM +0200, lee wrote:
> One is using git:, the other one https:.
snip
> I don't have ssh access to any of the remote hosts.  Both repos, I can
> only clone/fetch/merge from.

OK.

> But I don't want to fetch?  If I can fetch only the data (a minimal
> amount of data) I need to figure out if the remote is more recent,
> that's ok, though.

I don't mean a full git fetch - I mean fetch only the information you need,
i.e. what is the remote's head pointing at. If it's different, then there are
likely more commits on the remote repository than local.

With the HTTP(s) method, git fetches the following paths

> http://somehost/somerepo/info/refs?service=git-upload-pack

The server returns a string (as an application/octet-stream mime-type, most
likely) containing something like the following

> 1935f7966c0efffeb192824c53f30633b0030e74        refs/heads/master

You could write a script to fetch that file and compare that sha1 against
your local repository, something like this (unfinished/untested)

> # to be run from inside the local git repo
> remoteurl=$(git config -l|grep remote.origin.url|cut -d= -f2-)
> localsha1=$(cat .git/refs/heads/master)
> remotesha1=$(curl "${remoteurl}/info/refs?service=git-upload-pack" \
>     2>/dev/null | awk '/refs\/heads\/master$/ { print $1 }')
> if [ "$remotesha1" != "$localsha1" ]; then
>     echo "the remote git repo has changed" \
>     | mail -s 'git repo has changed' you@example.com
> fi

In practice you would want to check all refs, not just refs/heads/master,
to see if there any added (or deleted) branches from your local copy, and
check the hash for each of them.

To achieve the same with something using the git:// protocol, you would need
roughly the same logic but couldn't use curl (or wget, or HEAD) to fetch the
refs. 

I did a quick trace of a git fetch over a git:// repo, essentially you 
initiate a TCP connection to port 9418, send something like the following

0000   67 69 74 2d 75 70 6c 6f 61 64 2d 70 61 63 6b 20  git-upload-pack 
0010   2f 63 6f 6c 6c 61 62 2d 6d 61 69 6e 74 2f 6c 68  /collab-maint/lh
0020   61 73 61 2e 67 69 74 00 68 6f 73 74 3d 61 6e 6f  asa.git.host=ano
0030   6e 73 63 6d 2e 64 65 62 69 61 6e 2e 6f 72 67 00  nscm.debian.org.

(in my case, I was cloning git://anonscm.debian.org/collab-maint/lhasa.git, so
you would substitute the path appropriately)

The reply looked like the following

0000   61 62 34 61 65 35 31 63 30 62 36 65 62 33 62 32  ab4ae51c0b6eb3b2
0010   39 31 66 39 63 35 34 66 34 61 37 64 32 65 36 64  91f9c54f4a7d2e6d
0020   38 38 33 62 64 63 61 34 20 48 45 41 44 00 6d 75  883bdca4 HEAD.mu
snip

I've snipped there because the very first thing returned was the sha1
for HEAD, you then get some other stuff as well.

I attempted to reconstruct the above using netcat, but I couldn't get it to
work. This is what I tried:

> printf "git-upload-pack /collab-maint/lhasa.git\0host=anonscm.debian.org\0"\
>     | nc anonscm.debian.org 9418 \
>     | hexdump -C

To persue this further, I'd suggest reading up on the git:// wire protocol
(quite possibly there's a command other than 'git-upload-pack' which would
give you what you want)

-- 
Jonathan Dowland


Reply to: