26

I've setup my environment so I can push to a remote bare repository. I used these commands to set up the remote repository:

$ mkdir ~/website.git && cd ~/website.git $ git init --bare 

And

$ cat > hooks/post-receive #!/bin/sh GIT_WORK_TREE=/var/www/website git checkout -f $ chmod +x hooks/post-receive 

And on my local environment:

$ git remote add web ssh://website.com/home/website.git $ git push web +master:refs/heads/master 

Now I can deploy to this remote using git push web, and everything works great..

The problem: Submodules

I have a few submodules on my project that aren't getting initialized/updated at the remote repository. I can't run git submodule update on the bare because it's bare, and I can't run it on the /var/www/website folder because it's just a copy of the files and not a git repo.

3 Answers 3

14

I figured out another solution which looks rather clean to me. Just give git all the info it needs to perform the submodule stuff:

$ cd /path/to/your/git_work_tree $ git --git-dir=/path/to/your/bare_repo.git --work-tree=. submodule init $ git --git-dir=/path/to/your/bare_repo.git --work-tree=. submodule update 
Sign up to request clarification or add additional context in comments.

1 Comment

How can you automate this so that it does this after each push deployment?
12

One possible way might be:

In other words:
Pull from the bare repo instead of trying to checkout from a bare repo: a non-bare repo should be able then to accommodate the git submodule update step.

An example script may look like

#!/bin/sh # Get the latest code cd /path/to/bare/repo # Set git variables GIT_WORK_TREE=/var/www/website GIT_DIR=/var/www/website/.git # Go to website and pull cd /var/www/website git pull /path/to/bare/repo git submodule update --init --recursive # Run additional build stuff here 

8 Comments

Can you provide an example for the post-receive / post-update script (although this answer is pretty old)? Every time I try to push I gets errors.
remote: fatal: Not a git repository: '/var/www/website'
@raveN is there a .git folder in /var/www/website?
Is GIT_DIR set to /var/ww/website/.git and GIT_WORK_TREE to /var/ww/website/?
@johnshumon Right! I have removed the unnecessary step. Not sure what I was thinking about when I write this answer 6 years ago...
|
6

I stumbled across this thread two days ago while I struggled with the same issue. After finally arriving at a nice, tidy solution, I wrote an article about it here:

Git push with submodules: a how-to guide

I realized that if I'm going to push to a bare repo, only to use post-receive to pull into a non-bare repo, I might as well just keep it simple and push directly to the non-bare repository. This is a clear case where the "best practice" of only pushing to a bare repo is only adding complexity.

In case of link rot, I'll paste my solution here, skipping over the bits where I run into all of the same problems that I'm sure you did.


First, let’s create a universal post-receive hook, one that I won’t need to change on a per-repository basis:

[aaron@aaronadams]$ cat > /usr/local/share/git-core/templates/hooks/post-receive.sample #!/bin/sh # # An example hook script to update the working tree, including its # submodules, after receiving a push. # # This hook requires core.worktree to be explicitly set, and # receive.denyCurrentBranch to be set to false. # # To enable this hook, rename this file to "post-receive". # Read standard input or hook will fail while read oldrev newrev refname do : done # Unset GIT_DIR or the universe will implode unset GIT_DIR # Change directory to the working tree; exit on failure cd `git config --get core.worktree` || exit # Force checkout git checkout --force # Force update submodules git submodule update --init --recursive --force [aaron@aaronadams]$ chmod +x /usr/local/share/git-core/templates/hooks/post-receive.sample 

Now let’s go ahead and break all the rules.

We’re going to initialize a non-bare Git repository, right in our website directory; make sure it can receive from git push; explicitly set its working tree to its parent directory; and enable our hook we just created.

[aaron@aaronadams]$ cd /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca [aaron@aaronadams]$ git init && git config --bool receive.denyCurrentBranch false && git config --path core.worktree ../ && mv .git/hooks/post-receive.sample .git/hooks/post-receive Initialized empty Git repository in /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca/.git/ 

Finally, on our local machine, we’ll change our remote to reflect the location of our new repository, and push.

[aaron@aaronadams]$ git remote set-url staging [email protected]:sites/staging.aaronadams.ca [aaron@aaronadams]$ git push staging master remote: Submodule 'codeigniter' (git://github.com/EllisLab/CodeIgniter.git) registered for path 'codeigniter' remote: Cloning into 'codeigniter'... remote: Submodule path 'codeigniter': checked out 'fd24adf31255822d6aa9a5d2dce9010ad2ee4cf0' To [email protected]:sites/staging.aaronadams.ca * [new branch] master -> master 

Holy crap, it worked!

Not only is this method compatible with submodules, it also requires just one command to set up a new remote repository (which, okay, consists of four commands). It also keeps the repository and the working tree in the same place; and with no absolute paths required in our configuration or hook files, it’s now completely portable as well.


I hope this answer helps somebody as much as everyone else's Stack Exchange posts helped me over the last two days!

8 Comments

I tried your article but after the first push it breaks. I notice it is not storing files in the objects directory. The error is: error: unable to create temporary sha1 filename ./objects/9e: No such file or directory. I believe it should be .git/objects/9e. Any ideas? This is very close
Interesting. It sounds like your configuration maybe ended up a little different from mine in the end – but hey, as long as it's working!
This will likely cause problems if multiple programmers are deploying to the same website. See "all about bare repos". VonC's solution avoids this hiccup.
@jrhorn424 Indeed, there's lots wrong with the above solution; I've learned plenty since I wrote it, the most important being that submodules create more problems than they solve. I'd strongly recommend switching to the submodule-free solution I've documented here: stackoverflow.com/questions/14656047/…
@jrhorn424 Indeed, my original blog post documents all of the pains I encountered in attempting to implement that solution myself.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.