====== 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 [[http://git.evergreen-ils.org/|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** send ''id_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= ===== 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//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 ===== * [[http://book.git-scm.com/|Git Community Book]] * [[http://wiki.koha-community.org/wiki/Version_Control_Using_Git|Version Control Using Git (from the Koha project)]] * [[http://git-scm.com/course/svn.html|Git-SVN crash course]] ====== 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, and should include a bug number from LaunchPad 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 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 Signed-off-by: Roger Reviewer Signed-off-by: Chris Committer ===== 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 ==== 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 []//. 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 #!/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 (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 (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//localbranch" # git pushcollab localbranch - Will push "localbranch" to "collab//localbranch" # git pushworking localbranch:remotebranch - Will push "localbranch" to "user//remotebranch" # git pushcollab localbranch:remotebranch - Will push "localbranch" to "collab//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//localbranch" # git pushcollab +localbranch - Will *force* push "localbranch" to "collab//localbranch" The + modifier works in all forms of the command when put in front of localbranch to trigger a force push. #!/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 []"; exit 1; fi gitpushworkinglocalbranch=${1%%:*} gitpushworkingremotebranch=${2-${1#+}} git push $gitpushworkingrepo $gitpushworkinglocalbranch:user/$gitpushworkinguser/${gitpushworkingremotebranch##*:} #!/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 []"; exit 1; fi gitpushworkinglocalbranch=${1%%:*} gitpushworkingremotebranch=${2-${1#+}} git push $gitpushworkingrepo $gitpushworkinglocalbranch:collab/$gitpushworkinguser/${gitpushworkingremotebranch##*:}