User documentation: UsingGit

Current setup

Repositories are in /srv/git/group_name.git for now. git+ssh is supported in Savane's sv_membersh (delegates to git-shell), however, as of 2024-04, a customized setup is used that doesn't involve sv_membersh. The git:// lightweight protocol is also available.

Creating an additional repository

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

On vcs2, 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 write access to hooks:

chown -R root:root /srv/git/lwip/lwip-contrib.git/hooks
chmod -R og-w /srv/git/lwip/lwip-contrib.git/hooks

Group administrators can edit repository description at https://savannah.gnu.org/git/admin/?group=$unix_group_name.

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

Enabling Commit Notifications

Set git configurations. This can be done using the git-config utility to edit that file. Don't set an emailprefix or there will be two when the mailing list configuration is also configured to add one.

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

The result will be this in the git config file.

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

Link git_multimail.py to the local hooks directory:

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

Copy the template from another group into the hooks directory and then edit it to configure it for the new group. 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

Verify that the hooks/post-receive file then looks like this. Two instances in the file need to be set. (Oldest configurations included only the sender via the reply_to value. But we have switched to having follow-ups go to the bug list. Then configurations switched to both the bug list and the original sender. But having discusson on the bug list makes the most sense. But we do have a variety of configurations currently active.)

grep Mail-Followup-To ./hooks/post-receive
Mail-Followup-To: emacs-devel@gnu.org
Mail-Followup-To: emacs-devel@gnu.org

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

Renaming or deleting a branch needs some rationale and justification because during normal operation we never want to rewind a branch. Rewinding a branch causes problems for anyone who has pulled from the branch previously as it breaks being able to pull to it. Normally branches only move forward. But sometimes renaming a branch or deleting a branch is the best solution to a problem. Use judgement.

Examples are that 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. If in your best judgement it should be modified then these are the steps that might be used to do it.

Verify the current and future state of the repository:

cd /srv/git/examplegroup.git
git branch -l
git log
git log new-master
git log --oneline --graph --decorate --color master new-master

Save the current branch to master-broken as a backup save. Here I am calling it master-broken but use as descriptive of a name as appropriate. Perhaps master-oldconversion for example. Use your judgement. This following creates master-broken based upon master.

git branch master-broken master

Then now that the hash exists in another branch the easiest thing is to delete the master branch. Use the lower case "-d" as that has a safety feature built into it which will warn and require a force option if this would remove the last reference to the objects. But having a reference in master-broken that we just created this action will succeed without issue.

git branch -d master

Then now that the name is available can do the same again and "create" a new branch named master based upon the desired branch.

git branch master new-master

Verify the result. The master branch should be the HEAD branch. That is the default branch used with clients clone the repository.

git branch -l
* master
  master-broken

At this point if everything seems good then you are done! Update the bug tickets, write a closing email response, make a reply on IRC, or whatever is needed.

Cleaning Up

Verify that the changes made are 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. I recommend being in no hurry to hard delete things. Perhaps it never needs to be deleted.

Later when all is okay only then to clean up and discard the broken branch do the following. This uses the "-D" which is a shortcut abbreviation for "--delete --force" and one should always be careful when using force.

git branch -D master-broken

Fixing git HEAD problems

Previous versions of these instructions specified to move the branches around. That worked but also moved the HEAD as well and left HEAD referencing master-broken. If you find yourself in this situation then the result will look like this following undesired state.

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

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 group_name.git and group_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