How to sync a local dir to server using Git?
How can I use Git to simply keep in sync a local dir with a server dir?
I'm used to FTP but it's slow and prone to errors.
I have SSH access to the server. I can run Git on the server.
I also want to avoid a third-party Git hosting service like Github or Bitbucket. I want to be able to directly upload to my server.
Solution 1:
On the local machine:
-
Initialize the directory to be synced as a Git repository
git init
Commit any existing code
git add -A git commit -am "initial commit"
-
Set its remote to the server
git remote set-url origin user@server:/path/to/dir/on/server
Where
user
is the username you use to SSH to yourserver
. Eg. [email protected]/path/to/dir/on/server
is the directory on the server you wish to sync your changes to
Side-note: It's advisable to go password-less for SSH logins
On the remote machine:
-
Initialize an empty directory on the server
mkdir /path/to/dir/on/server cd /path/to/dir/on/server git init
-
Set its config to ignore updates to checked out branch
git config receive.denyCurrentBranch ignore
This is needed because (quoting the exact error you'll get if you don't do this) "updating the current branch in a non-bare repository is denied, because it will make the index and work tree inconsistent with what you pushed, and will require 'git reset --hard' to match the work tree to HEAD." (we'll actually do just that in the next step).
-
Set up a
post-receive
git hook:Create a file
post-receive
in the.git/hooks
directory, and open it in an editor:vim .git/hooks/post-receive
Put the following in it:
#!/bin/sh git --git-dir=. --work-tree=.. checkout -f
Set its mode to executable:
chmod +x .git/hooks/post-receive
This will checkout your latest changes on the server dir whenever you push any.
-
One-liner for all of above:
dir=<dir>; mkdir $dir && cd $dir && git init && git config receive.denyCurrentBranch ignore && printf '#!/bin/sh\ngit --git-dir=. --work-tree=.. checkout -f' > .git/hooks/post-receive && chmod +x .git/hooks/post-receive
Now on the local machine you can do this:
git commit -am "Some changes"
git push
and your local dir will be synced to the server dir.
An additional recipe that I use often: On local machine, I keep the origin
remote name for Github/Bitbucket which is the "home" of the project, and a special server
remote name which is where it gets deployed. I also create a git branch (which is also named) server
and configure it to always push to the server
remote:
git config branch.server.remote server
git config remote.server.push server:master
This way whenever I'm on master branch it pushes to the origin
(Github/Bitbucket etc) and when I'm on the server
branch it pushes to the server.