"Proper" way to pull git "production branch" to production server

dropson picture dropson · Oct 30, 2012 · Viewed 28k times · Source

I'm quite new to Git, and have read the Pro Git book @ http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging. My question is if what I'm doing today is the prefered way to work with production server and a remote Git repo.

I have my repo hosted on GitHub, using three remote branches: developing -> testing -> master.

Whenever the 'testing' branch has been verified to be working, I git merge 'master' with 'testing' (fast forward?) locally, and git push 'master' to GitHub.

On the production server (/opt/www/url.com/) I have done:

git init
git remote add origin https://github.com/.....
git pull origin master

Now everytime I want to update the master I issue a git pull

git pull origin master

Production will never push any changes to remote. And local changes won't happen. Am I doing it correct? If not, what is the prefered way to pull updates to production?

Edit #1: I don't want to manage any conflicts on the production server, which I am facing now (somehow I've done something wrong). I simply want to pull down the latest updated master branch, and switch to it.

Answer

Bob Kerns picture Bob Kerns · Jun 28, 2018

Doing 'git pull' is pretty ordinary for this, but there's a more bullet-proof way.

There wouldn't be any conflict, if somehow you didn't make local changes. But if you just want to get an up-to-date tree, and blow away any local changes, there's a better way, that ignores anything local:

First, you need to get the latest from the server. Rather than 'git pull', for this, we'll use:

git fetch origin master

This does the first half of a 'git pull'. (The second is the merge into your local master, which is where you ran into problems).

Git fetch does:

  1. Finds what commit master points to on the remote
  2. Downloads that commit and everything it references that you don't have locally.
  3. Updates the origin/master ref to point to that commit, to remember where the remote is on its version of 'master'.

Next, we'll simply update our local 'master' to point to the same commit, and update our working tree.

For this, we'll use:

git reset --hard origin/master

(This is presuming you didn't use a different name for your remote repo, instead of the default 'origin' -- adjust accordingly if you did).

This actually does three things:

  1. Updates your local master branch to point to the same commit you just fetched from the remote.
  2. Loads that tree into your index
  3. Updates your working tree to match the index.

You now have a local master branch and tree that match the remote.

But there's one more step, which is to clean up anything left over, that's not being tracked by git.

git clean -fdx

Will remove any files created by prior builds and give you a clean environment. You should be copying any build artifacts you want to preserve to some other location in any case.

'git pull' is aimed at developers coordinating their work, so it's really not the ideal tool for this job. 'git fetch' and 'git reset --hard' are more specific, without the protections against accidental overwrite of local work.

But that's exactly what you want here.

Still, if you sometimes make changes to fix problems on the production server, you might want to continue to use 'git pull'. Merges and possible conflicts may be more helpful than harmful.

But sometimes you just want reliable updating as part of your automation, and any local changes are a problem to be eliminated.

But you probably want that 'git clean' even with 'git pull'. Left-over files can screw up builds and deployments in mysterious and hard-to-identify ways.