📜 ⬆️ ⬇️

Git and site publishing

When I try to edit this old post, all the formatting has gone. Maybe I'll ever fix it.

I spent several months fighting Git-svn glitches and thinking about different options before coming to this method of organizing a workflow with a site - simple, flexible and easy to use.

Main advantages:

Overview


The main idea of ​​the system is to create two repositories on the server: an empty bare repository and a regular repository with a working copy of the site. This pair is connected by a pair of simple hooks that automate push and pull changes.
')
Scheme of work

So, two repositories:

Working with two repositories is simple and very flexible. Remote copies that have ssh access can easily update the live version of the site by simply pushing to the Hub repository. Any changes made to the live version on the server are instantly merged into the Hub at commit. In general, everything works very simply - and it doesn't matter where changes are made.

Small preparations before the start


Naturally, first of all, it is necessary that Git be installed on the server and on all the developers' computers. If Git is not installed on your shared hosting, you can fix it very easily (en).

If this is your first time working with Git on your server, do not forget to specify global settings . I specify special values ​​for user.name , in order to see in the project history changes made on the server:
$ git config --global user.name ", "


Go!


First of all, we will create a new git-repository in the live-directory of our site, and then we will add and fix all the files of the site. This will be the Prime repository and the working copy. Even if there is already a project history in other places, the contents of the site will be the base point into which all other copies will then be merged.
$ cd ~/www
$ git init
$ git add .
$ git commit -m " "


Since we have initialized the repository in the working copy — there is no need to shut down the site for maintenance and re-upload all the files, Git will simply create the repository from the existing files.

Now that our site is already in Git, let's create a bare repository somewhere outside the site’s working directory.
$ cd
$ mkdir site_hub.git
$ cd site_hub.git
$ git --bare init
Initialized empty Git repository in /home/joe/site_hub.git

Hooray! Again, we’ll go back to the working directory of the site and add the Hub as a remote repository, and then add the contents of the master branch from the Prime repository to the Hub.
$ cd ~/www
$ git remote add hub ~/site_hub.git
$ git remote show hub
* remote hub
URL: /home/joe/site_hub.git
$ git push hub master

Hooks


As I mentioned at the beginning, Hub and Prime are synchronized with each other using two simple scripts.

One of the basic rules when working with Git is to never push into a repository that has a working copy. We follow this rule and create a “Hub” repository. Instead of pushing from the Hub, which will not affect the working copy, we will use a hook that will force Prime to pull from the Hub repository.

Post-update - in the Hub-repository

As soon as the Hub receives a new batch of changes, this script will be executed immediately. We move to the working directory of the Prime repository, and pull the changes from Hub. Pushing changes (push) does not change the state of the working directory of the repository, so you need to pull, while in the working directory.
#!/bin/sh

echo
echo "**** Prime [Hub's post-update hook]"
echo

cd $HOME/www || exit
unset GIT_DIR
git pull hub master

exec git update-server-info

Post commit - in Prime repository

This script runs after every commit in the Prime repository and pushes changes to the Hub. In an ideal world, of course, we will never edit anything directly on the server. But in our imperfect world, anything is possible, so let's automate the process of pushing changes in order not to destroy the project's history and avoid possible conflicts.
#!/bin/sh

echo
echo "**** pushing changes to Hub [Prime's post-commit hook]"
echo

git push hub

So, using this hook, we immediately receive in the Hub-repository all the changes made in the master branch of the Prime-repository. Other branches can also be cloned, but they will not affect the site. Since all remote copies are accessed via the SSH address to the Hub, only users who have direct access to the shell can push and start updating the site.

Conflicts


“Putting” a website with such a system of synchronization of two repositories is very difficult. Every change made in Prime automatically enters the Hub and all conflicts will be immediately visible when you try to push from repository clones.

But still there are several situations in which the state of Prime may differ from Hub'a, and to correct the situation, you will need to perform several additional gestures. If we rule something on Prime and do not commit the changes, and at this moment the post-update in the Hub will work, then everything will end with an error with the message “Entry 'foo' not uptodate. Cannot merge. " Committing changes to the Prime working directory will allow you to clear its state, and the post-update hook will be able to merge all unsent changes.

I also found that if a conflict arises due to the fact that changes in Prime cannot be merged with Hub, then the best solution would be to push Prime's current state into a new branch on Hub. This command, executed from the Prime working directory, will create a remote fixme branch based on the current Prime-repository location.
$ git push hub master:refs/heads/fixme

As soon as the changes are in Hub, we can get a branch in any of the clones, resolve the conflict and merge the branches. An attempt to resolve the conflict directly on the server will almost certainly lead to problems in the work of the site due to the appearance of markers of conflict areas.

Keep everything clean


The .git Prime repository directory is located in the root directory of the site, and is probably available for public access. To prevent anyone from sticking their nose where they shouldn't, add these lines to the top-level .htaccess file:
# deny access to the top-level git repository:
RewriteEngine On
RewriteRule \.git - [F,L]

Note translator: there are other ways to close access to the directory on the server.

Other problems


If you see this error when trying to push to the repository on the server:
git-receive-pack: command not found
fatal: The remote end hung up unexpectedly

In this case, simply add export PATH=${PATH}:~/bin to your server .bashrc file.

Source: https://habr.com/ru/post/127213/


All Articles