Gollum auto sync to remote git repo

Posted on Tuesday, April 18, 2017


One thing I really need to add to my Gollum install is the ability to auto sync with a remote git repository.

In this article I am going to go over a simple way to do that using git hooks.  In the end every Gollum commits a change it will push that change up to the remote repo.  Also, every time another repo pushes a change to the same remote repo it will run another hook that will cause Gollum to run a git pull locally.






Git hooks and remote repositories


First a quick lesson in git hooks!    It's been a long time since I even fiddled with git hooks and I am by no means a master.  So it's probably a good idea to set up a test.

So as a test let me first set up a git repo and a remote git repo to push to.


  > mkdir push_test.git
  > cd push_test.git
  > git init .
  > git config --global user.email "you@example.com"
  > git config --global user.name "Patrick"
  > echo "hello world" >  test.txt
  > git add --all
  > git commit -m "First commit"
  > git log -n 1









Quick set up of a git remote repository


If you are reading this article I am assuming you have a remote git repo set up and good to go.  But just in case you don't, and to help me the next time I do this, I am going to set up a git remote repository on an Ubuntu 16.04 server I have.

First you need to make a git user (this will set the git user default shell to git-shell to prevent logins


  > sudo useradd git -m -s /usr/bin/git-shell


Create a location to store your git repos. (and make the git user the owner)


  > sudo mkdir /git
  > sudo chown git:git /git





Now switch to the git user


  > sudo su git




You will see that you cannot do it, you need to specify the shell since we set the git-shell as the default.


  > sudo su git -s /bin/bash




That worked.



Now go make a bare repo.


  > cd /git
  > mkdir push_test.git
  > cd push_test.git
  > git init --bare




One last thing to set up on the git remote server, the ssh keys!
SSH  public keys need to be added to the git users .ssh/authorized_keys file.

Generate the SSH keys (for git user on the git-test server)


  > ssh-keygen -t rsa -b 4096




  > vi ~/.ssh/authorized_keys


And copy/paste the ssh key from the server (In my case my gollum server)


Last thing I need to do is to unlock the git account.  (I can't do this as the git user since it does not have sudo access)  Also I need to set the users password


  > sudo passwd git
  > sudo usermod -U git







As a test try to ssh from your server to the git server.  (In my case the git-test server is living at 192.168.0.142 change this to whatever address yours is using)


  > ssh git@192.168.0.142




The connection succeeds, but it also fails to login because it uses the git-shell which will not allow git to login via ssh.  But, it will allow it to push git changes to it via the ssh protocols.


Now it should be ready to be pushed to from my gollum server.







Push to the remote git server


First add the remote.


  > git remote add origin git@192.168.0.142:/git/push_test.git


Now push it  (push the master branch to the remote named origin)


  > git push origin master


 



I prefer to set my upstream so that I do not need to designate the remote repository when I do a push. 

This command will do that.


  > git push --set-upstream origin master
  > git config --global push.default simple






Now If I commit a new change…


  > echo "test" >> test.txt
  > git add --all
  > git commit -m "Second commit"




Then I can just do git push


  > git push







Client-side git hook


Now that I have it all connected, how can I get the wiki to auto push up to the remote repo on changes?

You can read up on git hooks at the official docs https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks [1]

Create a post-commit hook that will run after a local commit has been completed.


  > vi .git/hooks/post-commit


And place the following in it.


#!/bin/bash

#Simple push to origin master
git push origin master






Save it and make it executable


  > chmod a+x .git/hooks/post-commit


That should be it.

Let's run a test…

Run gollum against this folder


  > cd push_test.git
  > gollum





Now open up the website and start editing the wiki (my server happens to be at 192.168.0.77
http://192.168.0.77:4567/





Create a few wiki pages





I made a few pages and edited them a few times.

Let me see what happened.



Let me look at the local log


  > git log -n 2






To test let me pull the git repo anew in the /tmp directory/


  > cd /tmp
  > git clone git@192.168.0.142:/git/push_test.git









  > cd push_test
  > git log -n 2




 

And it did not work…

I believe the hook is good but there is an issue with how gollum's git tool.

To prove this out let me go back to the original repo and hand edit a file and check it in.




  > cd ~/push_test.git/
  > echo "new stuff" >> test.txt
  > git add --all
  > git commit -m "Added by hand"






Now go to the repo that was cloned in the /tmp directory and pull it.


  > cd /tmp/push_test/
  > git pull
  > git log -n 2


 


That worked just fine.   So the hook is fine!  Gollum's implementation of git is lacking.







Fixing Gollum's Git


I found this post on the subject https://github.com/gollum/gollum/issues/69 [2]

K00P at the bottom has a suggestion on how to fix it.  I am going to try and implement that fix.

Create a config.rb file (in my simple case I am going to do it in the repo itself … which is probably not the best place to put it)


  > vi config.rb


And place the following in it  (Replace the path with your own)


Gollum::Hook.register(:post_commit, :hook_id) do |committer, sha1|
        system('.git/hooks/post-commit')
end





Now start gollum, but use the --config option to load this file.




  > gollum --config config.rb


Now open the wiki page and edit a page.






Check the last log in git





Now go to the repo that was cloned in the /tmp directory and pull it.


  > cd /tmp/push_test/
  > git pull
  > git log -n 2





Looks like a match to me J





Auto pulling


How do I get Gollum to auto pull from the remote repo?   I will not use this often, but there are times when I do pull down a git wiki repo and add small images to it and then push it up.


I am not too fond of that idea, but it does take away the need to have a config.rb file.

My other choice is to set up a custom hook on my remote git server that will force my gollum git to run a pull.

I am going to try that and see how successful I am J

First I need to make sure I can ssh from my git server as the git user to my gollum server.

Login the git server and switch to the git user and obtain the public ssh key.


  > sudo su git -s /bin/bash
  > cat ~/.ssh/id_rsa.pub




Copy that into the ~/.ssh/authorized_keys on the gollum server.


  > vi ~/.ssh/authorized_keys


In the git server head over to the base of the git repo you want to add the hook to.


  > cd /git/push_test.git/


Create the post-receive hook


  > vi hooks/post-receive




And place the following in it (tweak the user settings to your own


#!/bin/bash

#Set user to login to gollum server as
USER="patman"
GOLLUM_ADDR="192.168.0.77"
GOLLUM_DIR="~/push_test.git"

#First check to see if the Commited SHA on the GOLLUM server and here are a match
LOCAL_SHA=$(git rev-parse --verify HEAD)
GOLLUM_SHA=$(ssh $USER@$GOLLUM_ADDR "cd $GOLLUM_DIR; git rev-parse --verify HEAD")

#If they do not match then GOLLUM server needs to do a pull
if [ $LOCAL_SHA != $GOLLUM_SHA ]; then
  ssh $USER@$GOLLUM_ADDR "cd $GOLLUM_DIR; git pull origin master"
fi





Make it executable


  > chmod a+x hooks/post-receive



Now in theory when a change is made on gollum and commited it will auto push the code to the remote repo which will then run this hook upon completion.   This hook will run but nothing should be done because the local SHA and SHA on the gollum server will be equal.

But if I push a change up from another location to the remote repo it should force gollum to pull down the changes.

Let's see if it works. ..



Restart Gollum


  > gollum --config config.rb




First make a change in Gollum from the wiki page.  Just to make sure I did not break anything.



Checking the local git repo and remote git repo


  > git log -n 1









Both are identical so the auto-pushing is working.

Now to test the auto pulling…

Go to the cloned repo in the /tmp directory and get a fresh pull


  > cd /tmp/push_test
  > git pull




Make a change to the Home.md file


  > vi Home.md




Add some text and save it.  Add it, commit it and push it up.


  > git add --all
  > git commit -m "Non-gollum added"
  > git push


 


Now did that work?


 


Wahoo it worked!!



References


[1]        Git hooks
[2]        git hooks are not firing when using gollum web interface
[3]        Personal Wiki using GitHub and Gollum on OS X


1 comment:

  1. This was super helpful! Thank you so much for documenting this process so clearly, especially for including your full process.

    I set up a Gollum instance at work for some internal documentation, and this helped me set up an automatic backup of it to a private Bitbucket repository.

    I linked to this article from an article in my Gollum instance, but it's on a private server.

    All the best to you!

    ReplyDelete