8

I am trying to set up a "simple" git workflow for a Wordpress installation that has a local version, a staging version and a production version. All I want to do is make changes locally and push from local to staging and from local to production. At first I thought this would be a simple task. I have been able to initialize the repository, add the two remotes "staging" and "production", initialize git on the remotes and push changes from my local version to the staging and production servers normally using the commands:

git add .
git commit -m "some changes"
git push staging master
git push production master

However, at some point during my work something changed, and while I am still able to push to Staging, now I am unable to push to the Production server without getting the error:

! [remote rejected] master -> master (Working directory has unstaged changes)

When I do "git status" it says:

On branch master
nothing to commit, working tree clean

After reading the answers to several SIMILAR BUT DIFFERENT questions on Stack Overflow I have tried the following:

git pull staging master
git pull staging master --rebase
git pull production master
git pull production master --rebase

I also tried executing this command on the remote servers

git config --local receive.denyCurrentBranch updateInstead

I have already completely re-created the servers and repositories a few times just to re-install git entirely from scratch, but this problem keeps happening after a while and at this point Git is actually HURTING my workflow instead of helping it. If anyone has any insight into what my mistake is, it would be much appreciated!

user3826864
  • 429
  • 4
  • 19
  • is your production repo set up as a bare repository? – cptwonton Jan 24 '18 at 00:49
  • Hello, thanks for the suggestion. I have tried deleted the remote repos and reinitializing them with `git init --bare` which created bare repositories in each of them. However, now when I try to do `git push staging master` it says that it completes the push but then the changed file does not actually make it into the folder I am pushing to :-C – user3826864 Jan 24 '18 at 01:19
  • :(. may i ask why you're doing it this way? you could instead be using just plain old github and set up your (windows?) machines as VSTS build clients. anytime you push to your github, VSTS will automatically "build" your code either in the cloud or on your production/staging machine. final step in the build is publishing artifacts, which if your production/staging machines are build agents, will not even need to FTP or anything. – cptwonton Jan 24 '18 at 01:33
  • *the changed file does not actually make it into the folder I am pushing to* — Of course they don't. Bare repo is a repo without files (without worktree), it only contains git database. To checkout files from a bare repo you need to clone from it to a non-bare repo. And pull from it again every time you push to the bare repo. – phd Jan 24 '18 at 02:28

2 Answers2

15

I had similar problems, pushing to a non-bare remote repo where I wanted the working copy files to be checked out immediately.

My remote was configured with receive.denyCurrentBranch updateInstead, but it still refused to accept pushes at unpredictable times.

Git 2.4 added a push-to-checkout hook, which can override such push failures.

I wrote a short script based on the example in the githooks documentation.

#!/bin/sh
set -ex
git read-tree --reset -u HEAD "$1"

I installed this script in .git/hooks/push-to-checkout in my remote repo.

Note that this script overwrites the working copy in the remote — it does not attempt to merge any changes to those files.

That's because I want the working copy to simply reflect the files in the repo.

nyedidikeke
  • 6,899
  • 7
  • 44
  • 59
Jay Lieske
  • 4,788
  • 3
  • 30
  • 41
  • 7
    Thank You!!! I would vote this up 100 times if I could. The only thing I had to do that wasn't mentioned is change the file permissions to make it executable `chmod +x push-to-checkout` then it worked. – vinylDeveloper Feb 02 '19 at 05:25
  • 1
    Note that if you're using cPanel, then you'll need to manually create the `push-to-checkout` file. – Kourosh Taheri-Golvarzi May 25 '19 at 11:37
1

Making a git bare repo is the best practice to push to.
You could push to a non-bare one... but only if you are not modifying files on the destination side while you are pushing file from the source side. See push-to-deploy.

But the best practice remains to add a post-receive hook (as in my other answer) in order to checkout in an actual folder all the files you have received.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250