192

I need to perform some actions (prepare gettext *.mo message files) on my project everytime I run git pull. Is there any suitable git hook, which I could use for this purpose please?

msgre
  • 2,253
  • 3
  • 14
  • 12

4 Answers4

220

The githooks man page is a complete list of hooks. If it's not on there, it doesn't exist.

That said, there is a post-merge hook, and all pulls include a merge, though not all merges are pulls. It's run after merges, and can't affect the outcome. It never gets executed if there were conflicts; you'd have to pick that up with the post-commit hook if it really matters, or invoke it manually.

VivekDev
  • 20,868
  • 27
  • 132
  • 202
Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • Thank you Jefromi, it looks that post-merge is what I am looking for. – msgre Nov 15 '10 at 17:02
  • 46
    @Jefromi "all pulls include a merge" , even if I do a pull --rebase ? – FMaz008 Nov 25 '11 at 14:12
  • 1
    Update for the githook man page, the previous link seems down: http://www.manpagez.com/man/5/githooks/ – FMaz008 Nov 25 '11 at 14:12
  • @FMaz008: All the Git manpage links have been down for a while, since kernel.org has been down. kernel.org has recently come back up, so hopefully the manpage links will start working again. In any case, it's probably not worth trying to find all of them on SO - there are way too many. – Cascabel Nov 25 '11 at 14:27
  • 13
    Also found that merge never executes when running `git pull` if there are no changes to be pulled in (you are already up-to-date). – Kinsa Sep 20 '12 at 20:26
  • 12
    @jbergantine: I suppose I was imprecise in my answer - all pulls that aren't no-ops include a merge. But... in general, if you're trying to take action whenever a merge happens, I don't think you want to take action when someone does a no-op merge. For example, it'd be a waste for the OP to recreate those files if nothing has changed. – Cascabel Sep 20 '12 at 21:46
  • 13
    If you really want to do something every time you pull... you could alias 'git pull' so that you call a script that does the git pull then does something else – Shadow Radiance Jun 20 '14 at 14:21
  • 17
    `git pull` with rebase (either with `--rebase` or with the config `pull.rebase=true`) doesn't include a merge and won't trigger the post-merge hook. For this case you can specify `--no-rebase` to make sure the hook is triggered or make use of the post-rewrite hook. – Victor Schröder Sep 01 '15 at 09:44
  • 2
    @ShadowRadiance: That would have to be a shell alias, not a Git alias since Git doesn't allow overwriting commands with an alias. – Flimm Jan 07 '16 at 16:02
  • 1
    @Flimm thanks for the clarification of my comment - that is indeed what i meant - a bash alias, for example that runs a bash script, that calls git pull and then does whatever you want afterwards – Shadow Radiance Feb 07 '16 at 07:51
  • 1
    @foo "[man page](https://en.wikipedia.org/wiki/Man_page)" is not a typo. It's literally what that page is called, and you can view it on your own machine by running `man githooks`. – Cascabel Jul 26 '17 at 20:33
  • @Jefromi TIL! sorry about that! – Laszlo Jul 27 '17 at 11:23
  • Wouldn't the `post-checkout` hook be better? Yes, it runs even when switching branches, but it certainly runs both on `git pull --merge` and `git pull --rebase`. – mcepl Aug 03 '22 at 11:37
19

post-merge - see https://git-scm.com/docs/githooks#_post_merge for more details of how to use it.

Snowcrash
  • 80,579
  • 89
  • 266
  • 376
1

This approach works for me.

First, add a file named post-merge to /path/to/your_project/.git/hooks/

cd /path/to/your_project/.git/hooks/
touch post-merge

Then, change it's ownership to same as <your_project> folder(this is the same as nginx and php-fpm runner), in my case, I use www:www

sudo chown www:www post-merge

Then change it's file mode to 775(then it can be executed)

sudo chmod 775 post-merge

Then put the snippet below to post-merge. To understand the snippet, see here(actually that's me).

#!/bin/sh

# default owner user
OWNER="www:www"

# changed file permission
PERMISSION="664"

# web repository directory
REPO_DIR="/www/wwwroot/your_project/"

# remote repository
REMOTE_REPO="origin"

# public branch of the remote repository
REMOTE_REPO_BRANCH="master"

cd $REPO_DIR || exit
unset GIT_DIR
files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)"

for file in $files
do
  sudo chown $OWNER $file
  sudo chmod $PERMISSION $file
done

exec git-update-server-info

Everything is done, now, go back to your_project folder

cd /path/to/your_project/

run git pull under your_project folder, remember you must run as root or sudo(I remember sudo)

sudo git pull

Now check the new file that pulled from remote repository, see if its ownership has been changed to www:www(if it was as expected, the ownership of the new pulled file should be changed to www:www).

This approach is much better than sudo chown -R www:www /www/wwwroot/your_project/, because it only change the new file's ownership, not all of then! Say I just pulled 2 new file, if you change the whole folder's ownership, it's costs more time and server resources(cpu usage, memory usage...), that's totally unnecessary.

Willis
  • 599
  • 3
  • 25
0

post-merge is the closest to a true post-pull hook, as the other answers point out, but consider adding a post-checkout hook if you want to catch the changes post-merge misses.

From the docs:

This hook is invoked when a git-checkout or git-switch is run after having updated the worktree.

So anytime your working copy changes, because you are "switching what you are working on" / anyone on your team has worked on, the hook runs.

A practical example where the behavior differs is that post-merge doesn't trigger when you jump back to (check out a commit from) the past (because there is no merge)

Simon
  • 1,172
  • 12
  • 21
  • I just tried it out in git 2.25.1 - ipost-checkout works when I jump back or check out another branch, like you said, but it seems post-chechout won't trigger on a pull. – mit Oct 26 '22 at 20:58
  • @mit That's why I wouldn't consider this the best answer, but for practical applications triggering a script on any external change is a use-case, and this answer should help with that. I will update the wording, since "Alternative" seems to be definitely wrong thou. – Simon Oct 27 '22 at 09:28
  • 1
    another caveat here is that while a "run on any changes to the git managed files" hook would be Really Nice, the combination of post-checkout and post-merge does not actually accomplish that. For example, git reset --hard HEAD^ does not run either hook (by design). – rdm Dec 02 '22 at 14:19