Development » Git
All new development work should be done against current git code. The master branch is considered the mainline, authoritative branch that will eventually become the next release.
You can use the Horde Git repository as an anonymous user or as a developer.
You will need a Git client, if you don't already have one. Information on Git can be found at http://git-scm.com/.
These command lines should be the bare-bones needed to get you started with Horde and Git; this is not a Git tutorial, however. The standard Git documentation is available here. Additional tips and useful links can be found at git ready and 25 Tips for Intermediate Git Users.
Anonymous Git access is available via GitHub using the git:// protocol.
To clone a repository, use the following command:
git clone --depth 1 git://github.com/horde/[REPO]
where REPO is one of the available repositories listed above. The --depth 1 option creates a shallow clone rather than downloading the whole repository; this saves significant storage space on your local machine and requires less network bandwidth during the initial transfer. The disadvantage is that the full repository history will not be available on your local machine, you cannot clone or fetch from it, nor push from nor into it (none of these activities are generally useful for anonymous repositories anyway). If you do want the full repository, simply omit --depth 1.
To update the repository, enter the repository directory and use this command:
Making Development Repos Web-Accessible
Make sure you have cloned the horde repo. Once initialized, creating a web-accessible development installation can be done simply by running the install_dev PHP script located at horde-git/framework/bin. To properly run this script, the Horde_Role package must be installed and a local copy of install_dev.conf must be created on your system, with the variables inside that file edited as necessary to apply to your system.
pear channel-discover pear.horde.org pear install horde/horde_role cd /path/to/horde-git/framework/bin cp install_dev.conf.dist install_dev.conf vi install_dev.conf (replace vi with your favorite editing tool) ./install_dev
Running that script will symlink the entire horde package into the web-accessible directory you specified in install_dev.conf, symlink all other Horde applications within that directory, and will properly set up the necessary include/horde path definitions. Note that all edits should take place within the repository, as the web-accessible directory will be deleted every time the install_dev script is run.
Full directory paths will be needed in horde-git/horde/config/registry.php due to the symlinks. The easiest way to setup full paths is to set the $app_fileroot parameter in this file.
Note that unlike a PEAR install, the Autoloader_Cache package will be enabled by default. If you attempt to use Horde or load the test.php page before all PEAR dependencies are installed, you will have to purge the autoloader cache.
You can now follow the procedures in the normal INSTALL document to complete the configuration and database creation.
If, after you have configured Horde, you wish you can manually run the database migrations, you can run these from the checkout directory as so:
./horde/bin/horde-db-migrate [application_name [up|down]]
If installing the framework libraries directly via PEAR, i.e. not with with install_dev, you will need to define your horde application directory (i.e. the filesystem directory where the Horde application is installed and accessible to a browser) in your PEAR config. This can be done with the horde/Role package previously installed on your system via:
pear run-scripts horde/Horde_Role
To submit patches, first make the changes in your local repository. You will need to commit these changes locally. After committing, use the following command:
git format-patch -M -B origin
This command creates a separate patch file for each commit that exists locally on your machine but does not exist in the master Horde branch (origin). These patch files will be located in your local directory.
Access to the live Git repository is only available over SSH. You will want to create an SSH key and use that with your account on dev.horde.org to avoid having to enter your password on every pull/push.
You will also need to create an account on GitHub as the master repo will be mirrored to GitHub every time a commit is pushed. The following needs to be done:
- Create a GitHub account.
- Setup your SSH public key. This SSH key must exist in your github.com account.
- Make sure the github host key is stored in your git.horde.org account.
- Join the Horde organization on GitHub (send e-mail to email@example.com).
To clone a repository, use this command:
git clone ssh://dev.horde.org/horde/git/[REPO]
where REPO is one of the available repositories listed above.
This will create a REPO directory in your current directory. Once completed, an up to date copy of the master Git repository will be available on your system. You must use the SSH protocol rather than the git protocol because the Horde Git repository only supports pushing commits through SSH. (Since Git will automatically use the protocol used to clone the repository for all future push/pull operations, it is easiest to set your local repository up correctly from the beginning.)
To update your local repository, you MUST rebase the changes on top of your local repo copy. Failure to do so will result in useless, annoying commit merge messages both added to the master repository and sent in the commit e-mails.
To update/rebase the changes, you can use the following command:
git pull --rebase
Better still, to prevent an unnecessary merge, you can configure git pull to always rebase when pulling for a particular repo by using the following command:
git config branch.[reponame].rebase true
One disadvantage of git pull is that (as of Git v184.108.40.206) it does not indicate which files are updated. To see a list of files that are updated, you should run these two commands instead:
git fetch git rebase -v origin
A helpful alias for
.gitconfigto update your local repository while seeing changed files and avoiding conflicts is:
[alias] get = !BRANCH=$(git branch -vv | grep ^\\* | sed -r 's/^[^+\\[([^]:]+).+$/\\1/') && git fetch && ( git rebase -v $BRANCH || ( git stash && ( git rebase -v $BRANCH || echo "WARNING: Run 'git stash pop' manually!" ) && git stash pop ) )
For more information on rebasing, and the commands needed if conflicts are detected during the rebase/merge, see: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#using-git-rebase and http://jbowes.dangerouslyinc.com/2007/01/26/git-rebase-keeping-your-branches-current/.
First, you should make sure your contact information is correct. The easiest way to do so is to issue the following commands:
git config user.name "FirstName LastName" git config user.email "firstname.lastname@example.org"
Go ahead and hack away. When finished, commit the files to your local repo. There are several ways to do this. To add specific files to a commit, use the following commands:
git add filename [filename2] [filename3...] git commit
git add has many powerful tools to indicate what files or portions of a file you want to commit: the -i option (interactive mode), and -p option (patch mode) are good examples. Read the man page for further information on these options (and others).
You can also list the files to be committed on the command line to commit:
git commit [filename1] [filename2] ... [filenameX]
If you want to commit all modified files, you can use the following shortcut command:
git commit -a
If you want to commit all modified files, and want a shortcut to also specify the commit message on the command line, use the following command:
git commit -a -m "[commit message]"
Once you finish with your local commits and want to push them to the master repository, use the following command:
When pushing, it is most likely the desired action to ONLY push changes to branches that are currently being tracked on the master server. This is the default git behavior, but the following config verifies that the setting is configured properly:
git config push.default matching
Say you are working in a git tree and have previously made some local commits. You then started working on other code and modified several other files. However, you then decide you want to push the previously made commits to the central repository (e.g. those commits fix a critical bug). However, git will not let you push your commits because your tree is not clean.
In the absence of originally using a branch to do the newer hacking, you can easily create a temporary branch, move the work-in-progress to the temporary branch, push your commits to the server, and then re-apply your work-in-progress to the current branch. Git has a wonderful built-in command that will do all this work for you: stash. To stash all work-in-progress on the current tree, use:
When you need to pull the changes back, use:
git stash apply
Stash has many more features that won't be explained here - check the documentation (e.g. working with multiple stashes, popping a stash).
It may often happen that you have many local commits that you want to push to the central repository. It may often be that many of these changes are similar (i.e. nits/doc cleanup/whitespace) or that some of the commits fixed things caused by a previous local, non-pushed, commit. In this case, it may be better to clean up the commit list to make the ultimate project history and commit notification e-mails look nicer. Git provides an easy way to manipulate your local commits:
# origin means edit all commits applied on top of the last pull # from the central repository. git rebase -i origin
Use the 'squash' option to combine multiple commits. Instructions on the edit screen explain the various other features.
Creating/Managing remote branches
It may be useful to share work on a local branch with other developers. For example, a large change that might not yet be ready for primetime, but could benefit for some eyeballs, might be useful to share on a branch rather than the master repo. To create a branch on the master Horde repository, and have your existing topic branch track the remove branch, use the following command:
git push -u origin [localbranch]
Now all users can track this branch by issuing this command:
git checkout -t origin/[remote branch name]
You should keep the topic branch up to date with the main branch during development so that your topic branch only contains the changes related to the work being done in the branch:
git checkout [topic] git merge master # resolve conflicts git pull --rebase git push
During a long-lived branch, you will find yourself having to resolve the same conflicts over and over again. The git tool git-rerere is designed to help alleviate this issue. Once it is enabled, it will automatically take note of each conflict, and it's eventual resolution. Next time git comes across the exact same conflict, it will know on it's own how to resolve it. To use this feature you must explicitly enable it:
git config --global rerere.enabled 1
To delete the remote branch, issue this command:
git push origin :[branchname]
To remove stale remote branches from your branch list, issue this command:
git remote prune origin