
               Git Wrokflow - 10 Aug 2017


This file describes a typical workflow for SUNDIALS development following the
Gitflow workflow, see:
https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow

* For details on setting up Git and helpful commands for working with Git, see
  the gitCheatSheet.txt file.

In this workflow there are two persistent branches in the repository, 'master'
and 'develop'. Changes to either branch are merged in through pull requests from
short-lived branches. In general, code modifications should be done in smaller
units of work that engage a single issue or feature rather than bundles of many
such issues or features.

* FEATURE BRANCHES: Development of all new features for future releases takes
  place on feature branches created off of the 'develop' branch.

When creating a feature branch to work on, name it with a short, descriptive
name for the single feature being addressed in the branch, e.g.
"Feature/HypreVector" for adding support for a Hypre vector.

* BUGFIX / MAINTENANCE BRANCHES: Patches to the current production release are
  done on bugfix or maintenance branches created off of the 'master' branch.

When creating a bugfix or maintenance branch to work on, name it with either
"bugfix/" or "maintenance/" followed by the corresponding JIRA ticket if one
exists, e.g. "bugfix/SUNDIALS-123", or a short, descriptive name for the issue
being addressed in the branch, e.g. "maintenance/FixingDocumentation".

After the pull request for a branch is approved, the changes will be merged into
the 'develop' branch for feature branches and into both the 'master' and
'develop' branches for bugfixes and maintenance branches. At this point the
local and remote versions of the branch are no longer needed and should be
deleted.

In the following example workflow PARENT is 'develop' for feature branches and
'master' for bugfix/maintenance branches (without the single quotes).

Example workflow:

 1. You cannot work directly on the 'master' or 'develop' branches as you are
    not allowed to push changes to these branches. To start working you must do
    one of the following:

    a) To work on an existing branch, checkout the desired branch:
       > git checkout <branch-name>

    b) Make sure then branch is up to date:
       > git pull

    --- OR ---

    a) To create a new branch to work on, first make sure the PARENT branch is
       up to date:
       > git checkout PARENT
       > git pull

    c) Create a new branch off of the PARENT branch:
       > git checkout -b <branch-name> PARENT

    b) Push the new branch to the remote repo:
       > git push -u origin <branch-name>

    [ NOTE: When checking out a branch, any local changed must be committed (or
      stashed) prior to switching branches ]

 3. Modify files with your editor of choice then stage the files you want to
    commit with:
    > git add <path/file-name>

    Commit changes locally with either of the following depending on the detail
    needed in the commit message:

    a) For short commit messages:
       > git commit -m "Short Description of the Commit"

    --- OR ---

    b) For longer commit messages:
       > git commit

       This opens the default system editor or the editor set in
       .gitconfig, see gitCheatSheet.txt for more information.

       The desired format for a commit message is a short descriptive title
       followed by a blank line, and then a detailed commit message. For
       example, a commit turning on new regression tests might have following
       message:

           Turning on regression tests with 32bit integers

           Updated testing script to run sunindextype = 32bit_t. The following
           regression tests fail:
               *  16 - fark_roberts_dnsL
               *  17 - ark_bruss
               *  38 - fcvAdvDiff_bnd
               *  41 - fcvRoberts_dns
               *  42 - fcvRoberts_dnsL
               * 100 - fidaRoberts_dns
               * 101 - fidaRoberts_dns_openmp

 4. If you are collaborating on a branch with other developers:

    a) To get changes from the remote copy of the branch into your local copy of
       the branch:
       > git pull

       [ NOTE: local changes must be committed prior to pulling remote changes ]

       If there is a conflict during the pull (Git will tell you), follow the
       instruction in step 5b below to resolve the conflicts.

    b) To make your locally committed changes available on the remote copy of
       the branch:
       > git push

       [ NOTE: If changes exist on the remote copy of the branch that you have
         not pulled yet, git will not allow you to push. You must first pull the
         remote changes as described in 4a and then push your local changes. ]

 5. If you need updates from the PARENT branch:

    For longer lived branches it may be necessary to periodically update the
    branch with changes from the PARENT branch:

    a) Fetch changes from the remote PARENT branch and merge them into the
       current branch:
       > git pull origin PARENT

       [ NOTE: local changes must be committed prior to pulling remote changes ]

    b) If there are merge conflicts (Git will tell you):

       b1) View the status of the branch for more info:
           > git status

       b2) Use your editor of choice to resolve any conflicts, then add the
           resolved files:
           > git add <path/file-name>

           --- OR ---

           If you have setup a merge tool in your .gitconfig file (see
           gitCheatSheet.txt for details), start the merge tool:
           > git mergetool

           Git will open each conflicted file in the merge tool one at a time.
           Resolve the conflicts, save the merged file, and close the merge
           tool. Git will then open the next conflicted file. As files are
           resolved and saved they will be automatically added to the merge
           commit.

       b3) When all conflicts are resolved, commit the changes to the local
           branch:
           > git commit

       b4) Push the merge commit to the remote copy of the branch:
           > git push origin <branch-name>

 6. Creating a pull request:

    When a branch is ready to be reviewed for integration into the PARENT branch
    follow the instructions in step 5 to pull in any changes on the remote
    PARENT branch before creating a pull request.

    a) Browse to https://mybitbucket.llnl.gov/projects/SUNDIALS/repos/sunrepo
    b) Click on the branch icon on the left side of screen - you'll see a list
       of all available branches
    c) Click on your branch - you'll see a 'Compare' screen that lets you pick a
       branch (source on top) to merge with another branch (target on bottom)
    d) Select the desired branches and click 'Create pull request'
    e) Edit the title of the pull request (defaults to branch name), add a
       description, and select reviewers that can approve the request
    f) Click 'Create'

 7. The selected reviewers will go over the changes in the pull request and may
    ask for additional changes before merging the branch. To start work on a
    different task while the pull request is under review, return to step 1.

 8. After the pull request is merged, delete the local copy the branch:
    > git checkout PARENT
    > git branch -D <branch-name>

