add contribution guide focused on Git and PRs (#1664)
This commit is contained in:
parent
83a074eea6
commit
2ccb3d5531
247
lib/spack/docs/contribution_guide.rst
Normal file
247
lib/spack/docs/contribution_guide.rst
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
.. _contribution-guide:
|
||||||
|
|
||||||
|
Contribution Guide
|
||||||
|
=====================
|
||||||
|
|
||||||
|
This guide is intended for developers or administrators who want to
|
||||||
|
contribute a new package, feature, or bugfix to Spack.
|
||||||
|
It assumes that you have at least some familiarity with Git VCS and Github.
|
||||||
|
The guide will show a few examples of contributing workflow and discuss
|
||||||
|
the granularity of pull-requests (PRs).
|
||||||
|
|
||||||
|
First, what is a PR? Quoting `Bitbucket's tutorials <https://www.atlassian.com/git/tutorials/making-a-pull-request/>`_:
|
||||||
|
|
||||||
|
Pull requests are a mechanism for a developer to notify team members that they have **completed a feature**.
|
||||||
|
The pull request is more than just a notification—it’s a dedicated forum for discussing the proposed feature
|
||||||
|
|
||||||
|
Important is completed feature, i.e. the changes one propose in a PR should
|
||||||
|
correspond to one feature/bugfix/extension/etc. One can create PRs with
|
||||||
|
changes relevant to different ideas, however reviewing such PRs becomes tedious
|
||||||
|
and error prone. If possible, try to follow the rule **one-PR-one-package/feature.**
|
||||||
|
|
||||||
|
Spack uses a rough approximation of the `Git Flow <http://nvie.com/posts/a-successful-git-branching-model/>`_ branching
|
||||||
|
model. The develop branch contains the latest contributions, and master is
|
||||||
|
always tagged and points to the latest stable release. Thereby when you send
|
||||||
|
your request, make ``develop`` the destination branch on the
|
||||||
|
`Spack repository <https://github.com/LLNL/spack>`_.
|
||||||
|
|
||||||
|
Let's assume that the current (patched) state of your fork of Spack is only
|
||||||
|
relevant to yourself. Now you come across a bug in a package or would like to
|
||||||
|
extend a package and contribute this fix to Spack. It is important that
|
||||||
|
whenever you change something that might be of importance upstream,
|
||||||
|
create a pull-request (PR) as soon as possible. Do not wait for weeks/months to
|
||||||
|
do this: a) you might forget why did you modified certain files; b) it could get
|
||||||
|
difficult to isolate this change into a stand-alone clean PR.
|
||||||
|
|
||||||
|
Now let us discuss several approaches one may use to submit a PR while
|
||||||
|
also keeping your local version of Spack patched.
|
||||||
|
|
||||||
|
|
||||||
|
First approach (cherry-picking):
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
First approach is as follows.
|
||||||
|
You checkout your local develop branch, which for the purpose of this guide
|
||||||
|
will be called ``develop_modified``:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git checkout develop_modified
|
||||||
|
|
||||||
|
Let us assume that lines in files you will be modifying
|
||||||
|
are the same in `develop_modified` branch and upstream ``develop``.
|
||||||
|
Next edit files, make sure they work for you and create a commit
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git add <files_to_be_commited>
|
||||||
|
$ git commit -m <descriptive note about changes>
|
||||||
|
|
||||||
|
Normally we prefer that commits pertaining to a package ``<package-name>``` have
|
||||||
|
a message ``<package-name>: descriptive message``. It is important to add
|
||||||
|
descriptive message so that others, who might be looking at your changes later
|
||||||
|
(in a year or maybe two), would understand the rationale behind.
|
||||||
|
|
||||||
|
|
||||||
|
Next we will create a branch off upstream's ``develop`` and copy this commit.
|
||||||
|
Before doing this, while still on your modified branch, get the hash of the
|
||||||
|
last commit
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git log -1
|
||||||
|
|
||||||
|
and copy-paste this ``<hash>`` to the buffer. Now switch to upstream's ``develop``,
|
||||||
|
make sure it's updated, checkout the new branch, apply the patch and push to
|
||||||
|
GitHub:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git checkout develop
|
||||||
|
$ git pull upstream develop
|
||||||
|
$ git checkout -b <descriptive_branch_name>
|
||||||
|
$ git cherry-pick <hash>
|
||||||
|
$ git push <your_origin> <descriptive_branch_name> -u
|
||||||
|
|
||||||
|
Here we assume that local ``develop`` branch tracks upstream develop branch of
|
||||||
|
Spack. This is not a requirement and you could also do the same with remote
|
||||||
|
branches. Yet to some it is more convenient to have a local branch that
|
||||||
|
tracks upstream.
|
||||||
|
|
||||||
|
Now you can create a PR from web-interface of GitHub. The net result is as
|
||||||
|
follows:
|
||||||
|
|
||||||
|
#. You patched your local version of Spack and can use it further
|
||||||
|
#. You "cherry-picked" these changes in a stand-alone branch and submitted it
|
||||||
|
as a PR upstream.
|
||||||
|
|
||||||
|
|
||||||
|
Should you have several commits to contribute, you could follow the same
|
||||||
|
procedure by getting hashes of all of them and cherry-picking to the PR branch.
|
||||||
|
This could get tedious and therefore there is another way:
|
||||||
|
|
||||||
|
|
||||||
|
Second approach:
|
||||||
|
----------------
|
||||||
|
|
||||||
|
In the second approach we start from upstream ``develop`` (again assuming
|
||||||
|
that your local branch `develop` tracks upstream):
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git checkout develop
|
||||||
|
$ git pull upstream develop
|
||||||
|
$ git checkout -b <descriptive_branch_name>
|
||||||
|
|
||||||
|
Next edit a few files and create a few commits by
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git add <files_to_be_part_of_the_commit>
|
||||||
|
$ git commit -m <descriptive_message_of_this_particular_commit>
|
||||||
|
|
||||||
|
Now you can push it to your fork and create a PR
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git push <your_origin> <descriptive_branch_name> -u
|
||||||
|
|
||||||
|
Most likely you would want to have those changes in your (modified) local
|
||||||
|
version of Spack. To that end you need to merge this branch
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git checkout develop_modified
|
||||||
|
$ git merge <descriptive_branch_name>
|
||||||
|
|
||||||
|
The net result is similar to the first approach with a minor difference that
|
||||||
|
you would also merge upstream develop into you modified version in the last
|
||||||
|
step. Should this not be desirable, you have to follow the first approach.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
How to clean-up a branch by rewriting history:
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
Sometimes you may end up on a branch that has a lot of commits, merges of
|
||||||
|
upstream branch and alike but it can't be rebased on ``develop`` due to a long
|
||||||
|
and convoluted history. If the current commits history is more of an experimental
|
||||||
|
nature and only the net result is important, you may rewrite the history.
|
||||||
|
To that end you need to first merge upstream `develop` and reset you branch to
|
||||||
|
it. So on the branch in question do:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git merge develop
|
||||||
|
$ git reset develop
|
||||||
|
|
||||||
|
At this point you your branch will point to the same commit as develop and
|
||||||
|
thereby the two are indistinguishable. However, all the files that were
|
||||||
|
previously modified will stay as such. In other words, you do not loose the
|
||||||
|
changes you made. Changes can be reviewed by looking at diffs
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git status
|
||||||
|
$ git diff
|
||||||
|
|
||||||
|
One can also run GUI to visualize the current changes
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git difftool
|
||||||
|
|
||||||
|
Next step is to rewrite the history by adding files and creating commits
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git add <files_to_be_part_of_commit>
|
||||||
|
$ git commit -m <descriptive_message>
|
||||||
|
|
||||||
|
|
||||||
|
Shall you need to split changes within a file into separate commits, use
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git add <file> -p
|
||||||
|
|
||||||
|
After all changed files are committed, you can push the branch to your fork
|
||||||
|
and create a PR
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git push <you_origin> -u
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
How to fix a bad rebase by "cherry-picking" commits:
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
Say you are working on a branch ``feature1``. It has several commits and is
|
||||||
|
ready to be merged. However, there are a few minor merge conflicts and so
|
||||||
|
you are asked to rebase onto ``develop`` upstream branch. Occasionally, it
|
||||||
|
happens so that a contributor rebases not on top of the upstream branch, but
|
||||||
|
on his/her local outdated copy of it. This would lead to an inclusion of the
|
||||||
|
whole lot of duplicated history and of course can not be merged as-is.
|
||||||
|
|
||||||
|
One way to get out of troubles is to ``cherry-pick`` important commits. To
|
||||||
|
do that, first checkout a temporary back-up branch:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
git checkout -b tmp
|
||||||
|
|
||||||
|
Now look at logs and save hashes of commits you would like to keep
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
git log
|
||||||
|
|
||||||
|
Next, go back to the original branch and reset it to ``develop``.
|
||||||
|
Before doing so, make sure that you local ``develop`` branch is up-to-date
|
||||||
|
with the upstream.
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
git checkout feature1
|
||||||
|
git reset --hard develop
|
||||||
|
|
||||||
|
Now you can cherry-pick relevant commits
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
git cherry-pick <hash1>
|
||||||
|
git cherry-pick <hash2>
|
||||||
|
|
||||||
|
|
||||||
|
push the modified branch to your fork
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
git push -f
|
||||||
|
|
||||||
|
and if everything looks good, delete the back-up:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
git branch -D tmp
|
@ -60,6 +60,7 @@ or refer to the full manual below.
|
|||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
:caption: Contributing to Spack
|
:caption: Contributing to Spack
|
||||||
|
|
||||||
|
contribution_guide
|
||||||
packaging_guide
|
packaging_guide
|
||||||
developer_guide
|
developer_guide
|
||||||
API Docs <spack>
|
API Docs <spack>
|
||||||
|
Loading…
Reference in New Issue
Block a user