FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Gitwash clarifications by mdboom · Pull Request #24 · matplotlib/matplotlib · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .rst  (2) All 1 file type selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
108 changes: 94 additions & 14 deletions doc/devel/gitwash/development_workflow.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ Making a new feature branch

::

git branch my-new-feature
git checkout my-new-feature
git checkout -b my-new-feature master

This will create and immediately check out a feature branch based on
``master``. To create a feature branch based on a maintenance branch,
use::

git fetch origin
git checkout -b my-new-feature origin/v1.0.x

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Is this best practice, or should I make a local v1.0.x first and then create the feature branch off of that?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I don't see any real reason to create an intermediate local branch.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Either one should be fine. Personally, I have a local v1.0.x branch that I set up to track matplotlib/v1.0.x, not darrendale/v1.0.x. I don't want to worry about keeping my remote darrendale/v1.0.x branch in sync with matplotlib/v1.0.x.

I think the best practice can be stated thus: if the remote has a branch v1.0.x and you make a local copy of it, the state of your local copy should not diverge from the remote. Use "git pull" occasionally to keep it in sync with the remote, and especially when you are about to do a merge. The only time the state of your local copy should diverge from the remote is right before a push, when you do the merge. Right after the push, your local copy and the remote are once again in sync.

By the way, this:

git branch my-new-feature remotes/origin/v1.0.x
git checkout my-new-feature

is equivalent to:

git checkout -b my-new-feature remotes/origin/v1.0.x

and it also appears to be equal to:

git checkout -b my-new-feature origin/v1.0.x

One final comment: I find the "origin" and "upstream" convention to be confusing. Instead, I name my remotes after the github profiles: "matplotlib" instead of "upstream", "darrendale" instead of origin. Its a little more concrete.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

After reading Jouni's comment and rereading my own, I think I agree that it is easier to not have an intermediate, local v1.0.x branch.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think changing the two commands to "git checkout -b my-new-feature origin/v1.0.x" makes sense.

Generally, you will want to keep this also on your public github_ fork
of matplotlib_. To do this, you `git push`_ this new branch up to your github_
Expand All @@ -40,13 +46,16 @@ by default), git will have a link to your github_ repo, called

git push origin my-new-feature

In git >1.7 you can ensure that the link is correctly set by using the
``--set-upstream`` option::
You will need to use this exact command, rather than simply ``git
push`` every time you want to push changes on your feature branch to
your github_ repo. However, in git >1.7 you can set up a link by
using the ``--set-upstream`` option::

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.
and then next time you need to push changes to your branch a simple
``git push`` will suffice. Note that ``git push`` pushes out all
branches that are linked to a remote branch.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I'm really not sure if this is correct. The manpage seems to suggest this, but it's really not clear. Can someone else clarify what this does?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think this is correct. It makes the local branch "track" the remote branch, and while the documentation mainly talks about fetching or pulling getting the remote branch as default, also pushing uses the tracking branch by default.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Yes, I just tested it. Although, "git push" also pushed my v1.0.x and master branches at the same time as my test branch, because I had not been keeping those branches in my personal remote up to date.

Note that you can also view the .git/config file, where your --set-upstream information was stored.

The editing workflow
====================
Expand All @@ -73,12 +82,12 @@ In more detail
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: README
# modified: README
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# INSTALL
# INSTALL
no changes added to commit (use "git add" and/or "git commit -a")

#. Check what the actual changes are with ``git diff`` (`git diff`_).
Expand Down Expand Up @@ -125,7 +134,7 @@ without interfering with the output from the comparison. More detail?
Note the three dots in the URL above (``master...my-new-feature``) and
see :ref:`dot2-dot3`.

Asking for your changes to be merged with the main repo
Asking for your changes to be merged into the main repo
=======================================================

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

We should avoid words like "with" that don't have a sense of directionality -- it's very ambiguous. Here I've changed it to "into", but I hope I have the direction correct.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Looks right, and I agree that the directional wording is better.


When you are ready to ask for the merge of your code:
Expand All @@ -140,10 +149,16 @@ When you are ready to ask for the merge of your code:
recipient. The message will go to the `matplotlib mailing list`_. Please
feel free to add others from the list as you like.

Merging from trunk
==================
#. If the branch is to be merged into a maintenance branch on the main
repo, make sure the "base branch" indicates the maintenance branch
and not master. Github can not automatically determine the branch
to merge into.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Creating the feature branch based on the maintenance branch like I suggested above does not seem to set the correct base branch when the pull request is made on github.com. Am I doing it wrong?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Doesn't work for me either. I think maybe pull requests always default to master, but I could be wrong.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I noticed the same thing. I do not think you are doing it wrong. It may be a bug at github.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Actually, maybe github doesn't have the information needed to figure this out. Git branches are basically just names for commits, and the fact that my-feature-branch was branched off of origin/v1.0.x isn't recorded anywhere. The history of which commit e.g. the v1.0.x branch used to point to is only recorded in the reflog, which is a very ephemeral thing that gets cleared every now and then.