____________________________

Notes on Rebasing

Rebasing is an alternative to merging that replays commits one at a time on top
of the HEAD of another branch (e.g the remote copy of a local branch or the
branch's parent). This rewrites the commit history by reapplying old changes in
a new commit to keep the history linear and avoid a merge commit. Rewriting
history is potentially dangerous and should be done with caution.

1. In step 4a using the '--rebase' option will replay your local commits on top
   of the remote branch:
   > git pull --rebase

   If there are conflicts (Git will tell you), follow the steps below to resolve
   them:

   a) View the status of the branch for more info:
      > git status

   b) Use your editor of choice to resolve any conflicts, then add the resolved
      files:
      > git add <path/file-name>

      --- OR ---

      If you have setup a merge tool in your .gitconfig file (see
      gitCheatSheet.txt for details), start the merge tool:
      > git mergetool

      Git will open each conflicted file in the merge tool one at a time.
      Resolve the conflicts, save the merged file, and close the merge tool. Git
      will then open the next conflicted file.

      As files are resolved and saved they will be automatically added to the
      new commit of the old commit being reapplied.

   c) When all conflicts are resolved in this step of the rebase move on to the
      next commit to reapply:
      > git rebase --continue

   After the rebase is complete all of your local changes have been applied on
   top of the remote branch as new commits.

   At this point you may continue working locally or push your changes to the
   remote copy of the branch:
   > git push

   If you choose to continue to working locally and do another 'git pull
   --rebase' later, you will likely have to re-resolve conflicts that occurred
   in the previous rebase. In this case 'git rerere' can be used to have Git
   remember how conflicts were resolved previously.

2. In step 5 you should *NOT* use 'git pull --rebase'. In this case ALL of the
   commits (local and remote) on <branch-name> will be replayed on the PARENT
   branch.

   Unlike case 1 above where only local changes are being rebased, this case is
   rewriting commits that have been pushed and is therefore changing the history
   that others have pulled and are working on. This will cause significant
   problems for other developers and muddy the commit history.
