views:

333

answers:

3

I'm using git to manage a grails project I have.I set up a git repository on a remote server and what I want to do is when I have code working locally, I want to commit it and push to the remote server. I want the updated groovy file and gsp's to be put into the right spot on the remote server so that grails will pick up the changes for remote testing. Is this possible?

A: 

If you are on linux you could set up a cron job to copy the files for you, or if you are on windows you could create a scheduled task with a small bat or vbs script to copy the file to the remote server. If you need help on using Git here is the users manual. If that is not what your looking for we can work on something that might work better or if you need help with the scripts let me know.

Alos
So does git not store the actual files on the remote server? I created a repository locally, commited all the files then pushed to the remote server, it only seems to contain a large pack file, no actual source code. The server is linux(red hat). Thanks for the info.
TripWired
It can I just was not sure what you were asking for exactly. One of the advantage of Git is that you don't need a centralized approach, but you can if you want.
Alos
+3  A: 

With respect to your comment on Alos' post: the remote is what's called a bare repository - it contains the entire repository except for a checked-out copy of the contents. The idea is that for central repositories that you just push and pull from, there's no need to have the files.

That said, there are a lot of approaches to do what you're trying to do.

  • You could create another remote non-bare clone, and use it to pull from the bare one and do the testing. This is probably easiest.

  • You could directly check out files (using git read-tree and git checkout-index) from the bare repo (an example comes to mind, git.git's install-doc-quick.sh).

  • You could even use a non-bare remote, but keep in mind that pushing into a non-bare repo is dangerous since the working tree doesn't get updated. Depending on your version of git, there are various safeguards you'll have to override, and you'll have fix the work tree after pushing (git reset --hard probably).

No matter which approach you take, assuming you want to trigger your tests after every push, you can use the post-receive or post-update hook to do so. (You could have it check the length of time since the last test if you want to avoid repeated tests from a burst of pushes)

Jefromi
No offence taken. Cheers
Alos
Completely missed your answer at the time I was posting mine. +1 for enumerating all the possibilities.
VonC
You already had my +1 for the link to the previous question.
Jefromi
+2  A: 

If you are pushing to a remote repo, where "it only seems to contain a large pack file, no actual source code" (as you detail in the comments), that should mean "bare repo", which is good for it allows you to push without any risk of differences between a working tree and the git data.

Then, as described in "Can I use git to keep a remote server up to date?", another (non-bare) repo and a post-update hook on the bare repo side will get you where you want.


The OP TripWired adds:

Okay so what I did is:

  • create the bare repo for checking in then
  • I created another repo that was standard, basically i have ~/project.git and ~/project.
  • I cloned project.git into project and in project.git/hooks/post-update I put:

    cd ../../project env -i git checkout . env -i git pull

I also made sure that post-update was executable.
When I run the hook from the command line it works fine, but it doesn't seem to work when I do a check in to the repo.

I agree with steps 1 and 2, but would then use this script, as in this question.

Check if it works with a git push from your local repo to your bare repo.

#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update".

git-update-server-info

is_bare=$(git-config --get --bool core.bare)

if [ -z "$is_bare" ]
then
    # for compatibility's sake, guess
    git_dir_full=$(cd $GIT_DIR; pwd)
    case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi

update_wc() {
    ref=$1
    echo "Push to checked out branch $ref" >&2
    if [ ! -f $GIT_DIR/logs/HEAD ]
    then
        echo "E:push to non-bare repository requires a HEAD reflog" >&2
        exit 1
    fi
    if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null)
    then
        wc_dirty=0
    else
        echo "W:unstaged changes found in working copy" >&2
        wc_dirty=1
        desc="working copy"
    fi
    if git diff-index --cached HEAD@{1} >/dev/null
    then
        index_dirty=0
    else
        echo "W:uncommitted, staged changes found" >&2
        index_dirty=1
        if [ -n "$desc" ]
        then
            desc="$desc and index"
        else
            desc="index"
        fi
    fi
    if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
    then
        new=$(git rev-parse HEAD)
        echo "W:stashing dirty $desc - see git-stash(1)" >&2
        ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
        git-update-ref --no-deref HEAD HEAD@{1}
        cd $GIT_WORK_TREE
        git stash save "dirty $desc before update to $new";
        git-symbolic-ref HEAD "$ref"
        )
    fi

    # eye candy - show the WC updates :)
    echo "Updating working copy" >&2
    (cd $GIT_WORK_TREE
    git-diff-index -R --name-status HEAD >&2
    git-reset --hard HEAD)
}

if [ "$is_bare" = "false" ]
then
    active_branch=`git-symbolic-ref HEAD`
    export GIT_DIR=$(cd $GIT_DIR; pwd)
    GIT_WORK_TREE=${GIT_WORK_TREE-..}
    for ref
    do
        if [ "$ref" = "$active_branch" ]
        then
            update_wc $ref
        fi
    done
fi
VonC
This sounds like it might work. So if I have the bare repository and i update my post-update hook I can use it to copy the source code to another directory? I assume i would need a git repo similar to what i have on my local machine that just does a clone from the bare repo?
TripWired
Yes to the first, and yes (in the simplest case) to the second. I can think of more complicated ways to do it that'd avoid the duplication, if enormous repo size were a problem, but I doubt you're in that case.
Jefromi
Okay so what i did is create the bare repo for checking in then I created another repo that was standard, basically i have ~/project.git and ~/project. I cloned project.git into project and in project.git/hooks/post-update I put: (cd ../../project)(env -i git checkout .)( env -i git pull) parens just to separate the lines on here. I also made sure that post-update was executable. When i run the hook from the command line it works fine, but it doesn't seem to work when i do a check in to the repo. Any ideas?
TripWired
Some tips to try: `post-receive` instead of `post-update`? (http://stackoverflow.com/questions/1558036), check if it works from a push with tortoiseGit? (http://stackoverflow.com/questions/2108584), check your `post-update` location? (http://stackoverflow.com/questions/1474515), **try a `git push` instead of a `cd ...; git pull`**: http://stackoverflow.com/questions/279169
VonC