This is one of the things about git that seem odd at first, but kind of make sense once you understand the idea of branches. I ran into this in another project when I wanted to run git bisect only along the history of master, to find out which feature branch introduced a bug without running tests in intermediate versions on the feature branches. This is basically not doable using the information in the commit graph (except you can make it a rule that feature branches are always merged into master, so master is always the first parent of a merge commit; but you have to enforce the rule, because a merge in the other direction looks the same except for the order of the parents).

This updates your code from the upstream `matplotlib github`_ repo.
Staying up to date with changes in the central repository
=========================================================

This updates your working copy from the upstream `matplotlib github`_
repo.

Overview
--------
Expand All @@ -155,7 +170,7 @@ Overview
# pull changes from github
git fetch upstream
# merge from upstream
git merge upstream/master
git merge --ff-only upstream/master

In detail
---------
Expand All @@ -175,7 +190,72 @@ the upstream repo to a copy on your local machine::

then merging into your current branch::

git merge upstream/master
git merge --ff-only upstream/master

The ``--ff-only`` option guarantees that if you have mistakenly
committed code on your ``master`` branch, the merge fails at this point.
If you were to merge ``upstream/master`` to your ``master``, you
would start to diverge from the upstream. If this command fails, see
the section on accidents_.

The letters 'ff' in ``--ff-only`` mean 'fast forward', which is a
special case of merge where git can simply update your branch to point
to the other branch and not do any actual merging of files. For
``master`` and other integration branches this is exactly what you
want.

Other integration branches
--------------------------

Some people like to keep separate local branches corresponding to the
maintenance branches on github. At the time of this writing, ``v1.0.x``
is the active maintenance branch. If you have such a local branch,
treat is just as ``master``: don't commit on it, and before starting
new branches off of it, update it from upstream::

git checkout v1.0.x
git fetch upstream
git merge --ff-only upstream/v1.0.x

But you don't necessarily have to have such a branch. Instead, if you
are preparing a bugfix that applies to the maintenance branch, fetch
from upstream and base your bugfix on the remote branch::

git fetch upstream
git checkout -b my-bug-fix upstream/v1.0.x

.. _accidents:

Recovering from accidental commits on master
--------------------------------------------

If you have accidentally committed changes on ``master`` and
``git merge --ff-only`` fails, don't panic! First find out how much
you have diverged::

git diff upstream/master...master

If you find that you want simply to get rid of the changes, reset
your ``master`` branch to the upstream version::

git reset --hard upstream/master

As you might surmise from the words 'reset' and 'hard', this command
actually causes your changes to the current branch to be lost, so
think twice.

If, on the other hand, you find that you want to preserve the changes,
create a feature branch for them::

git checkout -b my-important-changes

Now ``my-important-changes`` points to the branch that has your
changes, and you can safely reset ``master`` as above |emdash| but
make sure to reset the correct branch::

git checkout master
git reset --hard upstream/master

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Instructions should probably also be added for keeping up to date with the private repository. I think "git pull" is sufficient, but that may not be the case for branches, etc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

If you are branching from your private remote, then yes, pushing your changes is a good idea. Otherwise, it will appear that all of your developments branch off of the same point in history: the day you made your personal fork.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Depends on what "the private repository" means. I guess you mean that you develop on several computers, and want to use github to keep them in sync. Then I think you would want to make your local branches track their respective branches on your github repository, and run "git push" when you are done on one machine, and every time you start working on another machine, check out the relevant branch and run "git pull".

Do note that your github repository is publicly visible, so if you have a workflow where you have private branches that you rebase at will but push to your github repository, it would be a good idea to make it clear which branches are meant for public consumption and which ones not.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I don't think I explained myself clearly. For cross-platform testing, I have clones on about 3 different physical machines, and 8 virtual machines. I'm trying to minimize the amount of work and confusion associated with that. The "git fetch upstream ; git merge upstream/master" commands pull in any recent changes from the central repository into the clone on my local machine. But, if I understand correctly, this does not have any effect on my personal repository, so would need to be performed in every clone. Is that just how it's supposed to work -- this particular merge should never have conflicts, after all, since in the workflow described here, new features are never added to master. Or is it better to do this merge, push it back to my personal repository, and then simply use "git pull" on all my other clones?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Oh, right. For the master branch (and similarly for maintenance branches) this should be a "fast forward" merge, i.e. your branch should be an ancestor of upstream/master and is just updated to point to the same commit. This kind of merge can be done on each repository separately or pushed to your own github repository and pulled from there. I don't see any big advantage either way, but the push/pull workflow seems a little bit more complicated.

