Developing with Git
Subscribe

From OpenNMS

(Redirected from Checkout the Source Code)
Jump to: navigation, search

As of January 1, 2010, OpenNMS is now using Git as its primary SCM.

Browsing Git

You can browse our Git repository at GitHub.

Install the Git source code management tool

Install Git as appropriate for your platform.

On Debian/Ubuntu systems, the following command will install Git.

sudo apt-get install git

Getting OpenNMS by forking the GitHub repository

As of 2014, the preferred method for OpenNMS developers to receive code contributions is for you (a potential contributor) to create a GitHub site account and then fork the GitHub repository into a private repository instead of cloning the main opennms repository directly.

Forking the opennms repository creates a private copy of OpenNMS that you can change and commit to that is tied to your github account.

To create a private fork, go to https://github.com/OpenNMS/opennms and then click the "Fork" button in the upper right. This will create a private fork of the codebase.

https://help.github.com/articles/fork-a-repo

Then, check out *your fork* of the code. So instead of checking out:

https://github.com/OpenNMS/opennms.git

you would check out:

https://github.com/my-github-username/opennms.git

For example:

$ mkdir src
$ cd src
$ git clone https://github.com/my-github-username/opennms.git
... (a directory "opennms" will be created below the current directory)
$ cd opennms

Then commit any desired changes to that fork using 'git commit' (where you will have commit access since it's your private fork or copy of the code) and use the instructions in the article below to notify us of the changes as a 'pull request'.

Then we can review them on github and merge them into the OpenNMS/opennms.git repository.

https://help.github.com/articles/using-pull-requests

Getting OpenNMS by cloning the GitHub repository

First, you must clone the OpenNMS Git repository.

This command is the usual one for people without read-write access to the repository:

$ git clone git://github.com/OpenNMS/opennms.git
... (a directory "opennms" will be created below the current directory)
$ cd opennms

If you have commit access to the OpenNMS repository, you can clone it read-write instead:

$ git clone git@github.com:OpenNMS/opennms.git
... (a directory "opennms" will be created below the current directory)
$ cd opennms

Unlike Subversion, when you clone a git repository, you have all of the commit history back to the creation of the codebase, as well as access to any branches and tags defined in the remote repository. That means that it is possible to do development on multiple portions of the OpenNMS codebase without needing network access. You can commit changes locally as necessary, without having to go back and forth to the upstream server.

Getting Started with Git

If you are starting without any Git experience, "man gittutorial" or look through the tutorial online. "Everyday GIT With 20 Commands Or So" is another good beginning reference.

Configuring Git

There are some things you should do to configure Git for your repository before you go any further. Ensure you are in the "opennms" top-level source code directory.

First, configure it to know who you are:

$ git config user.name "FirstName LastName"
$ git config user.email "user@example.com"

Or, if you have many git repositories under your current user, you can set this for all of them

$ git config --global user.name "FirstName LastName"
$ git config --global user.email "user@example.com"

If you want pretty colors, you can setup the following for branch, status, and diff commands:

$ git config --global color.branch "auto"
$ git config --global color.status "auto"
$ git config --global color.diff "auto"

Next, if you are comfortable with the way Subversion works, you will probably want to configure Git to push changes to the same location they are branched from:

$ git config push.default tracking

Working with Branches

The OpenNMS Git Repository Branches

There are 2 primary branches in the OpenNMS git repository, representing different stages in development.

1.12
The 1.12 branch is for doing small bugfixes or features suitable for inclusion in a future stable release.
master 
The master branch is for general development of new features that will be going into the next major version of OpenNMS.

In your local git repository, these are accessible as "remote" branches, i.e., branches that reference a location on a remote repository (in this case, the OpenNMS git repository).

Listing Branches

For a full list of branches in your cloned repository, use git branch -a:

$ git branch -a
* master
  remotes/origin/1.10
  remotes/origin/1.10-GpMonitor
  remotes/origin/1.12
  ...
  remotes/origin/HEAD -> origin/master
  ...

To view just your local branches, leave the -a flag off. The "master" branch is the default initial branch

$ git branch
* master

Working on a Branch

If you are used to Subversion, you will notice that branches work a bit differently in Git. Remote branches are not directly accessible, since they represent the state of a branch in another Git repository. If you attempt to check one out directly, you will get a warning:

$ git checkout remotes/origin/1.10
Note: moving to 'remotes/origin/1.10' which isn't a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
  git checkout -b <new_branch_name>
HEAD is now at 2047359... make sure that if pkg is null we return false

Instead, what you want to do is create a local branch from the remote one, using the syntax, "git checkout -b <new_branch_name> [source_branch_name]":

$ git checkout -b 1.12.3 remotes/origin/rc/stable/1.12.3

This created a local branch called "1.12.3" based on the remote branch "remotes/origin/rc/stable/1.12.3".

Note that it says it is set up to track the remote branch. That means that Git knows that your branch was created from the remote branch, and will automatically know what to do if you wish to push changes to that branch.

Now when you do a "git branch" it will show that your active branch is the one you created:

$ git branch
* 1.12.3
  master

Cleaning up after switching branches

Switching between two branches that are based on very different remote branches (e.g. 1.12.3 and master) may leave stuff from the switched-from branch in your filesystem that is not present in the switched-to branch. The following commands are useful for correcting this problem; note that running them causes all uncommitted changes in your current branch to be lost:

$ git reset --hard HEAD
$ git clean -f -d -x

Getting Updates

To get the latest updates from the remote origin in your tree, run "git pull":

$ git pull
Already up-to-date.

This will retrieve any changes that have been made and apply them to your repository.

Making Changes

Git is slightly different from SVN in that by default, no changes you make to files will be committed unless you specifically "git add" them. Otherwise, you will get something like this from "git status":

In the following example, two local files have been changed compared to the upstream repository.

$ git status
# On branch 1.12.3
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   debian/changelog
#       modified:   debian/control
#
no changes added to commit (use "git add" and/or "git commit -a")

If you are only modifying files, you can just run

git commit -a

when it's time to commit your changes, and it will automatically "git add" any modified files. Note that this does not add any new files or directories that have been created, however.

Also note, this is only committing files to your local repository. Once you have your local branch to your liking, it's time to push the changes back upstream.

After committing changes, "git status" will show your local commit status as 1 commit ahead of the upstream repository.

$ git status
# On branch 1.12.3
# Your branch is ahead of 'origin/rc/stable/1.12.3' by 1 commit.
#
nothing to commit (working directory clean)

Pushing Changes Upstream

First of all, if you're going to submit patches, please fill out the OpenNMS Contributor Agreement.

No Commit Access

If you do not have commit access, you can still easily submit patches to the project, thanks to Git's easy formatting of changes.

Just run

git format-patch -M -C <source-branch>

to generate a set of commit patch files between the source branch and your current branch. (Note: The -M flag is necessary to track file renames):

$ git format-patch -M -C remotes/origin/1.10
0001-testing-commits.patch
0002-removing-that-line-again.patch

Each commit gets a file which contains the patch, as well as some metadata (in the form of a standard email) that makes it easy to import into someone's git repository.

 $ cat 0001-testing-commits.patch
 From 26ed1d96e18db80ff76d0f462bb4b33b648e94e5 Mon Sep 17 00:00:00 2001
 From: Benjamin Reed <rangerrick@befunk.com>
 Date: Tue, 22 Dec 2009 15:41:05 -0500
 Subject: [PATCH 1/2] testing commits
 
 ---
  README.build |    1 +
  1 files changed, 1 insertions(+), 0 deletions(-)
 
 diff --git a/README.build b/README.build
 index b82d49b..cc57eb8 100644
 --- a/README.build
 +++ b/README.build
 @@ -1 +1,2 @@
  See the instructions at http://www.opennms.org/index.php/Building_OpenNMS
 +
 -- 
 1.6.3.3

Just open a bug in JIRA as an enhancement, and attach your patches.

If you want to get fancy, see this page for details on how to "rewrite history" so you can have one patch per feature.

No Commit Access, using a git pull-request

TODO: Document submitting a pull-request.

With Commit Access

If you have commit access, all you need to do is run "git push" from your branch. If you have configured "push.default" as above, you don't need to give it any arguments:

 $ git push

Recommended Workflow

Branch from Stable or Unstable

If you are working on a new feature, it is recommended that you branch from the appropriate version (1.10 - stable, or master - unstable) depending on the scope of your feature.

 $ git checkout -b feature-new-awesome-thing remotes/origin/master
 Branch feature-new-awesome-thing set up to track remote branch master from origin.
 Switched to a new branch 'feature-new-awesome-thing'

Make Changes

Create your changes as normal, editing/adding/removing files, and committing them to the local repository with "git commit".

You can update your branch with the latest changes by doing a "git pull":

 $ git pull
 Already up-to-date.

Make Your Branch Public

When you are ready for your code to be accessible by other people, you can push your feature branch like so:

 $ git push [--verbose] origin feature-new-awesome-thing
 Pushing to git@github.com:OpenNMS/opennms.git
 Counting objects: 5, done.
 Delta compression using up to 2 threads.
 Compressing objects: 100% (3/3), done.
 Writing objects: 100% (3/3), 283 bytes, done.
 Total 3 (delta 2), reused 0 (delta 0)
 To git@github.com:OpenNMS/opennms.git
    2047359..732c8a5  feature-new-awesome-thing -> feature-new-awesome-thing
 updating local tracking ref 'refs/remotes/origin/feature-new-awesome-thing'

This will create a "feature-new-awesome-thing" branch in remotes/origin/ based on your changes, and now other people can check it out as well, after a "git pull".

Get Changes

In the case of this example, our branch, "feature-new-awesome-thing" is tracking master. However, if you've pushed your branch to the upstream so you can collaborate with other people, it's possible they've made changes as well. You can merge any changes made to the remote branch by using "git pull" with arguments:

 $ git pull origin feature-new-awesome-thing
 From git@github.com:OpenNMS/opennms.git
  * branch            feature-new-awesome-thing        -> FETCH_HEAD
 Already up-to-date.

Merging the Code Upstream

When it's time for the code in the branch to be merged, check out the appropriate branch (creating it locally if it doesn't exist already) and pull the changes from your branch.

