<p>Based on your comment that you get an error saying Craft is not installed, to me that suggests the bash script does not have access to your environment variables, (this can also be a problem when running cron jobs).</p>

<p>To remedy this, create an env text file to <code>export</code> all the same values as those in your production env variables. For this example name it something like .env_cli.txt and save it in your site in the same place as .env-example if you have one. Add it to your .gitignore too. Syntax should look something like this:</p>

<pre><code>export ENVIRONMENT="live"
export SITE_URL="https://www.example.com"
export DB_DRIVER="mysql"
export DB_SERVER="123.456.789.10"
export DB_USER="aaa"
export DB_PASSWORD="bbb"
export DB_DATABASE="ccc"
export SECURITY_KEY="ddd"
export DB_TABLE_PREFIX="craft_"
export SOME_CUSTOM_VAR_YOU_MIGHT_HAVE="something"
</code></pre>

<p>Then in your git hook, you can use a leading <code>.</code> to "<a href="https://ss64.com/bash/source.html" rel="nofollow noreferrer">source</a>" that env file (basically meaning to suck in and consume all those exported vars), and then run your command(s) afterwards like this:</p>

<pre><code>. /path/to/your/env-file/.env_cli.txt &amp;&amp; /path/to/craft/./craft project-config/sync &amp;&amp; /path/to/craft/./craft clear-caches/all &amp;&amp; /path/to/craft/composer update
</code></pre>

<p>You could of course stick with relative paths to make it shorter, I just tend to use absolute paths for more certainty.</p>

CC BY-SA 4.0
2020-03-16T02:41:03.880Z
I added `. /home/pblog/pb-repo/.env_cli.txt && /home/pblog/staging/./craft project-config/sync && /home/pblog/staging/./craft clear-caches/all && /home/pblog/staging/composer update >> /home/pblog/pb-repo/git-hooks.log` to the end of the hook file and when I visited the CP, I didn't get the warning about applying config changes (like I was before). But also, Craft hadn't been updated to the same version as my local, and the `git-hooks.log` file I created didn't get updated either. So it seems it ran `project-config/sync` but not the rest.
Tyssen
CC BY-SA 4.0
2020-03-16T09:13:01.697Z
I think you'll need to repeat the `>> /home/pblog/pb-repo/git-hooks.log` after each command in order to log the output. If a command doesn't succeed it won't progress past the `&&` to the next command, so your logging won't catch errors.
James Smith
CC BY-SA 4.0
2020-03-17T00:09:40.287Z
Thanks. Everything seems to be working now except for this: `. /home/pblog/pb-repo/.env_cli.txt && /home/pblog/staging/composer update >> /home/pblog/pb-repo/git-hooks.log` which is giving me this error `PHP Fatal error:  require_once(): Failed opening required '/home/pblog/pb-repo/vendor/autoload.php' (include_path='.:/opt/alt/php70/usr/share/pear') in /home/pblog/pb-repo/craft on line 12` The path is correct though, `autoload.php` does exist there.
Tyssen
CC BY-SA 4.0
2020-03-17T12:25:27.633Z
Sounds like maybe a permissions issue remains. I'd first try executing that command as the same user as when you successfully ran it manually. You can temporarily switch users with `sudo -u username` before a command, but this assumes that the user running the command has permission to use sudo, so you might also need to add them to the `sudoers` file and specify which commands they can run. E.g. https://serverfault.com/questions/269359/allow-user-git-to-run-git-pull-as-www-data-via-sudo/269363
James Smith
CC BY-SA 4.0
2020-03-17T23:53:35.197Z
Adding `sudo -u username` to the beginning of the `composer update` command made the error go away but it's also still not executing, as no updates are being made. The log file just shows the successful output of running `project-config/sync` and `clear-caches`
Tyssen
CC BY-SA 4.0
2020-03-17T23:54:12.660Z
By the way, thanks for all your help so far. :)
Tyssen
CC BY-SA 4.0
2020-03-18T10:37:16.880Z
Hm, curious. Maybe instead of `/home/pblog/staging/composer update`, try cd-ing into the directory first: `cd /home/pblog/staging && sudo -u someoneelse composer update`
James Smith
CC BY-SA 4.0
2020-03-18T23:41:54.957Z
Unfortunately, got the same result. No errors, but no update either.
Tyssen
CC BY-SA 4.0
2020-03-13T10:04:06.327Z
2020-03-13T10:04:06.327Z
James Smith
<p>Late to the party and I can't really help on the git hook code per se.</p>
<p>But, for those who like me found this as they are looking how to automate their deployments, know that you should use <code>composer install --no-interaction</code> and not <code>composer update</code>. This ensure that the components installed will be exactly the same as your local environment.</p>
<p>This error explains why Tyssen had a different Craft version once his script was working.</p>

