One can use ssh -R
to open a reverse tunnel from a remote back to your local machine, allowing one to use git to clone from your local machine to the remote server.
One feature/drawback of git is that git clone
is a pull-only operation: it must be able to see a remote to clone it. This is fine in 99% of use cases, but sometimes, one wishes it were possible to “push clone” a new repository, e.g. from a laptop to a server.
However, by using the reverse tunneling feature of ssh, we can achieve this behaviour in a round-about way.
Specifically:
# Open an ssh connection to your server as usual, as well as a "reverse
# tunnel", mapping localhost:22222 on the server to localhost:22 on the client.
ssh -R 22222:localhost:22 user@server-hostname
cd /path/to/where/we/want/our/gitrepo
# Now, we clone as per normal, using our reverse tunnel back to the laptop as
# the remote server.
git clone ssh://${LAPTOP_USERNAME}@localhost:22222/path/to/repo/on/laptop
cd ${new_repo}
# we should remove the 'origin' remote, as it will depend on the (soon to be
# removed) reverse tunnel back to our laptop.
git remote rm origin
# OPTIONAL: allow pushes direct to the checked out files (see note below)
git config --set receive.denyCurrentBranch updateInstead
# Close the ssh session, and the remote tunnel. next time you ssh, you don't
# need to use the remote tunnel.
exit
# We now have a clone of our repo on the remote server. You can now add this as
# a remote as per normal on the original laptop copy of the repo.
Notes:
- Your laptop (or the client end of the original ssh connection) must be running sshd, and you must be able to log in (just run
ssh ${laptop_username}@localhost
on your laptop to check). If not, enable it. - You may need to adjust the port (22222) if there is already something running on this port on the server. You should see ssh complain if that’s the case.
- If you’re using this primarily as a backup of the local git repository, you’ll probably want to investigate the
receive.denyCurrentBranch
git config option. Specifically, you’ll probably want to set it toupdateInstead
, and read the info on push hooks in the git docs.