Search code examples
gitrepositorydvcsgit-push

git: Simple solution for pushing between working copies


What I want to do: On my (ssh remotely accessible) university machine I work on a project which I have put under git source control (git init, then git commit -a after every change, all works fine). Now I want to want to work on that project on my private machine at home. Should be easy, since git is a distributed vcs, right?

I read the git tutorial, which suggests to do a git pull at university to get the changes done at home. That won't work, since my machine at home is not remotely accessible. So I thought that I'd do a git push at home. That works, but it's complicated (requires git reset at university afterwards, etc.), since non-bare repositories are not designed for pushing.

Question 1: Is there an easier way than adding a additional bare repository to my setup (which would mean that I had: (1) the "main" bare repository, (2) the university working copy, (3) the home working copy)?
<Rant>If I really need that setup, I could have stayed with SVN.</Rant>

Question 2: If that setup is really needed, how do I create that bare repository (git clone --bare, I guess) and make it the "main" repository, i.e., tell the working copies that git push is supposed to go there.

PS: I know that there's a post-receive hook floating around that allows you to push into non-bare repositories. I tried it, but it didn't work well since the git version on the university machine is quite old (1.5.5.6) and misses some commands used by the hook. Updating is not an option, and I'd prefer a solution without third-party scripts anyway.


Solution

  • You really shouldn't push to the checked out branch as it effectively pulls the rug from under the remote working copy. It's then difficult to work out if the working tree is modified because the branch head has moved or if there were also local changes which would be lost by a reset --hard.

    The simplest thing to do is to push to a different branch. You can then merge this into the working copy's checkout out branch (or rebase the local branch onto it) when you have access to the remote machine and need to work on it.

    From home:

    git push origin HEAD:from-home
    

    From 'work':

    git merge from-home
    

    You can set up your config to default to a particular push refspec.

    e.g.

    git config remote.origin.push +master:from-home
    

    A bare repository is often more natural. You can either clone it from an existing repository or, what I usually do, initialize a new repository and push the master branch that I want to it from an existing repository.

    Better still, if you're going to use working copies at each location, is to use this trick to directly modify the remote's remotes, rather than a speically renamed branch.

    So, on origin, create a remote called 'home' -- you obviously can't fetch from it because of your network configuration. That doesn't matter.

    On home, tell it, "When I push to origin, have it update the origin's remote named home:

    git config remote.origin.push +master:home/master
    

    Now, things get really slick. From home, run git push origin, and go to origin, and run git status or git branch -a -v -- What you will see is something like: "master is behind home/master by 3 commits and can be fast forwarded."

    In other words, using home to push a change to origin's remote named home, is functionally the same as using origin to pull from home.

    The one downside here is that you'll need to continually do new git config settings as you create additional branches on home. That's the overhead you pay for your network setup. Thankfully, it's simple and only happens once per branch create.