From aa4014be669424e5f48b759261d23df57f6def99 2010-07-02 18:28:22 From: Fernando Perez <Fernando.Perez@berkeley.edu> Date: 2010-07-02 18:28:22 Subject: [PATCH] Add Git workflow docs from Gitwash. These are auto-generated docs from the gitwash template. To improve anything in the gitwash/ directory, please go instead to that project and make your improvements upstream: http://github.com/matthew-brett/gitwash --- diff --git a/docs/Makefile b/docs/Makefile index f0d67de..e6a20f3 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -29,6 +29,7 @@ help: @echo "pdf latex and then runs the PDF generation" @echo "all html and pdf" @echo "dist all, and then puts the results in dist/" + @echo "gitwash-update update git workflow from source repo" clean: -rm -rf build/* dist/* $(SRCDIR)/api/generated @@ -93,3 +94,7 @@ linkcheck: @echo @echo "Link check complete; look for any errors in the above output " \ "or in build/linkcheck/output.txt." + +gitwash-update: + python ../tools/gitwash_dumper.py source/development ipython + cd source/development/gitwash && rename 's/.rst/.txt/' *.rst diff --git a/docs/source/development/contributing.txt b/docs/source/development/contributing.txt index ab57554..773b3d3 100644 --- a/docs/source/development/contributing.txt +++ b/docs/source/development/contributing.txt @@ -7,177 +7,20 @@ How to contribute to IPython Overview ======== -IPython development is done using Bazaar [Bazaar]_ and Launchpad [Launchpad]_. +IPython development is done using Git [Git]_ and Github.com [Github.com]_. This makes it easy for people to contribute to the development of IPython. There are several ways in which you can join in. -If you have a small change that you want to contribute, you can edit your -Bazaar checkout of IPython (see below) in-place, and ask Bazaar for the -differences: - -.. code-block:: bash - - $ cd /path/to/your/copy/of/ipython - $ bzr diff > my_fixes.diff - -This produces a patch file with your fixes, which we can apply to the source -tree. This file should then be attached to a ticket in our `bug tracker -<https://bugs.launchpad.net/ipython>`_, indicating what it does. - -This model of creating small, self-contained patches works very well and there -are open source projects that do their entire development this way. However, -in IPython we have found that for tracking larger changes, making use of -Bazaar's full capabilities in conjunction with Launchpad's code hosting -services makes for a much better experience. - -Making your own branch of IPython allows you to refine your changes over time, -track the development of the main team, and propose your own full version of -the code for others to use and review, with a minimum amount of fuss. The next -parts of this document will explain how to do this. - -Install Bazaar and create a Launchpad account ---------------------------------------------- - -First make sure you have installed Bazaar (see their `website -<http://bazaar-vcs.org/>`_). To see that Bazaar is installed and knows about -you, try the following: - -.. code-block:: bash - - $ bzr whoami - Joe Coder <jcoder@gmail.com> - -This should display your name and email. Next, you will want to create an -account on the `Launchpad website <http://www.launchpad.net>`_ and setup your -ssh keys. For more information of setting up your ssh keys, see `this link -<https://help.launchpad.net/YourAccount/CreatingAnSSHKeyPair>`_. - -Get the main IPython branch from Launchpad ------------------------------------------- - -Now, you can get a copy of the main IPython development branch (we call this -the "trunk"): - -.. code-block:: bash - - $ bzr branch lp:ipython - -Create a working branch ------------------------ - -When working on IPython, you won't actually make edits directly to the -:file:`lp:ipython` branch. Instead, you will create a separate branch for your -changes. For now, let's assume you want to do your work in a branch named -"ipython-mybranch". Create this branch by doing: - -.. code-block:: bash - - $ bzr branch ipython ipython-mybranch - -When you actually create a branch, you will want to give it a name that -reflects the nature of the work that you will be doing in it, like -"install-docs-update". - -Make edits in your working branch ---------------------------------- - -Now you are ready to actually make edits in your :file:`ipython-mybranch` -branch. Before doing this, it is helpful to install this branch so you can -test your changes as you work. This is easiest if you have setuptools -installed. Then, just do: - -.. code-block:: bash - - $ cd ipython-mybranch - $ python setupegg.py develop - -Now, make some changes. After a while, you will want to commit your changes. -This let's Bazaar know that you like the changes you have made and gives you -an opportunity to keep a nice record of what you have done. This looks like -this: - -.. code-block:: bash - - $ ...do work in ipython-mybranch... - $ bzr commit -m "the commit message goes here" - -Please note that since we now don't use an old-style linear ChangeLog (that -tends to cause problems with distributed version control systems), you should -ensure that your log messages are reasonably detailed. Use a docstring-like -approach in the commit messages (including the second line being left -*blank*):: - - Single line summary of changes being committed. - - * more details when warranted ... - * including crediting outside contributors if they sent the - code/bug/idea! - -As you work, you will repeat this edit/commit cycle many times. If you work on -your branch for a long time, you will also want to get the latest changes from -the :file:`lp:ipython` branch. This can be done with the following sequence of -commands: - -.. code-block:: bash - - $ ls - ipython - ipython-mybranch - - $ cd ipython - $ bzr pull - $ cd ../ipython-mybranch - $ bzr merge ../ipython - $ bzr commit -m "Merging changes from trunk" - -Post your branch and request a code review ------------------------------------------- - -Once you are done with your edits, you should post your branch on Launchpad so -that other IPython developers can review the changes and help you merge your -changes into the main development branch. To post your branch on Launchpad, -do: - -.. code-block:: bash - - $ cd ipython-mybranch - $ bzr push lp:~yourusername/ipython/ipython-mybranch - -Then, go to the `IPython Launchpad site <http://www.launchpad.net/ipython>`_, -and you should see your branch under the "Code" tab. If you click on your -branch, you can provide a short description of the branch as well as mark its -status. Most importantly, you should click the link that reads "Propose for -merging into another branch". What does this do? - -This let's the other IPython developers know that your branch is ready to be -reviewed and merged into the main development branch. During this review -process, other developers will give you feedback and help you get your code -ready to be merged. What types of things will we be looking for: - -* All code is documented. How to document your code is described in - :ref:`this section <documenting-ipython>`. -* All code has tests. How to write and run tests is described in - :ref:`this section <testing>`. -* The entire IPython test suite passes. - -You should also provide us with a list of changes that your branch contains. -See the :ref:`What's new <whatsnew_index>` section of our documentation -(:file:`docs/source/whatsnew`) for details on the format and content of this. - -Once your changes have been reviewed and approved, someone will merge them -into the main development branch. - Merging a branch into trunk =========================== Core developers, who ultimately merge any approved branch (from themselves, another developer, or any third-party contribution) will typically use -:command:`bzr merge` to merge the branch into the trunk and push it to the -main Launchpad site. There are a number of things to keep in mind when doing -this, so that the project history is easy to understand in the long -run, and that generating release notes is as painless and accurate as -possible. +:command:`git merge` to merge the branch into the trunk and push it to the main +Git repository. There are a number of things to keep in mind when doing this, +so that the project history is easy to understand in the long run, and that +generating release notes is as painless and accurate as possible. * When you merge any non-trivial functionality (from one small bug fix to a big feature branch), please remember to always edit the appropriate file in @@ -197,13 +40,13 @@ possible. committing something that is completely (or almost so) a third-party contribution, do the commit as:: - $ bzr commit --author="Someone Else" + $ git commit --author="Someone Else" This way it will show that name separately in the log, which makes it even easier to spot. Obviously we often rework third party contributions - extensively, but this is still good to keep in mind for cases when we don't + extensively ,but this is still good to keep in mind for cases when we don't touch the code too much. -.. [Bazaar] Bazaar. http://bazaar-vcs.org/ -.. [Launchpad] Launchpad. http://www.launchpad.net/ipython +.. [Git] The Git version control system. +.. [Github.com] Github.com. http://github.com diff --git a/docs/source/development/gitwash/branch_list.png b/docs/source/development/gitwash/branch_list.png new file mode 100644 index 0000000000000000000000000000000000000000..1196eb754d361dbb2e53a25745f913c2f0cdb83e GIT binary patch literal 13361 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 C_-JPU literal 0 Hc$@<O00001 diff --git a/docs/source/development/gitwash/branch_list_compare.png b/docs/source/development/gitwash/branch_list_compare.png new file mode 100644 index 0000000000000000000000000000000000000000..336afa3746040f118c073e7d02a5843bc8eed152 GIT binary patch literal 10679 zc${^51ymh9+bvSui+d@>in~jpXmL2WySux)6nFQ79^By+cXx;4?hcpt{r>;1t21k6 zGCNsGR+4A0=Sg<BysS71A^{=<1O$qt#7{*C2&mSNv@|^I$2*`5i|ykB>8L0!3{f>s zbolWDYw%0_C&c?dcWy^X!Uuw2C!y{L0fB`1&jSgOo{9GX!Z}IGh{7$yz`|lNWkal^ zLO^_hko@^W*=_lB&D{&r`R(CyflV@j&DsNkKbIa$!>lae%O<455E*<#>zCYSDS*5d zF1D(?-KB=YBf@&FvWgmps6RHA=A&W^Q2x^=I+zF|`bp@6I1ZU<qU&e!L(vv&<I7hs zzT7dVz3a4gsx<crQ-N!IbYXb1AoOjP!crhm3NPrN-`?GRIpHt=CcjN#|0mx!NaX`+ zMxT#2RMY+rtAsg98U5+!N7;9se9JLy@D8i0umqZpn=$g1ANxHLNlw~$cX+j<XFP&m zd?ivU%RO%{rqTwnT-14UO4~MtN!6$bMe4I@yL6L0N^)i&A2%;_x2BjD2_rvGB%i3c zn)`#0j_;d`bc7W(83TTd7tVO5q)B#%i=uE2)*DAHq5Cgg0}~CM0@2yu{-f#kyv5UW z+3A^5G_YdQp3y$cZ-2AR)AkcmUpbdJKl<Oyv_I*bxBOf{mjF|a%Eq_8RrPAU1C-u4 zUs21jF3T7?e9e;|AMc=o;HvdjEnqo8%tfOjBLhD(as;F%%S;aYONafE8m~ng9IeBg zG5=B^jz$K~jn9Z1Hsz%=8;c7XphU+sxS%W#LI1pMXohbJyV+fQn@E#O?b4~;w&L07 zoosBh@iC;^!da>d!K=pCOH=pm@!W^-N}xdJP%H~dTZxt71Jn-gM}xhX9JC&G@X0a& zo=re1_?~2>aAn7+9NvDY_IF(+yq^HMO^GMojTGWe^!<XcIk)|*qFWwmGn&^>4{PVw z{QXzyR&sDgx1#VKaCJF;m}Mbeu(bz21)NR(4Er&YxPnusJT-7F8%FU@IhE~9-HV&H zk7>u$O1a|0KcQ5{zw*1HEX}VwF+p<q;dwY!n)JkUD02xvmccLIAM{p@S~nQuDRbS7 zS!FN(wVnf|EFEwj8i!D(8qp%y4>8S@i6fiSUaK=16X}KwIQ9Xu@P1!$#^;YVI4)^- z{^FKZJ*_`_kul==(kzZh4&7;N<H3>UNgpM}lH-E^?^HdokGszXhsicM*lxgEWe98^ zkBM89lqc437&4Y(d}}fndA_6nL1S<l3*&rU3ajDTjM�S-H}rC{3rm9L!0*Q3a7V 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 literal 0 Hc$@<O00001 diff --git a/docs/source/development/gitwash/configure_git.txt b/docs/source/development/gitwash/configure_git.txt new file mode 100644 index 0000000..260898d --- /dev/null +++ b/docs/source/development/gitwash/configure_git.txt @@ -0,0 +1,89 @@ +.. _configure-git: + +=============== + Configure git +=============== + +.. _git-config-basic: + +Overview +======== + +:: + + git config --global user.email you@yourdomain.example.com + git config --global user.name "Your Name Comes Here" + + +In detail +========= + +This is to tell git_ who you are, for labeling any changes you make to +the code. The simplest way to do this is from the command line:: + + git config --global user.email you@yourdomain.example.com + git config --global user.name "Your Name Comes Here" + +This will write the settings into your git configuration file - a file +called ``.gitconfig`` in your home directory. + +Advanced git configuration +========================== + +You might well benefit from some aliases to common commands. + +For example, you might well want to be able to shorten ``git checkout`` to ``git co``. + +The easiest way to do this, is to create a ``.gitconfig`` file in your +home directory, with contents like this:: + + [core] + editor = emacs + [user] + email = you@yourdomain.example.com + name = Your Name Comes Here + [alias] + st = status + stat = status + co = checkout + [color] + diff = auto + status = true + +(of course you'll need to set your email and name, and may want to set +your editor). If you prefer, you can do the same thing from the command +line:: + + git config --global core.editor emacs + git config --global user.email you@yourdomain.example.com + git config --global user.name "Your Name Comes Here" + git config --global alias.st status + git config --global alias.stat status + git config --global alias.co checkout + git config --global color.diff auto + git config --global color.status true + +These commands will write to your user's git configuration file +``~/.gitconfig``. + +To set up on another computer, you can copy your ``~/.gitconfig`` file, +or run the commands above. + +Other configuration recommended by Yarik +======================================== + +In your ``~/.gitconfig`` file alias section:: + + wdiff = diff --color-words + +so that ``git wdiff`` gives a nicely formatted output of the diff. + +To enforce summaries when doing merges(``~/.gitconfig`` file again):: + + [merge] + summary = true + + +.. include:: git_links.txt + + diff --git a/docs/source/development/gitwash/development_workflow.txt b/docs/source/development/gitwash/development_workflow.txt new file mode 100644 index 0000000..2804f09 --- /dev/null +++ b/docs/source/development/gitwash/development_workflow.txt @@ -0,0 +1,233 @@ +.. _development-workflow: + +==================== +Development workflow +==================== + +You already have your own forked copy of the ipython_ repository, by +following :ref:`forking`, :ref:`set-up-fork`, and you have configured +git_ by following :ref:`configure-git`. + +Workflow summary +================ + +* Keep your ``master`` branch clean of edits that have not been merged + to the main ipython_ development repo. Your ``master`` then will follow + the main ipython_ repository. +* Start a new *feature branch* for each set of edits that you do. +* If you can avoid it, try not to merge other branches into your feature + branch while you are working. +* Ask for review! + +This way of working really helps to keep work well organized, and in +keeping history as clear as possible. + +See - for example - `linux git workflow`_. + +Making a new feature branch +=========================== + +:: + + git branch my-new-feature + git checkout my-new-feature + +Generally, you will want to keep this also on your public github_ fork +of ipython_. 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 github_ repo, called +``origin``. You push up to your own repo on github_ with:: + + git push 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. + +The editing workflow +==================== + +Overview +-------- + +:: + + # hack hack + git add my_new_file + git commit -am 'NF - some message' + git push + +In more detail +-------------- + +#. Make some changes +#. See which files have changed with ``git status`` (see `git status`_). + You'll see a listing like this one:: + + # On branch ny-new-feature + # Changed but not updated: + # (use "git add <file>..." to update what will be committed) + # (use "git checkout -- <file>..." to discard changes in working directory) + # + # modified: README + # + # Untracked files: + # (use "git add <file>..." 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`` (`git diff`_). +#. Add any new files to version control ``git add new_file_name`` (see + `git add`_). +#. To commit all modified files into the local copy of your repo,, do + ``git commit -am 'A commit message'``. Note the ``-am`` options to + ``commit``. The ``m`` flag just signals that you're going to type a + message on the command line. The ``a`` flag - you can just take on + faith - or see `why the -a flag?`_. See also the `git commit`_ manual + page. +#. To push the changes up to your forked repo on github_, do a ``git + push`` (see `git push`). + +Asking for code review +====================== + +#. Go to your repo URL - e.g. ``http://github.com/your-user-name/ipython``. +#. Click on the *Branch list* button: + + .. image:: branch_list.png + +#. Click on the *Compare* button for your feature branch - here ``my-new-feature``: + + .. image:: branch_list_compare.png + +#. If asked, select the *base* and *comparison* branch names you want to + compare. Usually these will be ``master`` and ``my-new-feature`` + (where that is your feature branch name). +#. At this point you should get a nice summary of the changes. Copy the + URL for this, and post it to the `ipython mailing list`_, asking for + review. The URL will look something like: + ``http://github.com/your-user-name/ipython/compare/master...my-new-feature``. + There's an example at + http://github.com/matthew-brett/nipy/compare/master...find-install-data + See: http://github.com/blog/612-introducing-github-compare-view for + more detail. + +The generated comparison, is between your feature branch +``my-new-feature``, and the place in ``master`` from which you branched +``my-new-feature``. In other words, you can keep updating ``master`` +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 +======================================================= + +When you are ready to ask for the merge of your code: + +#. Go to the URL of your forked repo, say + ``http://github.com/your-user-name/ipython.git``. +#. Click on the 'Pull request' button: + + .. image:: pull_button.png + + Enter a message; we suggest you select only ``ipython`` as the + recipient. The message will go to the `ipython mailing list`_. Please + feel free to add others from the list as you like. + +Merging from trunk +================== + +This updates your code from the upstream `ipython github`_ repo. + +Overview +-------- + +:: + + # go to your master branch + git checkout master + # pull changes from github + git fetch upstream + # merge from upstream + git merge upstream master + +In detail +--------- + +We suggest that you do this only for your ``master`` branch, and leave +your 'feature' branches unmerged, to keep their history as clean as +possible. This makes code review easier:: + + git checkout master + +Make sure you have done :ref:`linking-to-upstream`. + +Merge the upstream code into your current development by first pulling +the upstream repo to a copy on your local machine:: + + git fetch upstream + +then merging into your current branch:: + + git merge upstream/master + +Deleting a branch on github_ +============================ + +:: + + git checkout master + # delete branch locally + git branch -D my-unwanted-branch + # delete branch on github + git push origin :my-unwanted-branch + +(Note the colon ``:`` before ``test-branch``. See also: +http://github.com/guides/remove-a-remote-branch + +Several people sharing a single repository +========================================== + +If you want to work on some stuff with other people, where you are all +committing into the same repository, or even the same branch, then just +share it via github_. + +First fork ipython into your account, as from :ref:`forking`. + +Then, go to your forked repository github page, say +``http://github.com/your-user-name/ipython`` + +Click on the 'Admin' button, and add anyone else to the repo as a +collaborator: + + .. image:: pull_button.png + +Now all those people can do:: + + git clone git@githhub.com:your-user-name/ipython.git + +Remember that links starting with ``git@`` use the ssh protocol and are +read-write; links starting with ``git://`` are read-only. + +Your collaborators can then commit directly into that repo with the +usual:: + + git commit -am 'ENH - much better code' + git push origin master # pushes directly into your repo + +Exploring 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 + +You can also look at the `network graph visualizer`_ for your github_ +repo. + +.. include:: git_links.txt diff --git a/docs/source/development/gitwash/dot2_dot3.txt b/docs/source/development/gitwash/dot2_dot3.txt new file mode 100644 index 0000000..7759e2e --- /dev/null +++ b/docs/source/development/gitwash/dot2_dot3.txt @@ -0,0 +1,28 @@ +.. _dot2-dot3: + +======================================== + Two and three dots in difference specs +======================================== + +Thanks to Yarik Halchenko for this explanation. + +Imagine a series of commits A, B, C, D... Imagine that there are two +branches, *topic* and *master*. You branched *topic* off *master* when +*master* was at commit 'E'. The graph of the commits looks like this:: + + + A---B---C topic + / + D---E---F---G master + +Then:: + + git diff master..topic + +will output the difference from G to C (i.e. with effects of F and G), +while:: + + git diff master...topic + +would output just differences in the topic branch (i.e. only A, B, and +C). diff --git a/docs/source/development/gitwash/following_latest.txt b/docs/source/development/gitwash/following_latest.txt new file mode 100644 index 0000000..475e092 --- /dev/null +++ b/docs/source/development/gitwash/following_latest.txt @@ -0,0 +1,36 @@ +.. _following-latest: + +============================= + Following the latest source +============================= + +These are the instructions if you just want to follow the latest +*ipython* source, but you don't need to do any development for now. + +The steps are: + +* :ref:`install-git` +* get local copy of the git repository from github_ +* update local copy from time to time + +Get the local copy of the code +============================== + +From the command line:: + + git clone git://github.com/ipython/ipython.git + +You now have a copy of the code tree in the new ``ipython`` directory. + +Updating the code +================= + +From time to time you may want to pull down the latest code. Do this with:: + + cd ipython + git pull + +The tree in ``ipython`` will now have the latest changes from the initial +repository. + +.. include:: git_links.txt diff --git a/docs/source/development/gitwash/forking_button.png b/docs/source/development/gitwash/forking_button.png new file mode 100644 index 0000000000000000000000000000000000000000..d0e04134d4d086d0c78c45188848c4a0b71b157d GIT binary patch literal 13092 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 literal 0 Hc$@<O00001 diff --git a/docs/source/development/gitwash/forking_hell.txt b/docs/source/development/gitwash/forking_hell.txt new file mode 100644 index 0000000..dab481a --- /dev/null +++ b/docs/source/development/gitwash/forking_hell.txt @@ -0,0 +1,33 @@ +.. _forking: + +========================================== +Making your own copy (fork) of ipython +========================================== + +You need to do this only once. The instructions here are very similar +to the instructions at http://help.github.com/forking/ - please see that +page for more detail. We're repeating some of it here just to give the +specifics for the ipython_ project, and to suggest some default names. + +Set up and configure a github_ account +====================================== + +If you don't have a github_ account, go to the github_ page, and make one. + +You then need to configure your account to allow write access - see the +``Generating SSH keys`` help on `github help`_. + +Create your own forked copy of ipython_ +========================================= + +#. Log into your github_ account. +#. Go to the ipython_ github home at `ipython github`_. +#. Click on the *fork* button: + + .. image:: forking_button.png + + Now, after a short pause and some 'Hardcore forking action', you + should find yourself at the home page for your own forked copy of ipython_. + +.. include:: git_links.txt + diff --git a/docs/source/development/gitwash/git_development.txt b/docs/source/development/gitwash/git_development.txt new file mode 100644 index 0000000..64522c6 --- /dev/null +++ b/docs/source/development/gitwash/git_development.txt @@ -0,0 +1,16 @@ +.. _git-development: + +===================== + Git for development +===================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + forking_hell + set_up_fork + configure_git + development_workflow + diff --git a/docs/source/development/gitwash/git_install.txt b/docs/source/development/gitwash/git_install.txt new file mode 100644 index 0000000..6c6a57c --- /dev/null +++ b/docs/source/development/gitwash/git_install.txt @@ -0,0 +1,26 @@ +.. _install-git: + +============= + Install git +============= + +Overview +======== + +================ ============= +Debian / Ubuntu ``sudo apt-get install git-core`` +Fedora ``sudo yum install git-core`` +Windows Download and install msysGit_ +OS X Use the git-osx-installer_ +================ ============= + +In detail +========= + +See the git_ page for the most recent information. + +Have a look at the github_ install help pages available from `github help`_ + +There are good instructions here: http://book.git-scm.com/2_installing_git.html + +.. include:: git_links.txt diff --git a/docs/source/development/gitwash/git_intro.txt b/docs/source/development/gitwash/git_intro.txt new file mode 100644 index 0000000..6b0aa79 --- /dev/null +++ b/docs/source/development/gitwash/git_intro.txt @@ -0,0 +1,18 @@ +============== + Introduction +============== + +These pages describe a git_ and github_ workflow for the ipython_ +project. + +There are several different workflows here, for different ways of +working with *ipython*. + +This is not a comprehensive git_ reference, it's just a workflow for our +own project. It's tailored to the github_ hosting service. You may well +find better or quicker ways of getting stuff done with git_, but these +should get you started. + +For general resources for learning git_ see :ref:`git-resources`. + +.. include:: git_links.txt diff --git a/docs/source/development/gitwash/git_links.txt b/docs/source/development/gitwash/git_links.txt new file mode 100644 index 0000000..b1579f6 --- /dev/null +++ b/docs/source/development/gitwash/git_links.txt @@ -0,0 +1,67 @@ +.. This (-*- rst -*-) format file contains commonly used link targets + and name substitutions. It may be included in many files, + therefore it should only contain link targets and name + substitutions. Try grepping for "^\.\. _" to find plausible + candidates for this list. + +.. NOTE: reST targets are + __not_case_sensitive__, so only one target definition is needed for + nipy, NIPY, Nipy, etc... + +.. PROJECTNAME placeholders +.. _PROJECTNAME: http://neuroimaging.scipy.org +.. _`PROJECTNAME github`: http://github.com/nipy +.. _`PROJECTNAME mailing list`: http://projects.scipy.org/mailman/listinfo/nipy-devel + +.. nipy +.. _nipy: http://nipy.org/nipy +.. _`nipy github`: http://github.com/nipy/nipy +.. _`nipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel + +.. ipython +.. _ipython: http://ipython.scipy.org +.. _`ipython github`: http://github.com/ipython +.. _`ipython mailing list`: http://mail.scipy.org/mailman/listinfo/IPython-dev + +.. nipy +.. _dipy: http://nipy.org/dipy +.. _`dipy github`: http://github.com/Garyfallidis/dipy +.. _`dipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel + +.. git stuff +.. _git: http://git-scm.com/ +.. _github: http://github.com +.. _github help: http://help.github.com +.. _msysgit: http://code.google.com/p/msysgit/downloads/list +.. _git-osx-installer: http://code.google.com/p/git-osx-installer/downloads/list +.. _subversion: http://subversion.tigris.org/ +.. _git cheat sheet: http://github.com/guides/git-cheat-sheet +.. _pro git book: http://progit.org/ +.. _git svn crash course: http://git-scm.com/course/svn.html +.. _learn.github: http://learn.github.com/ +.. _network graph visualizer: http://github.com/blog/39-say-hello-to-the-network-graph-visualizer +.. _git user manual: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html +.. _git tutorial: http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html +.. _git community book: http://book.git-scm.com/ +.. _git ready: http://www.gitready.com/ +.. _git casts: http://www.gitcasts.com/ +.. _Fernando's git page: http://www.fperez.org/py4science/git.html +.. _git magic: http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html +.. _git concepts: http://www.eecs.harvard.edu/~cduan/technical/git/ +.. _git clone: http://www.kernel.org/pub/software/scm/git/docs/git-clone.html +.. _git checkout: http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html +.. _git commit: http://www.kernel.org/pub/software/scm/git/docs/git-commit.html +.. _git push: http://www.kernel.org/pub/software/scm/git/docs/git-push.html +.. _git pull: http://www.kernel.org/pub/software/scm/git/docs/git-pull.html +.. _git add: http://www.kernel.org/pub/software/scm/git/docs/git-add.html +.. _git status: http://www.kernel.org/pub/software/scm/git/docs/git-status.html +.. _git diff: http://www.kernel.org/pub/software/scm/git/docs/git-diff.html +.. _git log: http://www.kernel.org/pub/software/scm/git/docs/git-log.html +.. _git branch: http://www.kernel.org/pub/software/scm/git/docs/git-branch.html +.. _git remote: http://www.kernel.org/pub/software/scm/git/docs/git-remote.html +.. _git config: http://www.kernel.org/pub/software/scm/git/docs/git-config.html +.. _why the -a flag?: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html +.. _git staging area: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html +.. _git management: http://kerneltrap.org/Linux/Git_Management +.. _linux git workflow: http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html +.. _git parable: http://tom.preston-werner.com/2009/05/19/the-git-parable.html diff --git a/docs/source/development/gitwash/git_resources.txt b/docs/source/development/gitwash/git_resources.txt new file mode 100644 index 0000000..69e344e --- /dev/null +++ b/docs/source/development/gitwash/git_resources.txt @@ -0,0 +1,57 @@ +.. _git-resources: + +================ + git_ resources +================ + +Tutorials and summaries +======================= + +* `github help`_ has an excellent series of how-to guides. +* `learn.github`_ has an excellent series of tutorials +* The `pro git book`_ is a good in-depth book on git. +* A `git cheat sheet`_ is a page giving summaries of common commands. +* The `git user manual`_ +* The `git tutorial`_ +* The `git community book`_ +* `git ready`_ - a nice series of tutorials +* `git casts`_ - video snippets giving git how-tos. +* `git magic`_ - extended introduction with intermediate detail +* Fernando Perez' git page - `Fernando's git page`_ - many links and tips +* A good but technical page on `git concepts`_ +* Th `git parable`_ is an easy read explaining the concepts behind git. +* `git svn crash course`_: git_ for those of us used to subversion_ + +Advanced git workflow +===================== + +There are many ways of working with git_; here are some posts on the +rules of thumb that other projects have come up with: + +* Linus Torvalds on `git management`_ +* Linus Torvalds on `linux git workflow`_ . Summary; use the git tools + to make the history of your edits as clean as possible; merge from + upstream edits as little as possible in branches where you are doing + active development. + +Manual pages online +=================== + +You can get these on your own machine with (e.g) ``git help push`` or +(same thing) ``git push --help``, but, for convenience, here are the +online manual pages for some common commands: + +* `git add`_ +* `git branch`_ +* `git checkout`_ +* `git clone`_ +* `git commit`_ +* `git config`_ +* `git diff`_ +* `git log`_ +* `git pull`_ +* `git push`_ +* `git remote`_ +* `git status`_ + +.. include:: git_links.txt diff --git a/docs/source/development/gitwash/index.txt b/docs/source/development/gitwash/index.txt new file mode 100644 index 0000000..93610f3 --- /dev/null +++ b/docs/source/development/gitwash/index.txt @@ -0,0 +1,18 @@ +.. _using-git: + +Working with *ipython* source code +====================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + git_intro + git_install + following_latest + patching + git_development + git_resources + + diff --git a/docs/source/development/gitwash/patching.txt b/docs/source/development/gitwash/patching.txt new file mode 100644 index 0000000..9053db6 --- /dev/null +++ b/docs/source/development/gitwash/patching.txt @@ -0,0 +1,123 @@ +================ + Making a patch +================ + +You've discovered a bug or something else you want to change in ipython_ - excellent! + +You've worked out a way to fix it - even better! + +You want to tell us about it - best of all! + +The easiest way is to make a *patch* or set of patches. Here we explain +how. Making a patch is the simplest and quickest, but if you're going +to be doing anything more than simple quick things, please consider +following the :ref:`git-development` model instead. + +.. _making-patches: + +Making patches +============== + +Overview +-------- + +:: + + # tell git who you are + git config --global user.email you@yourdomain.example.com + git config --global user.name "Your Name Comes Here" + # get the repository if you don't have it + git clone git://github.com/ipython/ipython.git + # make a branch for your patching + cd ipython + git branch the-fix-im-thinking-of + git checkout the-fix-im-thinking-of + # hack, hack, hack + # Tell git about any new files you've made + git add somewhere/tests/test_my_bug.py + # commit work in progress as you go + git commit -am 'BF - added tests for Funny bug' + # hack hack, hack + git commit -am 'BF - added fix for Funny bug' + # make the patch files + git format-patch -M -C master + +Then, send the generated patch files to the `ipython mailing list`_ - where we will thank you warmly. + +In detail +--------- + +#. Tell git_ who you are so it can label the commits you've made:: + + git config --global user.email you@yourdomain.example.com + git config --global user.name "Your Name Comes Here" + +#. If you don't already have one, clone a copy of the ipython_ repository:: + + git clone git://github.com/ipython/ipython.git + cd ipython + +#. Make a 'feature branch'. This will be where you work on your bug + fix. It's nice and safe and leaves you with access to an unmodified + copy of the code in the main branch:: + + git branch the-fix-im-thinking-of + git checkout the-fix-im-thinking-of + +#. Do some edits, and commit them as you go:: + + # hack, hack, hack + # Tell git about any new files you've made + git add somewhere/tests/test_my_bug.py + # commit work in progress as you go + git commit -am 'BF - added tests for Funny bug' + # hack hack, hack + git commit -am 'BF - added fix for Funny bug' + + Note the ``-am`` options to ``commit``. The ``m`` flag just signals + that you're going to type a message on the command line. The ``a`` + flag - you can just take on faith - or see `why the -a flag?`_. + +#. When you have finished, check you have committed all your changes:: + + git status + +#. Finally, make your commits into patches. You want all the commits + since you branched from the ``master`` branch:: + + git format-patch -M -C master + + You will now have several files named for the commits:: + + 0001-BF-added-tests-for-Funny-bug.patch + 0002-BF-added-fix-for-Funny-bug.patch + + Send these files to the `ipython mailing list`_. + +When you are done, to switch back to the main copy of the code, just +return to the ``master`` branch:: + + git checkout master + +Moving from patching to development +=================================== + +If you find you have done some patches, and you have one or more feature +branches, you will probably want to switch to development mode. You can +do this with the repository you have. + +Fork the ipython_ repository on github_ - :ref:`forking`. Then:: + + # checkout and refresh master branch from main repo + git checkout master + git pull origin master + # rename pointer to main repository to 'upstream' + git remote rename origin upstream + # point your repo to default read / write to your fork on github + git remote add origin git@github.com:your-user-name/ipython.git + # push up any branches you've made and want to keep + git push origin the-fix-im-thinking-of + +Then you can, if you want, follow the :ref:`development-workflow`. + +.. include:: git_links.txt diff --git a/docs/source/development/gitwash/pull_button.png b/docs/source/development/gitwash/pull_button.png new file mode 100644 index 0000000000000000000000000000000000000000..e5031681b97bcc3b323a01653153c8d6bcfb5507 GIT binary patch literal 12893 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 literal 0 Hc$@<O00001 diff --git a/docs/source/development/gitwash/set_up_fork.txt b/docs/source/development/gitwash/set_up_fork.txt new file mode 100644 index 0000000..627b4d9 --- /dev/null +++ b/docs/source/development/gitwash/set_up_fork.txt @@ -0,0 +1,68 @@ +.. _set-up-fork: + +================== + Set up your fork +================== + +First you follow the instructions for :ref:`forking`. + +Overview +======== + +:: + + git clone git@github.com/your-user-name/ipython.git + cd ipython + git remote add upstream git://github.com/ipython/ipython.git + +In detail +========= + +Clone your fork +--------------- + +#. Clone your fork to the local computer with ``git clone + git@github.com:your-user-name/ipython.git`` +#. Investigate. Change directory to your new repo: ``cd ipython``. Then + ``git branch -a`` to show you all branches. You'll get something + like:: + + * master + remotes/origin/master + + This tells you that you are currently on the ``master`` branch, and + that you also have a ``remote`` connection to ``origin/master``. + What remote repository is ``remote/origin``? Try ``git remote -v`` to + see the URLs for the remote. They will point to your github_ fork. + + Now you want to connect to the upstream `ipython github`_ repository, so + you can merge in changes from trunk. + +.. _linking-to-upstream: + +Linking your repository to the upstream repo +-------------------------------------------- + +:: + + cd ipython + git remote add upstream git://github.com/ipython/ipython.git + +``upstream`` here is just the arbitrary name we're using to refer to the +main ipython_ repository at `ipython github`_. + +Note that we've used ``git://`` for the URL rather than ``git@``. The +``git://`` URL is read only. This means we that we can't accidentally +(or deliberately) write to the upstream repo, and we are only going to +use it to merge into our own code. + +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/ipython/ipython.git (fetch) + upstream git://github.com/ipython/ipython.git (push) + origin git@github.com:your-user-name/ipython.git (fetch) + origin git@github.com:your-user-name/ipython.git (push) + +.. include:: git_links.txt + diff --git a/docs/source/development/index.txt b/docs/source/development/index.txt index 1d5bbee..368ab48 100644 --- a/docs/source/development/index.txt +++ b/docs/source/development/index.txt @@ -8,6 +8,7 @@ IPython developer's guide :maxdepth: 1 contributing.txt + gitwash/index.txt coding_guide.txt doc_guide.txt testing.txt diff --git a/docs/source/development/messaging.txt b/docs/source/development/messaging.txt new file mode 100644 index 0000000..408212e --- /dev/null +++ b/docs/source/development/messaging.txt @@ -0,0 +1,106 @@ +===================== +Message Specification +===================== + +Note: not all of these have yet been fully fleshed out, but the key ones are, +see kernel and frontend files for actual implementation details. + +General Message Format +===================== + +General message format:: + + { + header : { 'msg_id' : 10, # start with 0 + 'username' : 'name', + 'session' : uuid + }, + parent_header : dict, + msg_type : 'string_message_type', + content : blackbox_dict , # Must be a dict + } + +Side effect: (PUB/SUB) +====================== + +# msg_type = 'stream':: + + content = { + name : 'stdout', + data : 'blob', + } + +# msg_type = 'pyin':: + + content = { + code = 'x=1', + } + +# msg_type = 'pyout':: + + content = { + data = 'repr(obj)', + prompt_number = 10 + } + +# msg_type = 'pyerr':: + + content = { + traceback : 'full traceback', + exc_type : 'TypeError', + exc_value : 'msg' + } + +# msg_type = 'file': + content = { + path = 'cool.jpg', + data : 'blob' + } + +Request/Reply +============= + +Execute +------- + +Request: + +# msg_type = 'execute_request':: + + content = { + code : 'a = 10', + } + +Reply: + +# msg_type = 'execute_reply':: + + content = { + 'status' : 'ok' OR 'error' OR 'abort' + # data depends on status value + } + +Complete +-------- + +# msg_type = 'complete_request':: + + content = { + text : 'a.f', # complete on this + line : 'print a.f' # full line + } + +# msg_type = 'complete_reply':: + + content = { + matches : ['a.foo', 'a.bar'] + } + +Control +------- + +# msg_type = 'heartbeat':: + + content = { + # XXX - unfinished + } diff --git a/tools/gitwash_dumper.py b/tools/gitwash_dumper.py new file mode 100755 index 0000000..000245a --- /dev/null +++ b/tools/gitwash_dumper.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +''' Checkout gitwash repo into directory and do search replace on name ''' + +import os +from os.path import join as pjoin +import shutil +import sys +import re +import glob +import fnmatch +import tempfile +from subprocess import call + + +verbose = False + + +def clone_repo(url, branch): + cwd = os.getcwd() + tmpdir = tempfile.mkdtemp() + try: + cmd = 'git clone %s %s' % (url, tmpdir) + call(cmd, shell=True) + os.chdir(tmpdir) + cmd = 'git checkout %s' % branch + call(cmd, shell=True) + except: + shutil.rmtree(tmpdir) + raise + finally: + os.chdir(cwd) + return tmpdir + + +def cp_files(in_path, globs, out_path): + try: + os.makedirs(out_path) + except OSError: + pass + out_fnames = [] + for in_glob in globs: + in_glob_path = pjoin(in_path, in_glob) + for in_fname in glob.glob(in_glob_path): + out_fname = in_fname.replace(in_path, out_path) + pth, _ = os.path.split(out_fname) + if not os.path.isdir(pth): + os.makedirs(pth) + shutil.copyfile(in_fname, out_fname) + out_fnames.append(out_fname) + return out_fnames + + +def filename_search_replace(sr_pairs, filename, backup=False): + ''' Search and replace for expressions in files + + ''' + in_txt = open(filename, 'rt').read(-1) + out_txt = in_txt[:] + for in_exp, out_exp in sr_pairs: + in_exp = re.compile(in_exp) + out_txt = in_exp.sub(out_exp, out_txt) + if in_txt == out_txt: + return False + open(filename, 'wt').write(out_txt) + if backup: + open(filename + '.bak', 'wt').write(in_txt) + return True + + +def copy_replace(replace_pairs, + out_path, + repo_url, + repo_branch = 'master', + cp_globs=('*',), + rep_globs=('*',), + renames = ()): + repo_path = clone_repo(repo_url, repo_branch) + try: + out_fnames = cp_files(repo_path, cp_globs, out_path) + finally: + shutil.rmtree(repo_path) + renames = [(re.compile(in_exp), out_exp) for in_exp, out_exp in renames] + fnames = [] + for rep_glob in rep_globs: + fnames += fnmatch.filter(out_fnames, rep_glob) + if verbose: + print '\n'.join(fnames) + for fname in fnames: + filename_search_replace(replace_pairs, fname, False) + for in_exp, out_exp in renames: + new_fname, n = in_exp.subn(out_exp, fname) + if n: + os.rename(fname, new_fname) + break + + +USAGE = ''' <output_directory> <project_name> + +If not set with options, the repository name is the same as the <project +name> + +If not set with options, the main github user is the same as the +repository name.''' + + +GITWASH_CENTRAL = 'git://github.com/matthew-brett/gitwash.git' +GITWASH_BRANCH = 'master' + + +if __name__ == '__main__': + from optparse import OptionParser + parser = OptionParser() + parser.set_usage(parser.get_usage().strip() + USAGE) + parser.add_option("--repo-name", dest="repo_name", + help="repository name - e.g. nitime", + metavar="REPO_NAME") + parser.add_option("--github-user", dest="main_gh_user", + help="github username for main repo - e.g fperez", + metavar="MAIN_GH_USER") + parser.add_option("--gitwash-url", dest="gitwash_url", + help="URL to gitwash repository - default %s" + % GITWASH_CENTRAL, + default=GITWASH_CENTRAL, + metavar="GITWASH_URL") + parser.add_option("--gitwash-branch", dest="gitwash_branch", + help="branch in gitwash repository - default %s" + % GITWASH_BRANCH, + default=GITWASH_BRANCH, + metavar="GITWASH_BRANCH") + parser.add_option("--source-suffix", dest="source_suffix", + help="suffix of ReST source files - default '.rst'", + default='.rst', + metavar="SOURCE_SUFFIX") + (options, args) = parser.parse_args() + if len(args) < 2: + parser.print_help() + sys.exit() + out_path, project_name = args + if options.repo_name is None: + options.repo_name = project_name + if options.main_gh_user is None: + options.main_gh_user = options.repo_name + copy_replace((('PROJECTNAME', project_name), + ('REPONAME', options.repo_name), + ('MAIN_GH_USER', options.main_gh_user)), + out_path, + options.gitwash_url, + options.gitwash_branch, + cp_globs=(pjoin('gitwash', '*'),), + rep_globs=('*.rst',), + renames=(('\.rst$', options.source_suffix),))