jb. jb. - 28 days ago 17
Git Question

How can I push and automatically update working copy of my non-bare remote git repository?

See also this related question, it has most current answer: http://stackoverflow.com/a/28262104/7918.

How can I push and automatically update working copy of my non-bare remote git repository?

Before git people will say that "this is unsafe", please let me explain why in my case this would work. I have repository

foo
in on machines
A
and
B
.
A
happens to be my local machine,
B
is on a supercomputing grid. Project is normally developed on
A
(with some testing) then pushed to
B
for more testing and to submit jobs to the grid. Both repositories have working directories. Repositories both on
A
and
B
are private and tied to my user account.

For now git flow is like that:


  1. Commit on
    A

  2. Push on
    A

  3. Fetch on
    B

  4. Merge on
    B



I'd rather omit steps 3 and 4. That is: I'd like to have remote non-bare repository updated on push, if changes from
A
can be automatically safely merged (that is: when merge is fast-forward, and working dir on
B
is clean).

First solution would be to drop repository on
B
and just use
rsync
to sync code, but this is undesirable as sometimes I do some changes directly on
B
, and don't want these changes to be overriden easily.

Second soultion would be to install this patch, which even got merged to mysysgit (but not git proper). This patch adds
updateInstead
value to the
receive.denyCurrentBranch
git option. This is viable, but I'd rather not patch git on many machines.

Third solution (taken from here) would involve having three git repositories:
A
,
B'
,
B
. Where
B'
is bare and uses hooks to sync
A
and
B
. This is really straightforward, but I guess having three repositories would likely increase fragility of whole system.

Last solution would be preffered: that is to use hooks on repository
B
to automatically merge pushed changes to working copy. Everyone says it is straightforward to do this, but I guess that my knowledge of git internals is to weak to patch something sensible. I did some work on this but nothing that actually works.

What I'm looking for:


  • Hook-based solution that would automatically merge remote non-bare repo on push. That does not: require me to recompile git, and create additional repositories.


jb. jb.
Answer

Thanks for both the answers, I think I just created python hook script that does what I need. Whole script is a little bit too long to post here, so here is a gist. I guess that it is well documented and can stand on it's own.

Since most people will probably roll your own hooks there are gothas which took me some time to understand:

  • You can't have a hook that will both be able to merge and update working directory and reject push on errors. You need to install both uptate/receive (to do validation) and post-update/post-receive do update working dir.
  • You really can't create a hook that on push to branch foo will update working copy if foo is checked out. Git people just don't like it. Or maybe you can using two hooks as mentioned earlier.
  • To merge you'll need to cd to working copy directory, hooks are executed inside GIT_DIR, so you'll need to figure out where to go from there. If you'll call git merge foo without cd'ing to working copy it will not be updated (at least it didn't work on git 2.0.1).