It is important to always use --squash on your commits so they can be easily cherry-picked to another branch if necessary.

 # make sure everything's up-to-date
 git pull
 git checkout master
 # this will take all of your commits on your branch and turn them into 1 commit on your master
 git merge --squash feature-new-awesome-thing
 git commit

...then push them to the upstream repository:

 $ git push origin
 Total 0 (delta 0), reused 0 (delta 0)
 To git@github.com:OpenNMS/opennms.git
    2047359..732c8a5  master -> master

If you're done with the feature branch, you can delete it.

To delete the local branch, use "git branch -D":

 $ git branch -D feature-new-awesome-thing
 Deleted branch feature-new-awesome-thing (was 732c8a5).

To delete the remote branch, the syntax is a little funky, since it's just like pushing a branch: "git push origin <local-branch>:<remote-branch>". In this case, you push nothing (an empty string) as the local branch:

 $ git push origin :feature-new-awesome-thing
 To git@github.com:OpenNMS/opennms.git
  - [deleted]         feature-new-awesome-thing

Resources

There are a lot of other resources for help with git:

Additionally, every single git command has pretty extensive documentation. Just run "git help <command>" for help with a given command.

 usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]
 
 The most commonly used git commands are:
    add        Add file contents to the index
    bisect     Find by binary search the change that introduced a bug
    branch     List, create, or delete branches
    checkout   Checkout a branch or paths to the working tree
    clone      Clone a repository into a new directory
    commit     Record changes to the repository
    diff       Show changes between commits, commit and working tree, etc
    fetch      Download objects and refs from another repository
    grep       Print lines matching a pattern
    init       Create an empty git repository or reinitialize an existing one
    log        Show commit logs
    merge      Join two or more development histories together
    mv         Move or rename a file, a directory, or a symlink
    pull       Fetch from and merge with another repository or a local branch
    push       Update remote refs along with associated objects
    rebase     Forward-port local commits to the updated upstream head
    reset      Reset current HEAD to the specified state
    rm         Remove files from the working tree and from the index
    show       Show various types of objects
    status     Show the working tree status
    tag        Create, list, delete or verify a tag object signed with GPG
 
 See 'git help COMMAND' for more information on a specific command.