User documentation: UsingGit

Current setup

Repositories are in /srv/git/project_name.git for now. git+ssh is supported in Savane's sv_membersh (delegates to git-shell). The git:// lightweight protocol is also available.

Creating an additional repository

NOTE: See below for an automated scripted method to add sub-repositories.

If a project wishes to have several repositories grouped together under the same project name.

make a directory to place additional repositories:

mkdir /srv/git/lwip
chgrp lwip /srv/git/lwip
chmod g+s /srv/git/lwip

create a new shared bare repository (supposedly named lwip-contrib hereafter) in that directory:

git init --shared=all --bare /srv/git/lwip/lwip-contrib.git

write following to: /srv/git/lwip/lwip-contrib.git/hooks/post-update:

#!/bin/sh
exec git update-server-info

make it executable:

chmod a+x /srv/git/lwip/lwip-contrib.git/hooks/post-update

forbid access to hooks:

chown -R root:root /srv/git/lwip/lwip-contrib.git/hooks
chattr +i /srv/git/lwip/lwip-contrib.git/hooks

Update the description file:

echo "lwIP Contrib - Contributed code for Lightweight TCP/IP stack" > /srv/git/lwip/lwip-contrib.git/description

Deprecated cvs server: If upon specific request add 'git-cvsserver' support. This is no longer desirable for a default. Only kept here now for documentation of the legacy environment.

cd /srv/git/lwip/lwip-contrib.git
git config gitcvs.pserver.enabled 1
git config gitcvs.ext.enabled 0
git config gitcvs.dbname "%G/gitcvs-db/sqlite"
mkdir /srv/git/lwip/lwip-contrib.git/gitcvs-db -m 755
chown nobody /srv/git/lwip/lwip-contrib.git/gitcvs-db

Creating an additional repository - automation script

A script to automate the above steps is available in vcs:~root/bin/gnu-sv-add-git-sub-repository.sh and also in fencepost:~agn/gnu-sv-scripts/gnu-sv-add-git-sub-repository.sh.

The script takes two parameters: the existing project name (e.g. lwip) and the new sub-repository name to create (e.g. contrib).

Example, the following request: https://savannah.gnu.org/support/?108678 has been completed using:

ssh vcs
~/bin/gnu-sv-add-git-sub-repository.sh guix artwork

The script also prints the URLs for easy copy&pasting.

Enabling Commit Notifications

Set git configurations:

cd /srv/git/auctex.git/
git config multimailhook.mailinglist emacs-elpa-diffs@gnu.org

The result will be this in the git config file.

[multimailhook]
        mailinglist = emacs-elpa-diffs@gnu.org

This can be done using the git-config utility to edit that file.

git config multimailhook.mailinglist emacs-elpa-diffs@gnu.org
git config multimailhook.emailprefix "[emacs-elpa-diffs]"

Unprotect hooks/ directory:

chattr -i hooks/

Link git_multimail.py to the local hooks directory:

ln -s /usr/src/git-multimail/git-multimail/git_multimail.py hooks/

Copy another projects template into the hooks directory and then edit it to configure it for the new project. This can be done on the fly using sed. This sets the Mail-Followup-To: header address to the devel discussion mailing list which is separate from the commit diff mailing list. Set it to where follow-up discussion is desired.

sed s/emacs-devel@gnu.org/groff@gnu.org/ /srv/git/emacs/elpa.git/hooks/post-receive > hooks/post-receive
chmod a+x hooks/post-receive

Protect hooks/ directory again:

chattr +i hooks/

Disabling Reference Change Notifications

Sometimes maintainers do not like the receiving reference change commits in addition to changeset commits. Optionally this may be disabled. See the groff.git config for an example. In summary change the config file from this:

    mailinglist = groff-commit@gnu.org

To this:

    mailinglist = nobody
    commitList = groff-commit@gnu.org

Multiple post-receive Hooks

If multiple post-receive hooks are desired then special handling is needed since oldrev newrev refname are passed in on stdin. This will need to be passed in to all hook scripts if multiple ones are desired. See auctex.git/hooks/post-receive for an example. Here is a snippet.

while read oldrev newrev refname; do
  echo $oldrev $newrev $refname | /usr/local/bin/git-post-receive-hook
  echo $oldrev $newrev $refname | hooks/post-receive-mail-local
done

Renaming a branch

This needs some rationale and justification because during normal operation we never want to rewind a branch. It causes problems for anyone who has pulled from the branch. Normally branches only move forward. But sometimes renaming a branch is the best solution to a problem.

Sometimes a user has munged a commit, has pushed the desired branch onto a temporary branch (call it new-master), and wishes to have the new temporary branch become the master branch as the correction.

Verify the current and future state of the repository:

cd /srv/git/exampleproject.git
git branch -l
git log
git log new-master

Move the current branch to master-broken as a backup save:

git branch -m master master-broken

Move the new branch into place as master:

git branch -m new-master master

At this time the "current" branch will be shown to be master-broken:

git branch -l
  master
* master-broken

(There is likely a less heavy-handed command to do this. This is the only way I know how at this moment. I would welcome an improvement here. Normally with a working directory 'git checkout' would be used to set this.) The current branch reflog was moved when the branch was moved and is now set to master-broken and needs to be updated to point to master. Since this is a raw repository update the HEAD file directly:

echo ref: refs/heads/master > HEAD

Verify the current status us as desired:

git branch -l
* master
  master-broken

Verify that the change is correct. Better to leave the broken branch around for a while than to remove it too soon and lose something that should not have been lost. Then clean up and discard the broken branch:

git branch -D master-broken

Task List

  • Sub-repositories
  • We need to decide how to allow multiple repositories, or stick with a single one. repo.or.cz seems to use project_name.git and project_name/forks.git, which sounds cool.
  • repo.or.cz also implements the concept of "forks": http://repo.or.cz/m/regproj.cgi?name=git/ which can be used to save bandwidth.
  • Implement repository instanciation in Savane - more generally git support. [Basic Git support implemented]
  • Repository optimization (packing, pruning) needs to be done at some points, probably via hooks. git:// doesn't allow this kind of operations. At kernel.org, people usually have shell access and a private/non-shared repository, so they don't have this kind of issues. The doc says: "packing every 4-5MB of loose objects accumulation may be a good rule of thumb." (http://www.kernel.org/pub/software/scm/git/docs/everyday.html#Basic%20Repository). Apparently it's done by git when there's a lot of objects committed at once, but it may be necessary to do it manually (git gc --auto) from time to time.
  • Hooks management, as usual.

Links