2

I would like to know how to use a pair of fifos as a means for exchanging commits between Git repository clones.

git-remote-fd documents how to use this from a client's perspective, but does not give any example how to set up the associated server part.

So far, I have tried the following:

# Prepare repos.
git init a
(cd a && echo one > file1 && git add file1 && git commit -m first)
git clone a b
(cd a && echo two > file2 && git add file2 && git commit -m second)
mkfifo ab && mkfifo ba
# Now I want to push from a to b via the fifos
(cd a && git push fd::8,9 master) 8< ba 9> ab &
(cd b && git pull fd::9,8 master) 8> ba 9< ab

No luck, though. The fifos obviously block. The commands hang and never complete.

I guess "git push" is not the right command for the server part, and "git send-pack" or "git upload-pack" would be more appropriate. But I have a hard time understanding how to actually use both commands.

Any ideas?

  • git push & git pull cannot communicate with each other, on the backend `git-receive-pack` and `git-upload-pack` are used. You might also want to look into `git-bundle` because thats a method of distributing git commits using plain binary files – Ferrybig Sep 07 '17 at 09:33
  • This looks like a problem with I/O streams redirections and subshells: while you think that your `(…git {pull|push}…)` will use the indicated FDs, they appears to be not redirected by those `N>` and `M<` redirections which follow them—see [this](https://stackoverflow.com/q/15153158/720999) for example. May be [this](http://tldp.org/LDP/abs/html/process-sub.html) could help. – kostix Sep 07 '17 at 13:36
  • Oh, and you could try asking a general question regarding shell redirection (tagged `bash` `shell` `file-desctiptor` `io-redirection` etc). – kostix Sep 07 '17 at 13:42
  • @Ferrybig: I am already using bundles, but I don't like having more intermediate files than necessary. It's also more work to do, because I have to transfer the bundle first, unbundle it next, and then merge or ff. Also I have to do this for every pushed commit. I really would prefer starting some sort of "git daemon" server on one side of the communication, issuing multiple push or pull commands on the other side as long as the server runs. – Guenther Brunthaler Sep 07 '17 at 14:42
  • Are file descriptors required, or can you do `(cd /repo1; git pull /repo2/.git)` as that's far easier to use (use `strace` to see how it calls `git upload_pack` in the other repo) – Ferrybig Sep 07 '17 at 14:45
  • @kostix: You are right, there is something fishy with the redirections. However, I don't think the redirections themselves are the problem, but rather the fifos involved. I guess I am doing something in the wrong order, and so the fifos block. However, I am not sure what I can do about it. I need those fifos to be connected, or the 2-way data exchange won't work.. – Guenther Brunthaler Sep 07 '17 at 14:57
  • @Ferrybig: I want two unprivileged users to be able to exchange commits via a fifo set up by root for them. Those users share no further access to any files or directory with write acess; they have only that fifo (or rather a pair of them). I have no problems shovling git bundle files through that fifo, but letting git run as a server would be much easier to work with. I probably could use pppd or slip to establish a network link through the fifos somehow, but I want to avoid such a complex setup. The git fd:: mechanism is already there, so why not do something useful with it? – Guenther Brunthaler Sep 07 '17 at 15:14
  • @kostix, 2nd: I have now looked at the linked examples, but unfortunately they use bash-specific features. I want to avoid using any non-POSIX extensions such as process substitution unless absolutely necessary. My scripts are intended to run without modification with BusyBox ash and dash as well as on BSD systems. They should work on any POSIX-compliant box. – Guenther Brunthaler Sep 07 '17 at 15:21

1 Answers1

1

Piping git commits through pipes is easy using git receive-pack and git upload-pack.

Normally git receive-pack and git upload-pack accepts 1 argument, a git directory (the directory containing the objects folder), and then performs a full duplex communication over its stdin/stdout with the remote git push/pull.

Calling git receive-pack command manually is simple:

mkfifo ab && mkfifo ba
# Now I want to push from a to b via the fifos
(git receive-pack b/.git) 1> ba 0< ab &
(cd a && git push fd::8,9 master) 8< ba 9> ab

Same way for git upload-pack:

mkfifo ab && mkfifo ba
# Now I want to push from a to b via the fifos
(git upload-pack a/.git) 1> ab 0< ba &
(cd b && git pull --no-edit fd::8,9 master) 8< ab 9> ba

Take a note that git pull and git push aren't exactly the inverse operations of each other:

  • git push refuses to push by default when the other side has commits it doesn't have by its own (unless -f has given, then it will overwrite`), while pull makes a merge commit
  • git pull may open an editor for the editing of a merge commit, unless the --no-edit flag has been given (a potential security exploit if the editor is vi)
Ferrybig
  • 18,194
  • 6
  • 57
  • 79
  • THANKS a lot! This is exactly what I wanted to know! (Sorry it took my so long to accept your answer. I thought I already did it before, but I must have done something wrong and the status change got lost somehow.) – Guenther Brunthaler Oct 01 '17 at 18:45