12

Is there a way to hook when a git pull happens on the remote (similar to a pre-receive or post-receive). Basically I'd like to be able to cause the remote to commit whatever it has when there is a pull.

In my situation, whatever is live on the remote is an authoritative source which may get modified without a git commit. I want to make sure when I pull I'm always able to get the latest of whatever is live.

Danny
  • 121
  • 1
  • 3
  • 1
    So, you're sending a commit to a remote repo and want the remote repo to commit just before your changes are merged into it? – Felipe Cypriano May 08 '10 at 16:05
  • Not quite. More like this: 1: on remote fileA.txt gets edited 2: on local I run 'git pull remote' What I would like is for the edit to fileA.txt to get commit'ed so that my pull brings down the changes that were made. – Danny May 08 '10 at 16:17
  • Why not edit fileA.txt locally, commit it, and perform the pull on the remote server? Changes should start on the developer's local setup and trickle up to the production environment, not the other way around. – Mathew May 08 '10 at 16:25
  • The remote isn't a production environment, just a different environment. It's a "live" copy of my repo that it exposed over the web with some limited editing ability. The live web based editing is for when I'm need to access or occasionally modify a file and I can't bring down a full repo (like using a friends computer). – Danny May 08 '10 at 20:29

6 Answers6

4

First, to answer your actual question: there are no hooks invoked on the remote side when someone fetches. (When someone pulls, all the remote knows is that they fetched from it - it doesn't know whether they ran git pull, git fetch, git remote update...)

As for your actual situation: I agree with Magnus that it'd be best to simply have commits take place after edits, or failing that, have some sort of periodic task (cronjob?) that checks for modifications and commits if it finds any. If you don't like either of those choices, you're left with streamlining things so that it's quick and easy for you to trigger a commit in the remote repository just before pulling.

Also, I'd suggest not regarding a repository with a work tree as your canonical repository. It's asking for trouble if you ever need to push to it. Instead, you could have a bare canonical repository which your live repository pushes to after committing, and install a post-receive hook in that bare repository to update the live repository when necessary.

mrj
  • 1,571
  • 1
  • 10
  • 7
  • As for your last paragraph, that doesn't solve the problem at all. This can be done with gitolite, but when someone pulls from the bare repo, how do you make it tell the non bare one to commit everything unless the gitolite user has direct privileges to call 'git commit' which might not always be a good idea. Basically what many people need is to be able to provoke a hook on a remote repository with a noop. That's why people think fetch might be good, only to find that there is no pre-fetch hook. I think it might be solved by pushing to a non existing branch... –  Apr 20 '14 at 05:17
  • ... That's ok for something automated like gitolite, but is annoying if humans have to remember that before doing a pull... –  Apr 20 '14 at 05:18
2

Unfortunately git does not natively supply hooks for this, as it is a perfect use-case to want to check something before allowing a pull/fetch.

I don't know if your 'remote' is on a local machine, but if it isn't, have a look at gitolite which has hooks that are meant exactly for this:

From the v2 gitolite docs:

"gl-pre-git" hook

Although git has lots of nice hooks you can tap into, they all run only on a push. There's nothing that runs on a fetch or a clone, and there's no way to run something before git-receive-pack or git-upload-pack, (as the case may be) are invoked.

That's what the gl-pre-git hook is for. If an executable hook called gl-pre-git is present, it will be invoked with the current directory set to repo.git, and with a single argument which will be either R or W depending on what the client is trying to do.

For v3 gitolite, here are the docs about triggers. The documentation is a bit cryptic, but here is how it works:

  1. in ~/.gitolite.rc add (on the global scope):

    PRE_GIT => [ '<pre_git_trigger_script_name>' ]

  2. in the same file look at the line allowing to set LOCAL_CODE and set it to where ever you like

  3. In the directory that you set for LOCAL_CODE, create a subdirectory called 'triggers' and create a script called <pre_git_trigger_script_name> with whatever you want to do at that point... (make sure do to: chmod +x <pre_git_trigger_script_name>

  4. run gitolite setup

  5. test && have a good day

update: Actually using gitolite, I think you could have the pre-git trigger do something like pushing to an unexisting branch and then hook to pre-receive in your non-bare repository to reject the push, but to do git add --all . && git commit -m"autocommit" && push gitolite in the process. This is handy when you don't want to allow the gitolite hosting user privileges to run commands directly in your non-bare repository.

  • "there's no way to run something before git-receive-pack or git-upload-pack" ... except, of course, for just frontending them... it's just code. – jthill Nov 24 '13 at 04:38
0

I have no direct experience with git hooks, and this page may help, but it doesn't look like you're going to be able to do it.

The easier (and better IMO) solution would be to use a repo other than the production environment as the authoritative source. Can you do this? A production environment is very rarely used as the authoritative source because latest and most stable are two very different things...

FYI, I only ever perform a git pull or git status when in a production environment. Any changes are made on my local repo, tested, committed, pushed to github, then pulled down to the production environment.

UPDATE
I should point out that one of the great strengths and features of git is that it is a distributed source control system. As such, there isn't really any such thing as an authoritative source.

Mathew
  • 8,203
  • 6
  • 37
  • 59
  • Maybe authoritative wasn't the proper term, more like it's a "peer" source which is exactly what git promotes. The only problem is that the peer can't commit for itself so I was trying to figure out if git hooks can help it. – Danny May 08 '10 at 20:32
0

I think you can't do this with hooks, for what I understand reading the hooks' doc there's no hook that fits into your requirement.

If I need something like what you want I'd create a script on 'remote' that runs every hour and checks if any file was changes (git status) and commit all (git commit -a -m "Auto commit").

Felipe Cypriano
  • 2,727
  • 22
  • 32
  • Not really possible since the remote is just a file share stored on cloud storage. Thanks though, I'm realizing that this doesn't seem to exist. I have the hooks for when i do a push just not a pull. I guess I'll have to do some kind of empty commit+push. – Danny May 08 '10 at 20:31
  • Try to find a way to locally mount this file storage so you could use your local computer git's command. I'm guessing if could access the cloud storage as a local storage you could do everything directly from your computer. If the cloud storage is just a simple storage that contains your files and happens to have .git directory inside but no Git running it'll be impossible to hook something there. – Felipe Cypriano May 08 '10 at 21:50
0

It's not something I've ever done before, but you can run bash scripts from inside php:

http://www.devx.com/opensource/Article/40785
http://us2.php.net/function.exec

Which should allow you to commit and push a set of changes via a PHP script. Chuck an interface over it or integrate it into your current editing process and you should be good to go.

Mathew
  • 8,203
  • 6
  • 37
  • 59
0

Who/what is editing this file? If it's something being changed when someone changes something on a site, that must be triggered by something, which means you can automate this. When this something happens and the file is saved, there you should trigger the commit. The commit has to be done sometime and it might as well be at that time.

rtn
  • 127,556
  • 20
  • 111
  • 121
  • That assumes that the remote is actually capable of executing a git command. But in my case, it's a file server/shadow copy on skydrive that I want to be able to edit from the web on occasion. – Danny May 17 '11 at 09:35