.. highlight:: bash .. redirect-from:: /devel/gitwash/development_workflow .. redirect-from:: /devel/gitwash/maintainer_workflow .. _development-workflow: #################### Development workflow #################### Workflow summary ================ To keep your work well organized, with readable history, and in turn make it easier for project maintainers (that might be you) to see what you've done, and why you did it, we recommend the following: * Don't make changes in your local ``main`` branch! * Before starting a new set of changes, fetch all changes from ``upstream/main``, and start a new *feature branch* from that. * Make a new branch for each feature or bug fix — "one task, one branch". * Name your branch for the purpose of the changes - e.g. ``bugfix-for-issue-14`` or ``refactor-database-code``. * If you get stuck, reach out on `discourse `__. * When you're ready or need feedback on your code, open a pull request so that the Matplotlib developers can give feedback and eventually include your suggested code into the ``main`` branch. Overview -------- After :ref:`setting up a development environment `, the typical workflow is: #. Fetch all changes from ``upstream/main``:: git fetch upstream #. Start a new *feature branch* from ``upstream/main``:: git checkout -b my-new-feature upstream/main #. When you're done editing, e.g., ``lib/matplotlib/collections.py``, record your changes in Git:: git add lib/matplotlib/collections.py git commit -m 'a commit message' #. Push the changes to your GitHub fork:: git push -u origin my-new-feature .. _update-mirror-main: Update the ``main`` branch ========================== First make sure you have followed :ref:`installing_for_devs`. From time to time you should fetch the upstream changes from GitHub:: git fetch upstream This will pull down any commits you don't have, and set the remote branches to point to the right commit. .. _make-feature-branch: Make a new feature branch ========================= When you are ready to make some changes to the code, you should start a new branch. Branches that are for a collection of related edits are often called 'feature branches'. Making a new branch for each set of related changes will make it easier for someone reviewing your branch to see what you are doing. Choose an informative name for the branch to remind yourself and the rest of us what the changes in the branch are for. For example ``add-ability-to-fly``, or ``bugfix-for-issue-42``. The process for creating a new feature branch is:: # Update the main branch git fetch upstream # Make new feature branch starting at current main git branch my-new-feature upstream/main git checkout my-new-feature If you started making changes on your local ``main`` branch, you can convert the branch to a feature branch by renaming it:: git branch -m Generally, you will want to keep your feature branches on your public GitHub fork of Matplotlib. To do this, you ``git push`` this new branch up to your GitHub repo. Generally, if you followed the instructions in these pages, and by default, git will have a link to your fork of the GitHub repo, called ``origin``. You push up to your own fork with:: git push origin my-new-feature .. _edit-flow: The editing workflow ==================== #. Make some changes #. Save the changes #. See which files have changed with ``git status``. You'll see a listing like this one: .. code-block:: none # On branch ny-new-feature # Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: README # # Untracked files: # (use "git add ..." to include in what will be committed) # # INSTALL no changes added to commit (use "git add" and/or "git commit -a") #. Check what the actual changes are with ``git diff``. #. Add any new files to version control ``git add new_file_name``. #. To commit **all** modified files into the local copy of your repo, type: .. code-block:: bash git commit -am 'A commit message' Note the ``-am`` options to ``commit``. The ``m`` flag signals that you are going to type a message on the command line. The ``a`` flag stages every file that has been modified, except files listed in ``.gitignore``. For more information, see the `git commit `_ manual page. #. To push the changes up to your forked repo on GitHub, do a ``git push``. Verify your changes =================== Check that your change does what you intend. For code changes: * If the issue you are working on provided a code example, run that example against your branch and check that you now get the desired result. Note that adapting the issue example is often a good way to create a new test. * Run the tests to check that your change has not had unintended consequences on existing functionality. See :ref:`run_tests`. For documentation changes, build the documentation locally to check that it renders how you intended and that any new links work correctly. See :ref:`build_docs`. This is also a good time to look through the :ref:`pr-author-guidelines` and address as many of the relevant points as you can. .. _open-pull-request: Open a pull request =================== When you are ready to ask for someone to review your code and consider a merge, `submit your Pull Request (PR) `_. Go to the web page of *your fork* of the Matplotlib repo, and click ``Compare & pull request`` to send your changes to the maintainers for review. The base repository is ``matplotlib/matplotlib`` and the base branch is generally ``main``. Enter a title for the set of changes with some explanation of what you've done. Mention anything you'd like particular attention for - such as a complicated change or some code you are not happy with. If you don't think your request is ready to be merged, make a :ref:`draft pull request ` and state what aspects you want to have feedback on. This is a good way of getting some preliminary code review. For more guidance on the mechanics of making a pull request, see GitHub's `pull request tutorial `_. .. _update-pull-request: Update a pull request ===================== When updating your pull request after making revisions, instead of adding new commits, please consider amending your initial commit(s) to keep the commit history clean. You can achieve this by using .. code-block:: bash git commit -a --amend --no-edit git push [your-remote-repo] [your-branch] --force-with-lease .. tip:: Instead of typing your branch name every time, you only need to type the following once to link the remote branch to the local branch:: git push --set-upstream origin my-new-feature From now on git will know that ``my-new-feature`` is related to the ``my-new-feature`` branch in the GitHub repo. After this, you will be able to push your changes with:: git push Manage commit history ===================== Explore your repository ----------------------- To see a graphical representation of the repository branches and commits:: gitk --all To see a linear list of commits for this branch:: git log .. _recovering-from-mess-up: Recover from mistakes --------------------- Sometimes, you mess up merges or rebases. Luckily, in git it is relatively straightforward to recover from such mistakes. If you mess up during a rebase:: git rebase --abort If you notice you messed up after the rebase:: # reset branch back to the saved point git reset --hard tmp If you forgot to make a backup branch:: # look at the reflog of the branch git reflog show my-new-feature 8630830 my-new-feature@{0}: commit: BUG: io: close file handles immediately 278dd2a my-new-feature@{1}: rebase finished: refs/heads/my-new-feature onto 11ee694744f2552d 26aa21a my-new-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj ... # reset the branch to where it was before the botched rebase git reset --hard my-new-feature@{2} .. _rewriting-commit-history: Rewrite commit history ---------------------- .. note:: Do this only for your own feature branches. Is there an embarrassing typo in a commit you made? Or perhaps you made several false starts you don't want posterity to see. This can be done via *interactive rebasing*. Suppose that the commit history looks like this:: $ git log --oneline b7e99a8659 (HEAD -> my-new-feature) Fix some remaining bugs 8a5de78b17 Modify it so that it works 34448c69eb Fix a few bugs + disable 9a5d1ca186 First implementation d1da6fbf0b (upstream/main) Merge pull request #30778 from timhoffm/decorator-tracebackhide 6ad937ad83 Merge pull request #30838 from has2k1/fix-numpy-integer-markers ... and ``b7e99a8659`` is the most recent commit in the ``my-new-feature`` branch. Suppose we want to make the following changes: * Rewrite the commit message for ``9a5d1ca186`` to something more specific. * Combine the commits ``34448c69eb``, ``8a5de78b17``, ``b7e99a8659`` into a single one. We do as follows:: # make a backup of the current state git branch tmp HEAD # interactive rebase git rebase -i d1da6fbf0b This will open an editor with the following text in it:: pick 9a5d1ca186 First implementation pick 34448c69eb Fix a few bugs + disable pick 8a5de78b17 Modify it so that it works pick b7e99a8659 Fix some remaining bugs # Rebase d1da6fbf0b..b7e99a8659 onto d1da6fbf0b (4 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup [-C | -c] = like "squash" but keep only the previous # commit's log message, unless -C is used, in which case # keep only this commit's message; -c is same as -C but # opens the editor # x, exec = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop = remove commit # l, label