CC BY-SA 4.0
2023-09-26T09:05:45.503Z
2023-09-26T09:05:45.503Z
fdelaneau
<p>I site I'm working on uses a <code>post-receive</code> git hook for deploying changes to the server.</p>

<p>At the moment, it looks like this:</p>

<pre><code>#!/bin/sh

# default cpanel stuff
branch=$(/usr/local/cpanel/3rdparty/bin/git branch | awk '$1 == "*"{print $2}')
while read oldrev newrev ref
do
  if [ "x$ref" == "xrefs/heads/$branch" ]
  then
    echo "Recieved update on checked-out branch, queueing deployment."
    (cd .. ; /usr/bin/uapi VersionControlDeployment create repository_root=$PWD)
  fi

  branch=`echo $ref | cut -d/ -f3`

  cd ../
  # run from dir outside of .git
  # unset git dir because git ugh https://stackoverflow.com/a/10513684
  unset GIT_DIR

  if [ "master" == "$branch" ]; then
    # echo this is master
    # create new working tree in the desired directory
    git --work-tree=../prod-test checkout -f $branch
  fi

  if [ "develop" == "$branch" ]; then
    # echo this is develop
    git --work-tree=../staging checkout -f $branch
  fi

done &lt; /dev/stdin
</code></pre>

<p>That works fine. I push from my local and the changes get deployed to staging.</p>

<p>But I want project config and plugin update changes to be automatically applied rather than having to visit the CP and click the sync changes button.</p>

<p>I've seen elsewhere that the way to do that is to run</p>

<pre><code>  ./craft project-config/sync
  ./craft clear-caches/all
  composer update
</code></pre>

<p>so I thought I could add it to the hook, just above <code>done &lt; /dev/stdin</code> but it doesn't work, I still have to manually update.</p>

<p>Has anyone else done something like this before?</p>

CC BY-SA 4.0
2020-03-11T11:20:05.510Z
My guess is that you need to `cd` into the right directory where the `craft` script is located. Depending on your server settings you may also need to run it as a different user with `sudo -u someone-else`. What happens when you run the command manually?
James Smith
CC BY-SA 4.0
2020-03-12T00:05:34.000Z
I can run the commands manually OK after SSHing in to the server. I thought CDing up one level was the right directory because that's where the files get checked out to.
Tyssen
CC BY-SA 4.0
2020-03-12T09:47:04.307Z
I'd probably first look to log the output of those commands somewhere, which will hopefully give you some kind of error to work with. e.g. `./craft project-config/sync >> git-hooks-log-file.txt`
James Smith
CC BY-SA 4.0
2020-03-13T01:43:45.013Z
I did that and it's telling me that Craft isn't installed yet which would probably be because it's trying to execute the command from the wrong directory. But the thing is, it created the log file in the same directory as Craft is installed so presumably it's executing the commands from the same directory it was creating the log file in.
Tyssen
<deployment><projectconfig><git><project.yaml>
Applying project config changes with post-receive git hook
# Applying project config changes with post-receive git hook

(Asked by: username_0 on 2020-03-11)

I site I'm working on uses a post-receive git hook for deploying changes to the server.
At the moment, it looks like this:
#!/bin/sh

# default cpanel stuff
branch=$(/usr/local/cpanel/3rdparty/bin/git branch | awk '$1 == "*"{print $2}')
while read oldrev newrev ref
do
  if [ "x$ref" == "xrefs/heads/$branch" ]
  then
    echo "Recieved update on checked-out branch, queueing deployment."
    (cd .. ; /usr/bin/uapi VersionControlDeployment create repository_root=$PWD)
  fi

  branch=`echo $ref | cut -d/ -f3`

  cd ../
  # run from dir outside of .git
  # unset git dir because git ugh https://stackoverflow.com/a/10513684
  unset GIT_DIR

  if [ "master" == "$branch" ]; then
    # echo this is master
    # create new working tree in the desired directory
    git --work-tree=../prod-test checkout -f $branch
  fi

  if [ "develop" == "$branch" ]; then
    # echo this is develop
    git --work-tree=../staging checkout -f $branch
  fi

done < /dev/stdin

That works fine. I push from my local and the changes get deployed to staging.
But I want project config and plugin update changes to be automatically applied rather than having to visit the CP and click the sync changes button.
I've seen elsewhere that the way to do that is to run
  ./craft project-config/sync
  ./craft clear-caches/all
  composer update

so I thought I could add it to the hook, just above done < /dev/stdin but it doesn't work, I still have to manually update.
Has anyone else done something like this before?

**Tags:** deployment, projectconfig, git, project.yaml

