Git Workflow-Contributor


NOTE: The instructions on this page are for developers with commit access to the sproutcore repository who are not integrators.  If you do not have commit access or if you are an integrator, you will need to follow different instructions.

  

Now that you have SproutCore checked out on your machine, it's time to begin development.  SproutCore's development is done with git, which is a very flexible source control system designed for large teams working in parallel.

 

This page explains how you should use Git when working on SproutCore source if you have commit privileges to the main repository.  If you do not have commit privileges, you should instead "fork" the SproutCore repository on github and then consider using this same process for your own development team.

 

Branches

 

In git you work with branches.  In fact, git workflow encourages you to create many topic branches, one for each different task that you work on, so that you can easily manage the flow of your code.

 

The "official" branch of SproutCore code in git is called master.  Normally you will not make changes directly to this branch unless you are an integrator for the project.  Instead, you will often submit your work under branches labelled with your own username.  For example, any code you have written that you would like to have merged into the master branch will be on a branch called your_github_username/master.  

 

If all of this seems a bit confusing, don't worry.  With a simple change to your git configuration, git will actually handle all of the branching workflow for you.  You just work like normal.

 

Getting Started

 

Inside the root folder of every git repository is a folder called ".git".  Inside of this folder is a file called "config".  This .git/config file contains all of the setup information about your repository and how it connects to the repository on Github (called the "upstream" repository).  Normally this file is edited automatically when you add branches, pull code from origin and so on.    In this case, however, we're going to have you add one line to this config that will make your daily work much easier.

 

If you have setup abbot, you will need to add this line to three config files:  abbot/.git/config,  samples/.git/config, and samples/frameworks/sproutcore/.git/config.  Open each config file and locate the line:

 

  [remote "origin"]

 

