Q:

Deploy web site via Git

I work on a team of web developers. We each have a personal web site set up in our home directories on the development server.
We want to convert them to git working repos so we can branch, rebase, and generally enjoy the benefits of git goodness.
In reading online, there's a couple of options:
1) create a bare repo that syncs to the working repo in www/ via a post-receive hook
2) push directly to the working repo
Problem with option 1 is it doesn't handle branching well. When we push a branch other than master, the post-receive hook still only syncs master so our changes never appear on the development site.
Problem with option 2 is git disallows pushing to a checked-out branch to prevent a detached HEAD state.
In reading around the web, the "best practice" solution to option 2 goes something like this:
1) on CLIENT push to dummy branch
2) on SERVER merge dummy into master... BUZZZZ wrong answer. Assume the end users don't have shell access to the server.
So I thought, "no problem, just create a post receive hook like this":
#!/bin/bash
read oldSHA newSHA branch
git merge $branch

Now here's the weird part: when the post-receive hook executes I get
Please, commit your changes or stash them before you can merge.

Yes, I have confirmed that master is the checked-out branch on the server, and that the dummy branch has been updated correctly. When I run the very same command (git merge dummy) directly on the server, everything works fine.
Can anyone explain why?
Thanks in advance.
EDIT 1
Here are the results of git status, both pre-merge and post-merge
Counting objects: 5, done.                                                                                                                                                            
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 307 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: **** PRE MERGE ****
remote: # On branch master
remote: # Untracked files:
remote: #   (use "git add <file>..." to include in what will be committed)
remote: #
remote: #       COMMIT_EDITMSG
remote: #       FETCH_HEAD
remote: #       HEAD
remote: #       ORIG_HEAD
remote: #       config
remote: #       description
remote: #       hooks/
remote: #       index
remote: #       info/
remote: #       logs/
remote: #       objects/
remote: #       packed-refs
remote: #       refs/
remote: no changes added to commit (use "git add" and/or "git commit -a")
remote: error: Your local changes to the following files would be overwritten by merge:
remote:         index.htm
remote: Please, commit your changes or stash them before you can merge.
remote: Aborting
remote: **** POST MERGE ****
remote: # On branch master
remote: # Changes not staged for commit:
remote: #   (use "git add <file>..." to update what will be committed)
remote: #   (use "git checkout -- <file>..." to discard changes in working directory)
remote: #
remote: #       modified:   index.htm
remote: #
remote: # Untracked files:
remote: #   (use "git add <file>..." to include in what will be committed)
remote: #
remote: #       COMMIT_EDITMSG
remote: #       FETCH_HEAD
remote: #       HEAD
remote: #       ORIG_HEAD
remote: #       config
remote: #       description
remote: #       hooks/
remote: #       index
remote: #       info/
remote: #       logs/
remote: #       objects/
remote: #       packed-refs
remote: #       refs/
remote: no changes added to commit (use "git add" and/or "git commit -a")

Note that I can do a manual git add ., git commit -m "foo" and re-do this process with the same result

A:

In one of those "DUH!" moments, I realized I could use option 1 and just pass the branch name in like I was attempting with option 2.
So, I created a /home/username/www.git bare repository, cloned it to /home/username/www and added a post-receive hook to /home/username/www.git that looks something like this:
#!/bin/bash
read oldSHA newSHA branch
git --git-dir="/home/username/www/.git" --work-tree="/home/username/www" pull /home/username/www.git $branch

Then I changed my remote to ssh://username@example.com/home/username/www.git (the bare reop, not the working one) and push to that remote via:
git push remoteName branchName

Voila! Everything works.
The actual post-receive code is more complex as I use some error traps and variables for the directory names (so they can be deployed to any user), but you get the idea.
(Be careful to distinguish between www/.git and www.git when reading the code samples.)

