39

I cloned the GHC (Glasgow Haskell Compiler) repository. In order to build the compiler, you need several libraries, all of them are available as git repositories too. In order to ease ones live, the GHC hackers included a script sync-all that, when executed, updates all the dependent repositories.

Now to my question: How can I make git execute ./sync-all pull after I did a git pull automatically? I heard something about using hooks, but I don't really know, what I have to do.

fuz
  • 88,405
  • 25
  • 200
  • 352

2 Answers2

31

If you need to execute a script after a git pull on the client side (your machine), then a there is no reliable solution.

The post-merge client-side hook (mentioned here) won't be triggered by every pull (for instance, not in a pull rebase, not in case of fast-forward merge)

So an alias wrapping both commands remains a possible workaround.


Original answer (2011)

If you need that on the server side, where you would checkout the bare repo and pull from a working tree (on the server) after each push to a bare repo (on the server):

A post-receive or post-update hook is generally used for this kind of task, executed after each push.
The difference between the post-receive and post-update hooks is in the arguments: a post-receive will get both the old and the new values of all the refs in addition to their names.

The missing piece is: where that hook executes itself?

The blog post "Missing git hooks documentation" from (a great) SO contributor Mark Longair sheds some light on this:

the current working directory will be the git directory.

  • So, if this is a bare repository called “/src/git/test.git/”, that will be the current working directory – if this is a non-bare repository and the top level of the working tree is “/home/mark/test/” then the current working directory will be “/home/mark/test/.git/

Chris Johnsen details in his SO answer: "If –-git-dir or GIT_DIR are specified but none of -–work-tree, GIT_WORK_TREE and core.worktree is specified, the current working directory is regarded as the top directory of your working tree."

In other words, your working tree will also be the current directory (the .git directory), which almost certainly isn’t what you want.

Make sure your hook/post-receive script, once created and made executable, sets the GIT_WORK_TREE at the right path, in order for your ./sync-all pull to be executed in the right directory (i.e. not "xxx.git" one).

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 9
    post-receive and post-update hooks run on the remote repo after a git push. This doesn't help with running it on the local repo after a git pull. – decocijo Jul 20 '12 at 08:07
  • 1
    @decocijo yes, the idea is to *push* to a bare repo, which will trigger a post-receive hook and go to a non-bare repo, making the `git pull` there. – VonC Jul 20 '12 at 12:20
  • This is not the answer for running a command after pull. post-receive or post-update run after a push to that repository. – Onur Demir Aug 15 '18 at 14:22
16

When you run git pull, git actually does a fetch followed by a merge. This means you can use the post-merge hook to execute a script when a pull is completed.

To set this up you just need to create an executable script in your repository's .git/hooks/ directory called post-merge.

Note that this script will not be run if the merge fails due to conflicts.

nullability
  • 10,545
  • 3
  • 45
  • 63
  • 4
    This won't work for `git fetch` however. Also, one could do `git pull --rebase` so you'd have to add a hook for `post-rewrite` too. But even then, you won't be able to differentiate between a standalone merge/rebase and one that comes after a pull... – Ohad Schneider Feb 14 '16 at 15:42
  • Depending on the branch config i.e. if it's configured to rebase or merge, you can either have a pre-rebase or post-merge respectively. – solstice333 Mar 14 '16 at 11:42