ยปGit Tricks

How to interact with a repo on an untrusted machine

Let's say you have a Git repo that you use on a machine you don't trust particularly well, where "untrusted" in particular means you don't want the machine to have any credentials for accessing your master repo. This means that the typical SSH workflow for pulling/pushing from the client is unavailable.

There is a non-hacky way of doing this: set up a bare repo on that remote machine that you push changes to from your trusted machine (outbound SSH) and pull changes from on your untrusted machine (local file access).

But let's say you don't want this extra bare repo. It turns out there is a hacky way of doing this by specifying a different-than-usual set of refspecs in a few configurations.

Assume:

Then:

  1. On the trusted machine, edit /path/to/trusted/repo/.git/config to add a remote untrusted that both pushes to and pulls from a set of remote refs. I use remote self for this:

     [remote "untrusted"]
         url = untrusted:/path/to/untrusted/repo
         fetch = +refs/heads/self/*:refs/remotes/untrusted/*
         push = +refs/heads/*:refs/remotes/self/*
  2. On the untrusted machine, edit /path/to/untrusted/repo/.git/config to add a remote that is actually the same repo, and which pushes to and pulls from the same remote ref:

     [remote "self"]
         url = .
         fetch = +refs/remotes/self/*:refs/remotes/self/*
         push = +refs/heads/*:refs/remotes/self/*
  3. Set up local branch(es) on the untrusted repo to track the corresponding self heads:

     [branch "master"]
         remote = self
         merge = refs/remotes/self/master

Now when you git push on the untrusted machine, the self remote heads in the local repo will be updated to take the new commits; and when you git fetch untrusted on the trusted machine, it will SSH over and pull down whatever you pushed to those heads. Similarly, when you git push untrusted from the trusted machine, it will SSH over and (depending on your push.default settings) push the latest state for your local heads into the self remote heads; and when you git pull on the untrusted machine, it will update the local branch with whatever you pushed.

It's like having a separate bare repository on the untrusted machine without the clutter.