{{tag>development git}} ====== Accessing the FieldTrip source code through Git ====== The FieldTrip code is accessible using [[http://git-scm.com/|git]] at [[http://github.com/fieldtrip/fieldtrip|github]]. <note> To quickly get access to the code, you would do the following from the command line or the equivalent in a graphical git interface, such as the [[https://desktop.github.com|GitHub desktop]]. <code> git clone https://github.com/fieldtrip/fieldtrip </code> Note that all of this goes on a single line, but the link is slightly too long for it being properly displayed here. This allows you to easily track the changes that we make to the code. If you also want to contribute back, please make an account on github, fork FieldTrip to our own account and read on for a complete tutorial. </note> To keep an eye on the changes to the code, you can follow FieldTrip on [[http://twitter.com/fieldtriptoolbx|Twitter]]. ===== Development workflow ===== We use git and github.com (see below) in combination with a [[https://www.atlassian.com/git/tutorials/comparing-workflows#forking-workflow|Forking Workflow]] for our development. We complement this with code reviews by the core team and quality control using running a set of test scripts. The general procedure is as follows: - The contributor/developer makes the suggested changes in a branch, pushes that branch to his/her own fork (on github) and submits a pull request. - The core team reviews the code in the pull request. The suggested change should make sense, fit in the larger strategy, should be consistent with other code, and should be documented. - The code in the pull request is tested by the core team to ensure that it does not break anything. - After successful reviewing and testing, the core team merges the pull request with the master branch. ===== How to contribute with git and github.com ===== We welcome the contribution of external users, even if the changes consist of a few lines of code. The git version control system offers a simple and straightforward way to add your contribution to the FieldTrip toolbox. ==== What is git? ==== [[http://git-scm.com/|git]] is version control system to keep track of the changes to files and maintain a consistent repository, just like [[http://subversion.tigris.org/|svn]]. While svn follows a linear approach to version, where each user makes some changes to the main code and then a second user can make some other changes, git allows for multiple users to work in parallel and then merge their code in the main repository. This approach scales very well, considering that, for example, the [[http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git|Linux kernel]] and [[https://android.googlesource.com/| android]] use git. There are lots of resources available on the internet to learn more about git. The starting point is [[http://git-scm.com/documentation|this documentation]]. If you have a question, it's most likely already being answered at [[http://stackoverflow.com/questions/tagged/git|Stack Exchange]]. git is extremely powerful and flexible, so the following tutorial will give only the most basic ideas and tools to modify the FieldTrip code. === Basic concepts === == push, pull, clone == git lives on two levels: - on your local computer - on a remote server Both contain a full repository of the whole code. The basic idea is that you make some changes on your local copy and then send them to the remote server. Sending changes to a remote repository is called [[http://git-scm.com/docs/git-push|pushing]] and receiving changes from a remote repository to your local machine is called [[http://git-scm.com/docs/git-pull|pulling]]. The first time that you want to copy a complete repository from a remote server to your local machine, you need to [[http://git-scm.com/docs/git-clone|clone]] the repository. == commit == Your local repository is a complete repository of the whole source code. As such, you can modify some files (or even adding some files) and then include these changes to the local repository. This procedure is called [[http://git-scm.com/docs/git-commit|commit]]. The changes that are committed to your local repository are called **commits**. == branch, merge == One of the most powerful features of git is the idea of [[http://git-scm.com/book/en/Git-Branching|branching]]: //Branching means you diverge from the main line of development and continue to do work without messing with that main line//. So, from your local repository, you can create a new branch, make some changes, commit them. If you are happy with the changes, you can [[http://git-scm.com/docs/git-merge|merge]] your new branch with the main development line. Branches are very flexible because they allow you to develop new features without compromising the main repository. You can easily switch between the main branch (often called **master**) and experimental branches. == Main commands == To recap, the main commands that you'll need here are: * **clone** to create a new local repository based on a remote repository * **push** to send your local changes to the remote repository * **pull** to receive the remote changes on your local repository (it runs two processes: **fetch**, where the remote changes are downloaded, and **merge**, where the changes are integrated into your local repository) * **commit** to add some changes to your local repository * **branch** to list the branches * **checkout** to switch to an existing branch * **checkout -b** to create a new branch * **merge** to merge a branch with your main local repository. You can use any of these commands on the command line, in Linux and Mac, by doing: <code>git name_of_the_command</code> For example, using <code>git checkout master</code> you will switch from a side branch into the main branch of your repository. ==== What is github.com? ==== [[http://github.com|github.com]] is a fast, intuitive and popular website to share code. The interface is clean and intuitive, and many projects are hosted there, including [[https://github.com/fieldtrip/fieldtrip|FieldTrip]]. ==== How to add a feature or fix a bug ==== You only have read permission for the [[https://github.com/fieldtrip/fieldtrip|FieldTrip]], meaning that you cannot change directly the code of the FieldTrip repository. What you can do, and you will see how to do it here, is: - Copy the FieldTrip repository under your private account on github.com (this is called **forking**). - This new personal repository will become your __remote repository__. You will need __clone__ the remote repository onto your local machine. - You will create a new __branch__, edit some files, __commit__ them to the developmental branch of your __local repository__. - Then you can __push__ this developmental __branch__ to your __remote repository__. - You will then tell to the developers of FieldTrip to check these changes in your __remote repository__, using a **pull request**. All the __underlined__ words are the new concepts explained above. **Forking** and **pull request** are two main concepts when working with multiple remote repositories. I will use them throughout the tutorial and are the words that you will need to successfully google possible problems. If they are not clear, refer to the main [[http://git-scm.com/documentation|documentation]]. ===== Tutorial ===== Now that the main concepts are explained, we will try to add a new feature to FieldTrip using a minimal example. In our case, what we think that FieldTrip really needs is that when you run **[[:reference:ft_defaults]]**, you get a text saying //Welcome to FieldTrip//. So we need to create a new function that prints //Welcome to FieldTrip// and modify the existing function **[[:reference:ft_defaults]]** to run our new function. We expect that you already have git running on your system (see [[http://git-scm.com/book/en/Getting-Started-Installing-Git|installation instructions]]) and that you have an account on [[http://github.com]] (see [[https://help.github.com/articles/set-up-git|set up git]]). Let's say that your username on github is //USERNAME//. ==== 1. Fork the main FieldTrip ==== Go with your web browser to [[https://github.com/fieldtrip/fieldtrip]] and click on the right-hand side, towards the top, on **fork**. This will create a new remote repository in your github account at the address: https://github.com/USERNAME/fieldtrip. The title of your repository will say: <code> username / fieldtrip forked from fieldtrip/fieldtrip </code> ==== 2. Clone your remote repository ==== Now you can just clone your remote repository. There are two equivalent methods to connect to your remote repository: https (see [[https://help.github.com/articles/set-up-git|setup instructions]]) or ssh (see [[https://help.github.com/articles/generating-ssh-keys|setup instructions]]). If you're using https, then: <code> git clone https://github.com/USERNAME/fieldtrip.git </code> If you're using SSH, use: <code> git clone git@github.com:USERNAME/fieldtrip.git </code> Now you have a local repository of FieldTrip that you can work on. Then go into the just-created FieldTrip directory: <code> cd fieldtrip </code> ==== 3. Create an experimental branch ==== Before you start editing files, create a new branch. We will call our new branch //welcome//. Let's create it: <code> git checkout -b welcome </code> and it'll tell you: <code> Switched to a new branch 'welcome' </code> If you have filed a bug on [[/bugzilla|Bugzilla]], you could name your new branch //bugXXXX// where XXXX is the number of the bug. ==== 4. Add and edit files ==== Now we need to create a function that says //Welcome to FieldTrip//. Let's call it //ft_welcome.m//, just as you'd create any new Matlab function. <note important> When you create a new function or edit an existing one, follow the [[/development/guidelines/code|code guidelines]] for a consistent and readable code. </note> In addition to this function, we will also modify the function **[[:reference:ft_defaults]]**. ==== 5. Commit your changes ==== To see how git reacts to this changes, you can now type: <code> git status </code> It will tell you: <code> # On branch welcome # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: ft_defaults.m # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # ft_welcome.m no changes added to commit (use "git add" and/or "git commit -a") </code> If you want to review the changes you made, you can type: <code> git diff </code> Now we add our changes to the commit: <code> git add ft_welcome.m ft_defaults.m </code> and now //git status// will tell you: <code> # On branch welcome # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: ft_defaults.m # new file: ft_welcome.m # </code> You can now commit these changes. <code> git commit -m "print welcome message when executing ft_defaults" </code> where the option -m allows you to add a log entry. <note important> Follow these [[/development/guidelines/code#svn_log_messages|guidelines]] when writing a log entry. </note> and git will return: <code> 1 file changed, 1 insertion(+) create mode 100644 ft_welcome.m </code> === Switch to master === While you are working on the developmental branch called //welcome//, you might want to run some analysis on the main branch (called by default //master//). You can easily switch into the main branch with: <code> git checkout master </code> and then you go back to the developmental branch with <code> git checkout welcome </code> You see on which branch you are with <code> git branch </code> Switching between branches is really fast, so do not be afraid of doing it when necessary. ==== 6. Push the commits ==== We modified our local repository but the remote repository has not changed. We need to push our commits to the personal remote repository. By default, the remote repository is called **origin**. You can rename it. If you want more information about remote repository, just type: <code> git remote -v </code> The code to push commits is: <code> git push origin welcome </code> which means that we are pushing the commits in the branch called //welcome// to the remote repository called //origin//. This will create a new branch in your remote repository, as the last line of the output will kindly tell you: <code> ... * [new branch] welcome -> welcome </code> ==== 7. Make a pull request ==== Go to [[https://github.com|github.com]] to review the changes. By default on the webpage, you are shown the branch //master//, so you should switch to the newly created branch called //welcome//. Review the commits, by clicking on //commits//. Click on **pull request** in the top middle. The next page will show you the changes that are part of the pull request. <note important> You are about to send the changes to the main developers of FieldTrip, so explain in the box what you did and why. Please, review the commits very carefully before sending the pull request. It happens that you have commits that you forgot about and you did not intend to share. </note> Do **not** click on **Send Pull Request** when finishing this tutorial. ==== 8. Clean up ==== When you are done, you can delete the branch //welcome// on the local and remote repository. To delete the branch on your local and remote repository, you can use: <code> git branch -D welcome git push origin :welcome </code> ==== 9. Keeping up to date ==== Your suggested contributions to FieldTrip will not be the only changes: the code on the master branch is constantly updated. This means that you should regularly synchronize to benefit from these updates and to ensure that you won't be making changes to an outdated copy of the code. <note important> It is important to first pull the changes from others before you start implementing your own changes, otherwise your (new) changes might conflict with already accepted changes to the code. </note> Synchronizing between the different repositories is done by using your local (i.e. hard disk) copy as intermediary. By default your personal copy of the repository on github will be called the //origin//. You can check this with git remote -v which will show you origin git@github.com/USERNAME/fieldtrip.git (fetch) origin git@github.com/USERNAME/fieldtrip.git (push) or the corresponding URL with https instead of git. To synchronize with the official fieldtrip repository on github, you should also add it as a remote. Best practice is to call it the //upstream// repository. You add it with git remote add upstream https://github.com/fieldtrip/fieldtrip.git git remote -v will now show you both remotes origin git@github.com/robertoostenveld/fieldtrip.git (fetch) origin git@github.com/robertoostenveld/fieldtrip.git (push) upstream https://github.com/fieldtrip/fieldtrip.git (fetch) upstream https://github.com/fieldtrip/fieldtrip.git (push) You can pull (download) from the //upstream// repository and push (upload) to your own //origin// repository. To pull the changes from the master branch of the (official) //upstream// FieldTrip repository, you would do git checkout master git pull upstream master This may (or may not) show changes to files and new files that were added. Subsequently, you can push those changes to the master branch of your //origin// personal github repository with git push origin master After this, both the local copy on your hard drive and your copy on [[http://github.com|github.com]] will be up to date with the official release. Troubleshooting: pushing your master branch to your //origin// personal github repository may throw the error "This repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/pre-push." This .git directory can be found in the local directory of your repository (../fieldtrip/.git). Working with remotes is explained in more detail in the [[http://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes|Git book]]. ===== Want more? ===== [[http://github.com|github.com]] offers lots of documentation. In particular, see the detailed instructions to [[https://help.github.com/articles/fork-a-repo|fork a repository]] and to [[https://help.github.com/articles/using-pull-requests|create a pull request]]. If you plan to continue development, I suggest to set up your remotes with //origin// pointing to your personal remote repository and //upstream// pointing to [[https://github.com/fieldtrip/fieldtrip]], as described in [[https://help.github.com/articles/fork-a-repo|fork a repository]].