Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: one more cleanup of merge-from-master section.

This document provides details on E3SM development conventions and practices.

...

important -- Items colored in red mean they are important, and should not be ignored.

one time -- Items colored in green are commands to be issued once per machine.

repo once -- Items colored in orange are commands to be issued once per local repository.

...

Your PR is not finished until it has been merged to master by the Integrator.

This document can be used to help with pull request related issues.

...

  1. Check the github entry for the PR and make sure it has a good title and description, correct labels and a comment with a link to the Design Document.   A PR can not be merged to next or master unless it has a Design Document with Phase 1 and 2 completed. See /wiki/spaces/CNCL/pages/25231511.
  2. Look at the code changes either on github or using:  git log --reverse -p master.. on your checked out copy of the branch.
    1. Does new code hold up to visual inspection for code quality?    Look over code changes for glaring mistakes or code style issues (e.g. useful comments, reasonable subroutine lengths, new code in an existing file follows conventions of that file).
    2. Check to see if the description of the code changes in the PR match the actual changes.  Make sure nothing unrelated to the PR was committed accidentally.
    3. Although they can't be changed, see if commit messages on the branch follow the Commit message template and let the developer know if they can not.  Consider asking the developer to squash commits to clean up the history.
    4. Have tests been added or suggested that exercise this feature?
    5. Does code run on all platforms after integration into next?

...

Before communicating with remotes, you might want to add or remove remotes. In order to add and remove remotes the git remote command can be used. The two uses are as follows:

git remote add remote-name protocol:address/to/repo # Creates a remote


git remote remove remote-name # Removes a remote

  

In order to communicate with remotes, there are three actions. pushpull, and fetch.

...


git pull <remote-name> <branch-name>

...

Avoid Routine Merges From Master

You never need to "merge from master" to make the eventual merge of your feature branch "easier" or to "keep up".  This is because, unlike  Unlike svn, git is smart enough to ignore changes that have occurred in files you aren't working on when you finally merge your branch to master.  Also, this practice can cause more problems.

This policy is to make it easier on developers - developers dont don't have to concern themselves with a hundred other things going on in E3SM and can focus solely on their feature.  The integrator will evaluate how this feature works with the latest version of E3SM when they merge the feature to 'next', before it is merged to 'master'.   We also don't want unnecessary merges from upstream since they just clutter and confuse the repository history and provide more opportunity to break things in the branch. However, there are cases where merging from master (or better, an upstream release) can make sense - such as a long lived development branch.  The rule of thumb for any merge is that if you can clearly describe what you are merging and why that merge is necessary for your branch to be completed, then it's fine to merge.  But merges without such justification are generally undesirable.   Merging from master to "keep up" or avoid future conflicts is not an acceptable "why". 

There was a discussion and several links on this topic here.   To summarize some of key points:

  • "frequent pulling of the \[master] into a development branch will add a certain amount of randomness to that branch; this randomness is not particularly helpful for somebody who is trying to get a feature working. It also increases the chances that another developer who ends up in the middle of the series while running a bisect operation will encounter unrelated bugs."
  • A branch has a specific purpose. A topic branch 'add-frotz' would be about adding a new 'frotz' feature and shouldn't do anything else.  When you merge from master, you declare that all the other unrelated changes done on 'master' in preparation for the next release somehow bring 'add-frotz' closer to the goal of the 'frotz' topic. That is usually not true
  • Unnecessary merges and similar repository clutter reduces the ability to summarize, audit, notice bugs in review, and find bugs after the fact.  Keeping clean history is not difficult.  It requires a little bit of discipline on the part of integrators and developers, but it's a small price to pay for the time saved and improved quality/reliability.

If you want to see how your feature works with the latest version of master, do a test merge with a throwaway branch.  Update your local version of master,  make a new branch called something like "testmaster" and check it out.   Merge your feature branch to this new branch (which is just a copy of master) and run your tests.   When you're done, you can delete the "testmaster" branch.

If you want to know how an Integrator would merge a branch with conflicts they can't resolve, see Integrator Guide#Resolvingmergeconflicts 