For non-fast-forward merges on feature branches, you would most likely obtain a different commit hash on each repository (it depends on the commit message, and I'm not sure if it depends on the date), so then it's important to do the merge once and push/pull it to the other repositories.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Ok. I'll leave the instructions as-is.


Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

To put my question another way: Does performing this merge also pull in changes that may exist only on a maintenance branch? Or is there another step that needs to be performed if I'm, say, working on a bug fix for a maintenance branch, and want to test that it's compatible with any recent changes on that maintenance branch before filing a pull request?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Yes, the maintenance branches are very much like "master" and should be handled in the same way. Whatever you do on "master" has no effect on a maintenance branch and vice versa.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Ok -- so given that above we are recommending not having a separate personal maintenance branch that bugfix branches are built off of, how would one merge upstream changes on a maintenance branch? We are also recommending not merging changes onto feature/bugfix branches, so I'm not sure how it would be done. Apologies if I'm not getting something obvious.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

If you do have a local maintenance branch, handle it as you would handle master: don't commit features on it, and keep it up-to-date by pulling into it from the corresponding upstream branch as necessary. If you don't have a local maintenance branch, you can run git fetch upstream to update your local information on the remote branches (so git checkout -b upstream/v1.0.x branches from the current position of v1.0.x).

If you don't have a local maintenance branch but want to merge the current maintenance branch into your feature branch (which shouldn't be necessary, most of the time) run git pull upstream v1.0.x, assuming upstream is the remote corresponding to github.com/matplotlib/matplotlib. If you want to test that your branch merges cleanly, do the merge and then run git reset --hard HEAD^, or use git pull --no-commit upstream v1.0.x and then git reset --hard.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I'm having trouble following this, and maybe I'm asking the wrong questions.

The use case is: I'm working on a bugfix to 1.0.x, so I create a new branch based off of 1.0.x:

git checkout -b bugfix v1.0.x

I work on the bugfix for a while -- it turns out it's non-trivial and I can't finish right away -- days go by -- in the meantime 1.0.x may have changed considerably. I want to confirm that the work I've done on the bugfix is compatible with those changes. So I do "git pull upstream v1.0.x". Why do you say this shouldn't be necessary most of the time? Shouldn't it be something to check as a matter of course before pushing anything? What do the other steps do and why are they necessary? Shouldn't a pull be enough to tell me if my changes merge cleanly?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think this conversation is a good way of finding out the questions that the documentation needs to answer.

Where I work, we have a workflow where everyone works on a feature branch and when they're done (and all tests pass), submits it to a homebrew review system. Others look at the diff and add their comments. We rotate the task of merging into master: someone periodically merges accepted branches, runs the test suite and if it passes, pushes the master onto the centralized server. Sometimes the review process can take pretty long if the changes are big or if everyone is busy.

In this workflow it is pretty rare to have merge conflicts. People tend to be working on different tasks and so mostly touch different parts of the code, and if they do touch the same code, they tend to talk to each other and figure out how to make their changes work together. Even if you test that the current branch merges cleanly, there is no guarantee of the order in which different branches get merged, so the merge could fail later. We have agreed that the submitter should run the tests before the merge, and whoever merges the branches into master should run the test after the merge. That way we make sure that master is always in good condition, and since the tests pass before the merge, it's not very common for them to fail after the merge. It's also fine for the person doing the merging to fix obvious merge conflicts, since the tests get run after the merge anyway.

So: the extra check before pushing your feature branch doesn't usually catch anything, and it isn't sufficient either, because the branch being merged into can change between when you push and when it gets merged. The important checks are that tests pass before you push and after the merge (so whoever is doing merges should run the tests). Checking that the branch merges doesn't hurt, and doesn't take a lot of time.

A pull is enough to check that the branch would merge. If you push your branch after pulling master (or the maintenance branch) into it, you create extra nodes in the revision history graph, and many people seem to think this is bad. (Personally I don't mind, but this is an opinion held by many people, e.g. Linus.) That's why I recommend that if the merge goes fine, you discard the merge commit and push the branch as it was before the merge.

Finally, if you have developed the branch in private -- you did not push it on github, or at least you did not ask anyone else to build on it -- it's fine to rebase it on top of the branch you want it merged into (e.g. master). Rebasing does not create a merge commit; instead it applies the effect of ever commit on your branch on top of current master, creating a new series of commit objects. That's bad if someone has references to the old commit objects, but it makes the history look cleaner.

Deleting a branch on github_
============================
Expand Down
13 changes: 9 additions & 4 deletions doc/devel/gitwash/set_up_fork.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,17 @@ Note that we've used ``git://`` for the URL rather than ``git@``. The
(or deliberately) write to the upstream repo, and we are only going to
use it to merge into our own code.

Note this command needs to be run on every clone of the repository
that you make. It is not tracked in your personal repository on
github_.

Just for your own satisfaction, show yourself that you now have a new
'remote', with ``git remote -v show``, giving you something like::

upstream git://github.com/matplotlib/matplotlib.git (fetch)
upstream git://github.com/matplotlib/matplotlib.git (push)
origin git@github.com:your-user-name/matplotlib.git (fetch)
origin git@github.com:your-user-name/matplotlib.git (push)
upstream git://github.com/matplotlib/matplotlib.git (fetch)
upstream git://github.com/matplotlib/matplotlib.git (push)
origin git@github.com:your-user-name/matplotlib.git (fetch)
origin git@github.com:your-user-name/matplotlib.git (push)

.. include:: links.inc


Back | FazBrowse Home | New Git URL