> **Comments:**
> **username_1**: My guess is that you need to `cd` into the right directory where the `craft` script is located. Depending on your server settings you may also need to run it as a different user with `sudo -u someone-else`. What happens when you run the command manually?  
> **username_0**: I can run the commands manually OK after SSHing in to the server. I thought CDing up one level was the right directory because that's where the files get checked out to.  
> **username_1**: I'd probably first look to log the output of those commands somewhere, which will hopefully give you some kind of error to work with. e.g. `./craft project-config/sync >> git-hooks-log-file.txt`  
> **username_0**: I did that and it's telling me that Craft isn't installed yet which would probably be because it's trying to execute the command from the wrong directory. But the thing is, it created the log file in the same directory as Craft is installed so presumably it's executing the commands from the same directory it was creating the log file in.  

---

## 2 answers

### Answer by username_1 on 2020-03-13. Score: 2

Based on your comment that you get an error saying Craft is not installed, to me that suggests the bash script does not have access to your environment variables, (this can also be a problem when running cron jobs).
To remedy this, create an env text file to export all the same values as those in your production env variables. For this example name it something like .env_cli.txt and save it in your site in the same place as .env-example if you have one. Add it to your .gitignore too. Syntax should look something like this:
export ENVIRONMENT="live"
export SITE_URL="https://www.example.com"
export DB_DRIVER="mysql"
export DB_SERVER="123.456.789.10"
export DB_USER="aaa"
export DB_PASSWORD="bbb"
export DB_DATABASE="ccc"
export SECURITY_KEY="ddd"
export DB_TABLE_PREFIX="craft_"
export SOME_CUSTOM_VAR_YOU_MIGHT_HAVE="something"

Then in your git hook, you can use a leading . to "source" that env file (basically meaning to suck in and consume all those exported vars), and then run your command(s) afterwards like this:
. /path/to/your/env-file/.env_cli.txt && /path/to/craft/./craft project-config/sync && /path/to/craft/./craft clear-caches/all && /path/to/craft/composer update

You could of course stick with relative paths to make it shorter, I just tend to use absolute paths for more certainty.

> **Comments:**
> **username_0**: I added `. /home/pblog/pb-repo/.env_cli.txt && /home/pblog/staging/./craft project-config/sync && /home/pblog/staging/./craft clear-caches/all && /home/pblog/staging/composer update >> /home/pblog/pb-repo/git-hooks.log` to the end of the hook file and when I visited the CP, I didn't get the warning about applying config changes (like I was before). But also, Craft hadn't been updated to the same version as my local, and the `git-hooks.log` file I created didn't get updated either. So it seems it ran `project-config/sync` but not the rest.  
> **username_1**: I think you'll need to repeat the `>> /home/pblog/pb-repo/git-hooks.log` after each command in order to log the output. If a command doesn't succeed it won't progress past the `&&` to the next command, so your logging won't catch errors.  
> **username_0**: Thanks. Everything seems to be working now except for this: `. /home/pblog/pb-repo/.env_cli.txt && /home/pblog/staging/composer update >> /home/pblog/pb-repo/git-hooks.log` which is giving me this error `PHP Fatal error:  require_once(): Failed opening required '/home/pblog/pb-repo/vendor/autoload.php' (include_path='.:/opt/alt/php70/usr/share/pear') in /home/pblog/pb-repo/craft on line 12` The path is correct though, `autoload.php` does exist there.  
> **username_1**: Sounds like maybe a permissions issue remains. I'd first try executing that command as the same user as when you successfully ran it manually. You can temporarily switch users with `sudo -u username` before a command, but this assumes that the user running the command has permission to use sudo, so you might also need to add them to the `sudoers` file and specify which commands they can run. E.g. https://serverfault.com/questions/269359/allow-user-git-to-run-git-pull-as-www-data-via-sudo/269363  
> **username_0**: Adding `sudo -u username` to the beginning of the `composer update` command made the error go away but it's also still not executing, as no updates are being made. The log file just shows the successful output of running `project-config/sync` and `clear-caches`  
> **username_0**: By the way, thanks for all your help so far. :)  
> **username_1**: Hm, curious. Maybe instead of `/home/pblog/staging/composer update`, try cd-ing into the directory first: `cd /home/pblog/staging && sudo -u someoneelse composer update`  
> **username_0**: Unfortunately, got the same result. No errors, but no update either.  

---

### Answer by username_2 on 2023-09-26. Score: 0

Late to the party and I can't really help on the git hook code per se.

But, for those who like me found this as they are looking how to automate their deployments, know that you should use `composer install --no-interaction` and not `composer update`. This ensure that the components installed will be exactly the same as your local environment.

This error explains why username_0 had a different Craft version once his script was working.


---

