Table of Contents
Git
Evergreen uses Git as its primary version control system for both code and documentation. A number of repositories of interest to Evergreen, including the main public repositories for Evergreen, Evergreen's documentation, and OpenSRF, are maintained on the community Git server.
Using Git
Getting commit access to working repositories
Evergreen contributors are encouraged to publish branches containing their contributions to the OpenSRF and Evergreen "working" repositories. We maintain git repositories for this purpose; we simply need to add your SSH public key to the working repository to give you permission to publish branches.
- If you do not have an SSH key, you can generate one as follows:
bash$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/username/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again:
- Email your public key to the Evergreen git administrators at gitadmin@evergreen-ils.org and request permission to commit to the OpenSRF and Evergreen "working" repositories. NOTE: in the preceding example, your public SSH key would be found at
/home/username/.ssh/id_rsa.pub
- DO NOT sendid_rsa
!
Configuring SSH
If the SSH key you use for this Git repo isn't located at: ~/.ssh/id_rsa
then you will need the following configuration file in ~/.ssh/config
:
Host git.evergreen-ils.org IdentityFile=<LOCATION OF YOUR SSH KEY>
Quick start for Evergreen contributors
git clone git://git.evergreen-ils.org/Evergreen.git cd Evergreen # Add the "working" remote to pull from working branches git remote add working git://git.evergreen-ils.org/working/Evergreen.git # Have the ability to push to the working repo if you send in your SSH key git remote set-url --push working git@git.evergreen-ils.org:working/Evergreen.git # Fetch all of the branches and updates from all remotes # Probably a good idea to do this every time you start another working session git fetch --all # Set your email and user name git config user.email user@hostname git config user.name "Firstname Lastname" git checkout -b working_branch origin/main # hack away git commit -as # and enter a useful comment
If you have sent your SSH pubkey to gitadmin@evergreen-ils.org and have commit privileges to the working repository, please publish the branch containing your changes:
git push working working_branch:user/<username>/working_branch # then add 'pullrequest' to the tags for the Launchpad bug
Alternately, to create one or more patch files containing your changes:
git format-patch origin # attach patch file(s) to Launchpad bug
Git resources
Guidelines for contributors
Commit messages
A commit message should consist of a subject line (i.e., the first line of the commit message), then a blank line, then an optional description of the patch, followed by one or more signoffs. The subject line should be brief, ideally no more than 60-70 characters. Although it is acceptable to omit the Launchpad bug number from commit messages while work is in progress, by pullrequest time, each commit in a branch should include this number if relevant. Here is an example of a minimum commit message:
LP#24544: fix the quuxifier Release-Note: Fix the cromulent emulsification of the quuxifier for new installs. Signed-off-by: Jane Hacker <jhacker@example.org>
Of course, sometimes a patch requires more description and review:
LP#542: extend the foobar subsystem Add support for the thingmajigger interface provided by the Baz module. Adds the following OU settings: circ.foobar.baz and the following permissions VIEW_FOOBAR UPDATE_FOOBAR DELETE_FOOBAR Signed-off-by: Jane Hacker <jhacker@example.org> Signed-off-by: Roger Reviewer <roger@example.com> Signed-off-by: Chris Committer <chris@example.net>
Bug Fix Release Note Commit Message Tag
For simple bug fixes that can be described with one line, include a line that starts with "Release-Note:" that includes the release note text. This will be grabbed by a script during release creation to speed up creating the release notes.
Use Present Tense
"Release-Note:" entries should use present tense; Add, Adds, Fixes, Updates, Removes.
If the bug fix needs more explanation, then the docs/RELEASE_NOTES_NEXT/miscellaneous.adoc would be a better location to add those notes.
Examples:
Release-Note: Adds form field labels for patron survey question administration Release-Note: Fixes an issue where auto-renewal events can overwhelm open-ils.trigger drones
Testing Plan
Include a testing plan to ensure that any testers of your patch can quickly understand how to see the original problem and know how to confirm that the fix works. If a specific system configuration needs to be setup to see the problem in a Concerto Evergreen install, then include those steps.
It is also acceptable to include the testing plan in the Launchpad ticket, but a note in the commit message such as "See LP bug report for testing plan" can make sure the tester knows where to find it.
Sign-offs
For the Evergreen and OpenSRF projects, all patches must be signed off by the author. The author sign-off signifies that the author is permitted to submit the patch and is equivalent to signing a DCO (Developer's Certificate of Origin). More information on the DCO is included in the main contributing page.
An author sign-off can have a secondary meaning: that the author has tested the patch and believes it to be of sufficient quality to contribute to Evergreen. All contributors are encouraged to enlist other people to review their patches, and a sign-off by somebody other than the author signifies that the patch has been reviewed.
A sign-off takes the form of the following text in the commit message for a patch:
Signed-off-by: Jane Hacker <jhacker@example.org>
Signing off on one or more commits
The easiest way to sign-off on one or more commits is to:
- Create a new branch based on current main (or, if backporting a fix to a previous release, from the appropriate release branch)
- Cherry-pick the commits using the
-s
flag - Test to ensure that everything still works
- Then push that branch to the working repository
To get a list of commits of interest for a given branch, you can use git log
to display the commit log for any branch in any remote that you have synchronized. For example, to get a commit log for someone else's branch user/danger/add_dangerous_stuff in the working remote that you're interested in testing out:
git log working/user/danger/add_dangerous_stuff
We typically create branches for review that have the pertinent commits at the tip of the branch - that is, the most recent commits. However, if a long-lived branch has merged changes from main over time, you might need to use a tool like tig
to view the changes.
For example, to sign-off on two commits with hashes matching d28dfa2
and a30de02
using a local branch name of openurl-more and push them to a remote branch in the working repo named user/myname/openurl-signoff:
# Ensure you have the latest revision of main $ git fetch --all $ git checkout -b openurl-more origin/main # or if the intention is to backport to the rel_2_1 release: # git checkout -b openurl-more_rel_2_1 origin/rel_2_1 $ git cherry-pick -s d28dfa2 $ git cherry-pick -s a30de02 # Test # Test some more # Test some more $ git push working openurl-more:user/myname/openurl-signoff
Evergreen.git and OpenSRF.git
The following conventions apply to both Evergreen and OpenSRF. For the sake of concision, only Evergreen will be named in the forgoing.
Branches
The tip of Evergreen development is main
, while branches that start with rel_
are maintenance branches for release series. Branches that start with tags/
are legacies of Evergreen's previous Subversion repository, and should not be confused with Git tags.
Community Git Repository
http://git.evergreen-ils.org is the main community repository and is used for the following:
- the main Evergreen, Evergreen documentation, and OpenSRF repositories
- Evergreen and OpenSRF contribs
- Working trees of any of the above maintained by individuals and organizations
- Mirrors of Git repos of dependencies used by Evergreen or OpenSRF
- Working trees of related projects, e.g., OpenNCIP.
Any individual or group who wishes to have a repository hosted on the community Git server can request one. All repositories must meet the following conditions:
- They must be relevant to the Evergreen project.
- They may only contain free and open source software or, in the case of documentation, images, and other non-software artifacts, must be licensed under an appropriate open license such as CC-BY-SA or CC0.
To request a new repository, please email the open-ils-dev mailing list.
Working Repos
Working repos are intended for use by individual developers.
Any developer that has submitted their public key can push to user or collab branches on a working repo.
User branches start with user/USER/ where USER is the developer's username, as known by the git server. Only the user who created the branch can push to it.
Collab branches, on the other hand, start with collab/USER/ where USER is the initial developer's username, as known by the git server. Only the user who created the branch can non-ff push or delete it, but anyone can push to it otherwise.
In some cases the username is simple, in others it is an email address. If you do not know your username you can ask one of the git administrators, and they will be glad to inform you.
To track these repositories, you might do the following:
# with ssh keys, to push branches to the working repos git remote add working git@git.evergreen-ils.org:working/Evergreen.git git remote add working_srf git@git.evergreen-ils.org:working/OpenSRF.git git remote add working_sip git@git.evergreen-ils.org:working/SIPServer.git # or without ssh keys, if you just want to send patches git remote add working git://git.evergreen-ils.org/working/Evergreen.git git remote add working_srf git://git.evergreen-ils.org/working/OpenSRF.git git remote add working_sip git://git.evergreen-ils.org/working/SIPServer.git # then, in both cases, to make git aware of the remote branches git fetch working
Examples, assuming the working repo is set up as "working" as above and dealing with git user "mrgit":
To push "myfeature" as a user branch:
git push working myfeature:user/mrgit/myfeature
To push "myfeature" as a collab branch:
git push working myfeature:collab/mrgit/myfeature
To checkout a local copy of a user branch:
git checkout -b theirfeature working/user/mrgit/myfeature
To checkout a local copy of a collab branch:
git checkout -b theirfeature working/collab/mrgit/myfeature
To merge from a user branch:
git merge working/user/mrgit/myfeature
To merge from a collab branch:
git merge working/collab/mrgit/myfeature
To delete a user branch:
git push working :user/mrgit/myfeature
To delete a collab branch:
git push working :collab/mrgit/myfeature
Adding a Sign-off to a new feature in a Collab branch
Note: Assumes developer has submitted their public key to the Git administrators
Add a branch entitled "working"
git remote add working git@git.evergreen-ils.org:working/Evergreen.git
Note: If you've already done this before, you'll get "fatal: remote working already exists." – Just ignore it.
Make git aware of the remote branch(es)
git fetch working
Make sure we're up to date
git pull
Checkout the feature ("myfeature") we'll be signing off on, locally
git checkout -b myfeature working/collab/someuser/myfeature
Amend the commit message, to add our signoff
git commit --amend -s
Push our signoff back to a new branch
git push working penalty_null_display:user/mrgit/myfeature
Git administrators
To request a repository, please email gitadmin@evergreen-ils.org.
The people who currently have access to maintain the Git server and create new repositories (and who listen to the gitadmin@evergreen-ils.org address) are:
- Galen Charlton
- Jason Stephenson
Helpful Scripts
Git supports creating custom commands by adding scripts to your path. These scripts take the name git-command and are then run as git command [<args>].
We have some potentially helpful ones here. They can all be installed in, for example, /usr/local/bin (or anywhere else in your path).
Git URL
This script provides an easy way to share "how to use this branch" information with others. It defaults to the currently checked out branch, but can take any branch name as an argument.
Example:
# git url origin/main For sharing origin/main via the remote repo origin: Change remote_name as appropriate in the below commands. You need only add the remote once, regardless of how many branches you wish to look at. To add this repo as remote_name: Read-only (git protocol): git remote add remote_name git://git.evergreen-ils.org/Evergreen.git Read-write (ssh protocol): git remote add remote_name git@git.evergreen-ils.org:Evergreen.git Once you have the remote added you can check out this branch: git checkout -b main remote_name/main
- git-url
#!/bin/bash # Target Branch # Defaults to HEAD giturltarget=${1:-HEAD} giturlreference="the current branch" if [ "$giturltarget" != "HEAD" ]; then giturlreference=$giturltarget fi # Current rev: giturlcurrev=`git rev-list --max-count=1 $giturltarget` # Find all remote branches that have the current rev as their tip for giturlremote in `git remote` do giturlhasrev=`git ls-remote $giturlremote | grep "$giturlcurrev.*refs/heads/" | sed 's|.*refs/heads/||'` if [ "$giturlhasrev" ]; then echo "For sharing $giturlreference via the remote repo $giturlremote:" echo "" giturlremoteurl=`git config -l | grep ${giturlremote}.url | cut -f2 -d= | sed 's/\\([^@]*@\\|[^:]*:\\/\\/\\)\\([^:\\/]*\\)[:\\/]\\(.*\\)/\\2:\\3/'` if [ "$giturlremote" == "origin" ]; then giturlremote=remote_name echo "Change remote_name as appropriate in the below commands." echo "" fi echo "You need only add the remote once, regardless of how many branches you wish to look at." echo "To add this repo as $giturlremote:" echo " Read-only (git protocol):" echo " git remote add $giturlremote git://`echo $giturlremoteurl | sed 's/:/\\//'`" echo " Read-write (ssh protocol):" echo " git remote add $giturlremote git@$giturlremoteurl" echo "" echo "Once you have the remote added you can check out this branch:" giturlshowor= for giturlbranch in $giturlhasrev do if [ "$giturlshowor" ]; then echo "or" fi giturlshortbranch=`echo $giturlbranch | sed 's|.*/||'` echo "git checkout -b $giturlshortbranch $giturlremote/$giturlbranch" giturlshowor=yes done echo "" fi done
Git pushworking/pushcollab
These two scripts are designed to make it easier to push branches to the "working" repos. They do require some configuration:
- Add the working repo with SSH
- Set the name of the working repo: git config openils.gitpushworkingrepo <repo name> (ex: git config openils.gitpushworkingrepo working-eg) - If you named the repo "working" you can skip this step
- Set your git username (for the server, not locally): git config openils.gitpushworkinguser <user name> (ex: git config openils.gitpushworkinguser mrgit)
Once you have done the above you can use the commands:
# git pushworking localbranch - Will push "localbranch" to "user/<user name>/localbranch" # git pushcollab localbranch - Will push "localbranch" to "collab/<user name>/localbranch" # git pushworking localbranch:remotebranch - Will push "localbranch" to "user/<user name>/remotebranch" # git pushcollab localbranch:remotebranch - Will push "localbranch" to "collab/<user name>/remotebranch" Note that you can use a space instead of a colon in the previous two # git pushworking +localbranch - Will *force* push "localbranch" to "user/<user name>/localbranch" # git pushcollab +localbranch - Will *force* push "localbranch" to "collab/<user name>/localbranch" The + modifier works in all forms of the command when put in front of localbranch to trigger a force push.
- git-pushworking
#!/bin/bash gitpushworkinguser=`git config openils.pushworkinguser` gitpushworkingrepo=`git config openils.pushworkingrepo || echo working` if [ "$gitpushworkinguser" == "" ]; then echo "ERROR: Username not filled in"; echo "Try git config openils.pushworkinguser username"; exit 2; fi if [ -z "$1" ]; then echo "Usage: git pushworking <branch> [<remotebranch>]"; exit 1; fi gitpushworkinglocalbranch=${1%%:*} gitpushworkingremotebranch=${2-${1#+}} git push $gitpushworkingrepo $gitpushworkinglocalbranch:user/$gitpushworkinguser/${gitpushworkingremotebranch##*:}
- git-pushcollab
#!/bin/bash gitpushworkinguser=`git config openils.pushworkinguser` gitpushworkingrepo=`git config openils.pushworkingrepo || echo working` if [ "$gitpushworkinguser" == "" ]; then echo "ERROR: Username not filled in"; echo "Try git config openils.pushworkinguser username"; exit 2; fi if [ -z "$1" ]; then echo "Usage: git pushcollab <branch> [<remotebranch>]"; exit 1; fi gitpushworkinglocalbranch=${1%%:*} gitpushworkingremotebranch=${2-${1#+}} git push $gitpushworkingrepo $gitpushworkinglocalbranch:collab/$gitpushworkinguser/${gitpushworkingremotebranch##*:}