Directly beneath this line, add the line:

 

    push = +refs/heads/your_github_username/*:refs/heads/your_github_username/*
 

Replace your_github_username with your username on GitHub. When you do "git push", this will automatically push all any topic branch beginning with your github username to the master repository.

 

With this setup, you now should create your personal master branch and your first topic branch.  To create your personal master branch just run the following command:

 

     git checkout -b your_github_username/master master

 

As before, change your_github_username to your username on GitHub.  This personal master branch is where you will submit changes that you want to have integrated into the main master branch shared by all developers.  

 

Next, you should create your first topic branch.  In general you should create topic branches anytime you begin work on a new task.  Topic branches are your personal workspace; no one else will review or edit code on these branches unless you ask them to.  To create your first topic branch, just type the following:

 

     git checkout -b your_github_username/your_topic_name your_github_username/master

 

Choose any topic name you want for the above.  This will create the branch as an offshoot from your personal master branch.  

 

You are now setup to use the workflow defined below.  Follow the instructions in each section to work efficiently.

 

Your Daily Workflow

 

Each developer's "master" branch should only contain commits that are ready to be merged into SproutCore's master branch on GitHub. This implies two things: first, all unit tests pass in your master branch. Second, that all in-progress development work you do will be done in topic branches.

 

Creating a new branch 

 When you are ready to start work on a new task (or "topic"), the first thing you will want to do is to create a branch.  Create the branch with this command:

 

     git branch my_new_branch master

 

Replace my_new_branch with the name of your branch.  Now you can checkout this branch to begin work:

 

     git checkout my_new_branch

 

Commiting (Saving) Your Changes

 Unlike subversion, commit changes in git does not share your changes with the rest of the world.  It simply saves your changes to your local repository.  Think of it like hitting "save" in TextMate.  You should get into the habit of committing every time you reach a small milestone in your programming.  This way anytime you end up going down a path you later regret, you can easily back up to a point where you were happy with your code.

 

When you have made some changes to your branch that you would like to save, just commit them:

 

     git commit -a -m"Description of my commit"

 

Note that if you have added new files to the project, you will need to do 

 

     git add .

 

before you commit to add them to the repository.  Once a commit has finished, you can verify that everything is in cleanly by checking the status:

 

     git status

 

Backing-up Your Changes

 In addition to saving your changes on your local machine, you should also backup your changes to the shared repository and the end of every day when you are finished so that none of your work will be lost if something happens to your computer in the meantime.

 

Anytime you want to backup your committed changes to the github repository you can do so very easily with the command:

 

     git push

 

This will push all of your branches to the master github repository.  You can log into http://github.com and visit the private-sproutcore repository to verify that your changes were indeed saved.  Click on the "Branches" tab at the top to select your branch.  Your branches on github will always be preceded with your username.

 

Pushing your changes to the upstream git repository is also a great way to share your changes so that others can review them.  For example, let's say you've been working on a new feature for some time with another developer and you want the other developer to review it before you submit it for integration into the master branch.  You can push your changes and then ask the other developer to take a look at your custom branch.

 

Keeping Your Source Up-to-date 

 When you want to sync the latest source changes from the master repository, you can do so by following the instructions here.  It's usually a good idea to check for any new changes each day before you begin work on your code.  You can check for new changes by asking git to download any new updates from your origin server:

 

    git fetch origin

Updating Your Personal Master

If git tells you that every was up to date or only lists changes on branches OTHER than the "master" branch, then you're done.  If it lists some changes, then you should first update your personal master branch to reflect the latest changes:

 

    git checkout your_github_username/master
    git rebase origin/master # this replays your personal master branch on top of origin/master

Resolving Conflicts

If you have any conflicts with the new master branch, they will be reported here.  This won't happen often but when it does, you will need to fix the conflicts in each file listed by git (look for the "CONFLICT" keyword in the output), then finish the rebase using the command:

 

     git rebase --continue

 

If after attempting a rebase you discover so many conflict that it makes you wish you hadn't attempted a rebase quite yet, you can also abort the rebase using:

 

     git rebase --abort

 

This will reset your git repository to the state that it was in before you started the rebase.  You can then do any work you might need to do to prep your code for the rebase before attempting it again.

 

Updating Your Topic Branch

Once you've updated your personal master branch, you should update the topic branch you are working on:

 

   git checkout your_github_username/topic_branch
   git rebase your_github_username/master

Do this for each topic branch you are working on to get the latest changes.  If you get conflicts, follow the same instructions as above to resolve them.  Continue this process until git says the rebase completed successfully.

 

This may seem like a lot of steps today to get updates into your repository, but there is a reason for it!  One of the biggest challenges with managing source code is dealing with the effects of bad merges.  By breaking down the update process into steps like this, you gain a great deal of control over decided when and how to propagate changes to your different branches.  Although you will eventually need to update your code, it won't belong before this level of control allows you to expertly control how your changes move in and out of the master repository.

 

Submitting Your Changes for Integration

 After you've worked on a topic branch for a while you are eventually going to want your changes to be integrated back into the main repository.  You do this easily by simply merging your topic branch into your personal master.   

 

IMPORTANT:  Before you merge your topic branch into your personal master, you must make sure both your personal master and your topic branch are up-to-date with the main master branch.  If you don't do this, your master branch may not merge cleanly and the integrator will not include your code until you bring it up to date.  Follow the instructions in the previous section to make sure your personal master and topic branch is up to date.

 

Once you have your branches up to date, run these git commands to merge and push your changes:

 

     git checkout your_github_username/master

     git merge your_github_username/topic_branch

     git branch -d your_githhub_username/topic_branch # remove the topic branch since you are done

     git push

 

The changes on your master branch will now be visible to the integrator who can review your changes and apply them to the overall master.  Be sure to update your branch again later to bring it up to date to the new master once your changes have been integrated!

 

Reverting Changes

 What happens when you make some changes that you no longer want to keep?  If you have been commiting along the way whenever you reach a stable point, you can easily revert changes you've made since your last commit with the command:

 

     git reset --hard

 

This will simply reset your code to the last commit that you made.  If you have already committed some code and you need to revert the commit you can do that also using the revert command.  There are a number of ways to use revert.  The best way to learn about it is to try the command "git revert --help".  But in a pinch, you can always use the method below as well.

 

To revert a particular commit, first make sure you have pushed all of your changes to github.  Then log into http://github.com and visit your working branch on the repository.  Click on the "commits" tab at the top to see your commit history.  Look for the commit that you want and note the "current" commit number to the right.  This will be a hash code of 32 characters.  Then on your command line do:

 

     git revert commit    

 

Replace commit with the commit number you found on github.  This should revert the change for you, assuming there are no merge errors.