Hell0
Hell0

Reputation: 349

git push isn't syncing worktree directory

I'm working on a locale repository $HOME/some_git_repo Now, i must do git checkout on the server side, everytime i need to push anything updated. (i can handle that).

The problem is that isn't synchronizing anything in the /var/www/some_git_repo, on the server side (remote). That means the hooks/post_receive script isn't doing their work

scope:

# post-receive  -- script
git --work-tree='/var/www/some_git_repo' --git-dir='/var/repo/some_git_repo.git'

Upvotes: 0

Views: 76

Answers (2)

Hell0
Hell0

Reputation: 349

Well, this response is not the preferible solution, but it resolve the problem, by updating the working-tree with a simple executable script:

rsync -arv --exclude=something_tobe_excluded \
  --progress repo_source-dir working_tree

Every file/directory_path, must be specified as a single argument. (on the exclude variable).

Upvotes: 0

torek
torek

Reputation: 489628

TL;DR summary: add a #! line at the top

I assume your post-receive script is in fact just the single line:

git --work-tree=/var/www/some_git_repo --git-dir=/var/repo/some_git_repo.git checkout -f

(I note that this, from your comment, is slightly different from what was in your original posting, having checkout -f at the end of the line; I've also removed some unnecessary quote marks, one of which was missing in the comment version).

Your OS also appears to be Linux or Solaris or some Unix-like variant, based on the permissions you describe in another comment:

$ ls -l hooks/post-receive
-rwxr-xr-x 1 root root 93 Oct 31 14:08

The script is set to be executable, which is necessary, but is not sufficient: it needs to be marked executable (and is), but it also needs to be actually executable (and is not). That is, the underlying operating system must recognize this as a program that can be run without assistance.

Command-line interpreters (aka shells) like /bin/sh and /bin/bash use different rules than the underlying OS. If a file is marked executable, but the OS is unable to run it on its own, these command-line interpreters apply a fallback. They will treat the script as a shell script, and run it themselves. They will, for instance, tell the OS to run /bin/sh, with the script as an argument to /bin/sh. Git does not do this: it relies on the program being directly executable by the OS.

(Which shell is the fall-back interpreter? That's up to the shell you are running, since it's that very shell doing the fall-back.)

Fortunately, all modern Unix-like OSes provide a way to allow the OS to run the script directly. Simply write the script using at least two lines (more are of course permitted) with the first line having the form:

#! /bin/sh

or:

#! /bin/bash

or:

#! /usr/local/bin/bash

or wherever the appropriate command-line-interpreter itself lives. (You can run which sh or type sh to find out where the sh interpreter lives, or which bash or type bash to find out where the bash interpreter lives, and so on. For instance, on one of my machines I get:

$ which sh
/bin/sh
$ type sh
sh is /bin/sh
$ which bash
/usr/local/bin/bash
$ type bash
bash is /usr/local/bin/bash

while another gives me:

sh-3.2$ which sh
/bin/sh
sh-3.2$ type sh
sh is /bin/sh
sh-3.2$ which bash
/bin/bash
sh-3.2$ type bash
bash is /bin/bash

which shows that not every interpreter winds up in the same location on every machine.)

This first line makes the program directly executable by the OS: the OS locates the appropriate interpreter and runs that interpreter, passing the name of the script as an argument (just as the shells do themselves).

Note that this means you can use any program as the interpreter. An awk script can begin with:

#! /usr/bin/awk

A Python script can begin with:

#! /usr/bin/python

You can run Ruby scripts this way as well. You can also solve the problem that the interpreters live in different locations on different machines by using /usr/bin/env, which tends not to move around (so that it's always in /usr/bin) but also applies the PATH environment variable:

#! /usr/bin/env python

This locates the Python interpreter, whether it's /usr/bin/python or /usr/local/bin/python, automatically through $PATH. (Of course it's critical that $PATH be set, but it nearly always is.)

Long unnumbered footnote: fun with scripting

If you have ever wondered why scripts have these #! lines at the top, now you know. But they can do more than just make sh scripts directly executable.

This is a self-printing script:

#! /bin/cat
I print myself!

The OS runs this by invoking /bin/cat on the name of the script. The cat command prints the contents of the script to standard output, and exits. The one minor annoyance is that the #! line itself gets printed, so we fix this using /bin/sed:

#! /bin/sed 1d
I print myself too,
and I elide my first line.

The OS passes the 1d as an argument before the name of the script. Since /bin/sed treats its first argument as an editing command, and the second argument as the input file, this deletes the first line before copying to the output stream, then prints the remaining lines (sed's default action is to print a line).

This is a self-removing script:

#! /bin/rm -f

It has no function other than being entertaining. You can run it once, and then it's gone.

Some OSes allow multiple arguments after the interpreter, while others allow only one argument, effectively quoting remaining white space. You can tell which kind of OS you have by using a self-"awk"-ing script that works if and only if the entire command is one argv element:

#! /bin/awk NR > 1 { print }
only one argument is passed

When the OS invokes /bin/awk, it either does this as the shell equivalent of:

/bin/awk 'NR > 1 { print }' /path/to/script

which prints all but the first line, or it runs it as the shell equivalent of:

/bin/awk NR '>' 1 { print } /path/to/script

which causes a complaint from awk:

awk: can't open file >
 source line number 1

Upvotes: 1

Related Questions