Getting started with Git ======================== Installing Git -------------- Git is available for Linux, Mac OS X, and Windows. For Linux, it will certainly be available in your package manager. For Windows and Mac OS X, download from http://git-scm.com/downloads. If you're using SourceTree (download from http://www.sourcetreeapp.com), Git is included. .. image:: images/sourcetree_install/2.png :target: http://www.sourcetreeapp.com Once you've installed it, you should tell Git about yourself: .. code-block:: bash git config --global user.name Andrew Davison git config --global user.email andrew.davison@unic.cnrs-gif.fr If using SourceTree, you can set this information in the preferences. .. image:: images/sourcetree_preferences.png Creating a repository --------------------- We start by introducing three concepts: **Working copy** the set of files that you are currently working on **Index** a staging area **Repository** a "database" containing the entire history of your project (all versions) .. image:: http://rogerdudler.github.io/git-guide/img/trees.png As an example, we will use the Brian code from this paper: Brette R, Rudolph M, Carnevale T, Hines M, Beeman D, Bower JM, Diesmann M, Morrison A, et al. (2007) Simulation of networks of spiking neurons: A review of tools and strategies. *J Comp Neurosci* **23**:349-98 available from http://senselab.med.yale.edu/modeldb/showmodel.asp?model=83319 .. code-block:: bash $ unzip destexhe_benchmarks.zip $ cd destexhe_benchmarks $ cp -r Brian ~/my_network_model $ cd ~/my_network_model $ ls COBA.py COBAHH.py CUBA.py README.txt We're going to take this code as the starting point for our own project, and we want to keep track of the changes we make. The first step is to create a repository, where all the versions will be stored. This is very simple: .. code-block:: bash $ git init Initialized empty Git repository in /Volumes/USERS/andrew/my_network_model/.git/ Nothing seems to have happened. In fact, the :command:`git init` command has created a new subdirectory: .. code-block:: bash $ ls -a . .. .git COBA.py COBAHH.py CUBA.py README.txt You almost never need to care about what is in this directory: this is where Git will store all the information about the repository. With SourceTree, you create a new repository via the File menu: .. image:: images/sourcetree_new_menu.png .. image:: images/create_new_repository.png Adding files to the repository ------------------------------ Now we need to tell Git which files are part of our project. On the command line: .. code-block:: bash $ git add * .. code-block:: bash $ git status On branch master Initial commit Changes to be committed: (use "git rm --cached ..." to unstage) new file: COBA.py new file: COBAHH.py new file: CUBA.py new file: README.txt In SourceTree, we can see our files listed as "Unstaged" .. image:: images/sourcetree_initial.png When we check the boxes, they are listed as "Staged". .. image:: images/sourcetree_staged.png Committing changes ------------------ These files are now *queued* or *staged* to be added to the repository, but they are not yet there. Nothing is definitive until we make a *commit* (also known as a "*check-in*"). Via the command line: .. code-block:: bash $ git commit -m "Initial version, downloaded from http://senselab.med.yale.edu/modeldb/showmodel.asp?model=83319 on July 3rd 2014" [master (root-commit) b0c5d2c] Initial version, downloaded from http://senselab.med.yale.edu/modeldb/showmodel.asp?model=83319 on July 3rd 2014 4 files changed, 259 insertions(+) create mode 100644 COBA.py create mode 100644 COBAHH.py create mode 100644 CUBA.py create mode 100644 README.txt Via SourceTree; in both cases we have to give a short message summarizing what changes were made. .. image:: images/sourcetree_commit0.png Viewing the history of changes ------------------------------ The log command lists all the different versions stored in the repository. For now, of course, we have only one: .. code-block:: bash $ git log commit d66ee50a3975d6e46be27055bf0ecb4d8091c082 Author: Andrew Davison Date: Thu Jul 3 15:36:45 2014 +0200 Initial version, downloaded from http://senselab.med.yale.edu/modeldb/showmodel.asp?model=83319 on July 3rd 2014 In SourceTree, we use the "Log" view. .. figure:: images/sourcetree_log.png Now let's run the code: .. code-block:: bash $ python COBAHH.py Network construction time: 0.814524173737 seconds Simulation running... Simulation time: 45.7264661789 seconds 126014 excitatory spikes 29462 inhibitory spikes This pops up a window with the following figure: .. image:: images/brian_figure.png We'd prefer to save the figure to a file for further use, rather than work with the model interactively, so let's change the last lines of the script from: .. code-block:: python plot(trace.times/ms, trace[1]/mV) plot(trace.times/ms, trace[10]/mV) plot(trace.times/ms, trace[100]/mV) show() to .. code-block:: python plot(trace.times/ms, trace[1]/mV) plot(trace.times/ms, trace[10]/mV) plot(trace.times/ms, trace[100]/mV) savefig("COBAHH_output.png") Seeing what's changed --------------------- Now if we run :command:`git status` we see: .. code-block:: bash $ git status On branch master Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: COBAHH.py no changes added to commit (use "git add" and/or "git commit -a") .. code-block:: bash $ git diff diff --git a/COBAHH.py b/COBAHH.py index d9eda02..22bcf1a 100644 --- a/COBAHH.py +++ b/COBAHH.py @@ -93,4 +93,4 @@ print Mi.nspikes,"inhibitory spikes" plot(trace.times/ms,trace[1]/mV) plot(trace.times/ms,trace[10]/mV) plot(trace.times/ms,trace[100]/mV) -show() +savefig("COBAHH_output.png") This is even easier in SourceTree: we automatically see a list of files that have been changed, and a colour-coded view of what has changed. .. image:: images/sourcetree_firstchange.png Now let's commit the changes... .. code-block:: bash $ git add COBAHH.py .. code-block:: bash $ git commit -m 'Save figure to file' [master 1c5d37f] Save figure to file 1 file changed, 1 insertion(+), 1 deletion(-) .. code-block:: bash $ git log commit b535fafe86c0caeb2b38ef30f0e96c9904ff56d6 Author: Andrew Davison Date: Thu Jul 3 15:47:45 2014 +0200 Save figure to file commit d66ee50a3975d6e46be27055bf0ecb4d8091c082 Author: Andrew Davison Date: Thu Jul 3 15:36:45 2014 +0200 Initial version, downloaded from http://senselab.med.yale.edu/modeldb/showmodel.asp?model=83319 on July 3rd 2014 .. image:: images/sourcetree_commit1.png ... and look at the log again: .. image:: images/sourcetree_log1.png We see both versions, with commit messages, the author name and the date. Switching between versions -------------------------- To switch between versions (you should not do this if you have modified any of the files - commit your changes first), use :command:`git checkout`: .. code-block:: bash $ git checkout d66ee50a3975d6e46be27055bf0ecb4d8091c082 Note: checking out 'd66ee50a3975d6e46be27055bf0ecb4d8091c082'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at d66ee50... Initial version, downloaded from http://senselab.med.yale.edu/modeldb/showmodel.asp?model=83319 on July 3rd 2014 This will change the files in your working copy to reflect the state they had when you committed that particular version. (You can ignore the message about 'detached HEAD' for now). We can check that our working copy has really changed by looking at the end of the COBAHH.py file: we see that we are back to using the "show()" command instead of "savefig()". .. code-block:: bash $ tail COBAHH.py run(1000*msecond) duration=time.time()-start_time print "Simulation time:",duration,"seconds" print Me.nspikes,"excitatory spikes" print Mi.nspikes,"inhibitory spikes" plot(trace.times/ms,trace[1]/mV) plot(trace.times/ms,trace[10]/mV) plot(trace.times/ms,trace[100]/mV) show() Using :command:`git branch` we can see which version we are currently using: .. code-block:: bash $ git branch * (detached from d66ee50) master In SourceTree, just click on the version you want to use. This will add a label "HEAD" to show you which version is currently checked out. .. image:: images/sourcetree_checkout_v0.png To switch to the most recent version, use `git checkout master` .. code-block:: bash $ git checkout master Previous HEAD position was bfb2cd7... Initial version, downloaded from http://senselab.med.yale.edu/modeldb/showmodel.asp?model=83319 on July 3rd 2014 Switched to branch 'master' .. code-block:: bash $ git branch * master Giving informative names to versions ------------------------------------ Remembering the version number for a particular version of interest (for example, the version used to generate a particular figure in your manuscript) can be difficult. For this reason, the :command:`git tag` command can be used to give descriptive and memorable names to significant versions: .. code-block:: bash $ git tag Figure-1 You can now switch to a tagged version using the tag name: .. code-block:: bash $ git checkout Figure-1 In SourceTree, just right-click on the version you want to tag. .. image:: images/sourcetree_tag.png The tag is now shown in the log. .. image:: images/sourcetree_tag2.png Recap #1 -------- So far, we have learned how to: * Create a repository * Add files to a repository * Commit changes * Move your code-base backwards and forwards in time These operations are so easy and so useful that there is no reason not to use them for almost any work you do as a scientist. Any time I start a new project, whether writing code or writing a paper with LaTeX, I now run :command:`git init` as soon as I've created a new directory for the project.