There was a discussion and several links on this topic here.   To summarize some of key points:

  • "frequent pulling of the \[master] into a development branch will add a certain amount of randomness to that branch; this randomness is not particularly helpful for somebody who is trying to get a feature working. It also increases the chances that another developer who ends up in the middle of the series while running a bisect operation will encounter unrelated bugs."
  • A branch has a specific purpose. A topic branch 'add-frotz' would be about adding a new 'frotz' feature and shouldn't do anything else.  When you merge from master, you declare that all the other unrelated changes done on 'master' in preparation for the next release somehow bring 'add-frotz' closer to the goal of the 'frotz' topic. That is usually not true
  • Unnecessary merges and similar repository clutter reduces the ability to summarize, audit, notice bugs in review, and find bugs after the fact.  Keeping clean history is not difficult.  It requires a little bit of discipline on the part of integrators and developers, but it's a small price to pay for the time saved and improved quality/reliability.

There are some cases where merging from master (or better, a tagged version of master) can make sense.  The rule of thumb for any merge is that if you can clearly describe what you are merging and why that merge is necessary for your branch to be completed, then it's fine to merge.    For example, you might need a feature on master (some crucial functionality, not just a build system updates) to complete the feature on your branch.   Integrators may ask you to merge from master to help resolve conflicts during a PR integration.  But before merging from master, try one of the other ways to get features from other peoples development described in Incorporatinganotherbranchontoyourbranch.

If you want to see how your feature works with the latest version of master, do a test merge with a throwaway branch.  Update your local version of master,  make a new branch called something like "testmaster" and check it out.   Merge your feature branch to this new branch (which is just a copy of master) and run your tests.   When you're done, you can delete the "testmaster" branch.  Repeat as necessary.

If you want to know how an Integrator would merge a branch with conflicts they can't resolve, see Integrator Guide#Resolvingmergeconflicts

On conflicts: While git is better at handing merges and branches and resulting conflicts, do not expect that you (or the Integrator) will never encounter a merge conflict. Merge conflicts still exist, and have to be dealt with. No version control tool will be able to automatically resolve a conflict when two people change the same section of code.   If two or more developers need to work on the same piece of code, or code that touches several routines, the way to avoid conflicts is to serialize the development or find the common part and do that first, then make new branches after those changes are committed. 

Git branching model and avoiding conflicts:

One of the main differences between git and svn is how history and branches are stored. In svn branches are virtual directories (i.e. svn copy ^/trunk branch_name) and the history is stored as a stack of revisions (providing the monotonically increasing revision number). The problem with this is that a branch isn't actually a branch. It doesn't contain the information about where it was created from or what has been "merged" into it. The same is true when a branch is merged back into trunk; there isn't a clear historical description of what has already been integrated into trunk. (NOTE: svn has put some effort into improving their branching and merging capabilities, but they are still not up-to-par with DVCS tools)

However, in git the history is stored as a Directed Acyclic Graph (DAG), and branches are first-class citizens. The DAG structure allows any commit to determine which other commits it includes changes from (or which commits have been integrated into it). Using this history structure, git is able to ignore changes from commits that have already been integrated, reducing the number of merge conflicts that occur when bringing in a large set of changes.

On conflicts: While git is better at handing merges and branches and resulting conflicts, do not expect that you (or the Integrator) will never encounter a merge conflict. Merge conflicts still exist, and have to be dealt with. No version control tool will be able to automatically resolve a conflict when two people change the same section of code.   If two or more developers need to work on the same piece of code, or code that touches several routines, the way to avoid conflicts is to serialize the development or find the common part and do that first, then make new branches after those changes are committed. tools)

However, in git the history is stored as a Directed Acyclic Graph (DAG), and branches are first-class citizens. The DAG structure allows any commit to determine which other commits it includes changes from (or which commits have been integrated into it). Using this history structure, git is able to ignore changes from commits that have already been integrated, reducing the number of merge conflicts that occur when bringing in a large set of changes.

Additional References on git merges

...