Force git to run post-receive hook, even if everything is "up-to-date"

Solution 1:

Use '--allow-empty'

After the initial push replacing the script, you can do this :

git commit --allow-empty -m 'push to execute post-receive'

The --allow-empty flag overrides git's default behavior of preventing you from making a commit when there are no changes.

Use an alias and make your life even easier

Add the following to ~/.gitconfig

[alias]
    pushpr = "!f() { git push origin master;git commit --allow-empty -m 'push to execute post-receive';git push origin master; }; f"

Now Just do git pushpr

git pushpr

This will push any changes to master, which in your case will trigger your post receive replacement script, then it will push again (using the --allow-empty flag) which will then execute your updated post-receive script.

Solution 2:

I know this probably going to be considered "dangerous" but I like to live on the edge.

I just delete the remote branch and then push it again. Make sure your local branch is up-to-date first to limit the chance of losing stuff.

So if I want to trigger post-receive, in my case to get the testing branch to provision, all I do is:

$ git push origin :testing
$ git push origin testing

Don't accept this as the answer though. It's more of a just FYI thing.

Solution 3:

If you want to avoid making a fake new commit, you can simply use

git commit --amend --no-edit

This will modify the last commit record and you will be able to use git push -f (assuming from your answer that you're fine with the overwrite).

  • convenient: it doesn't create an extra commit
  • good: it doesn't use explicit path for the hook in the remote repo
  • bad: you overwrite history, which is fine in your use case, but shouldn't be used in a shared repository

I use this command relatively often to fix something in the last commit before pushing, so I made an alias for it:

git config --global alias.amend 'commit --amend --no-edit'

Now I can use it directly for the use case as yours (git amend), or

  • to add (all) modified files to the last commit: git amend -a
  • to modify the message: git amend -m 'better message'

Solution 4:

I'm afraid you have to ssh to the server and run the hook script manually. git push doesn't make the server run the pre-push, pre-receive and post-receive hooks if there was nothing added (i.e. when git prints Everything up-to-date).

The rest of the answer is about version-tracking the post-receive hook, so you can modify it without sshing to the server.

Add a shell script named do-post-receive to the local repository:

$ ls -ld .git
$ echo 'echo "Hello, World!"' >do-post-receive
$ git add do-post-receive
$ git commit do-post-receive -m 'added do-post-receive'

Replace your hooks/post-receive hook on the server with:

#! /bin/sh
while read OLDID NEWID BRANCH; do
  test "$BRANCH" = refs/heads/master && eval "$(git show master:do-post-receive)"
done

(Make sure to chmod 755 hooks/post-receive on the server.)

Push your changes from the local repository to the server, and watch your do-post-receive code run:

$ git push origin master
...
remote: Hello, World!
...

Solution 5:

I tried empty commits and delete upload branch.

But what about a direct ssh command:

ssh your_host /path/to/your_repo/hooks/post-receive