Developer cheatsheet for git

Starting: getting the latest source
First you need to create your own local clone of the SourceForge repository. There are two options:

(a) If you are going to push changes back to the SF repository (using your SF username) do:

git clone --recursive ssh://yourusername@supercollider.git.sourceforge.net/gitroot/supercollider/supercollider

(b) If you don’t have an account in SourceForge or you don’t want to push changes (so will instead be contributing via patches or pull-requests), then use anonymous access:

git clone --recursive git://supercollider.git.sourceforge.net/gitroot/supercollider/supercollider

("--recursive" is needed to get all submodules, which make it easier to maintain parts of a repository)

Pull: How to get new changes from the main repository
Normally, you will pull only from the sourceforge repository ("origin"). That is simple.

git pull --rebase git submodule update

(If you are not doing development work, you can omit "--rebase.")

--rebase keeps your repository in sync with the order of committed changes in the origin. This is required before pushing your changes back to origin.

git submodule update is needed because git pull does not update shared library code contained in the submodules. If you forget to do this, you will probably get build errors related to boost. Most of the time, git submodule update is sufficient to fix those errors.

With git, it's also possible to pull changes from different clones of the same repository. For instance, you might have two or three computers that you use at different times. You can synchronize those clones over a local network without touching sourceforge!

The easy way:

git pull https://johnny.com/repo.git johnnys-branchname   #get his changes git pull --rebase 	#update master from SourceForge git push
 * 1) check that everything is okay

The hard way:

git checkout -b merge-johnnys-changes git pull https://johnny.com/repo.git johnnys-branchname   #get his changes git checkout master git pull --rebase 	#update master from SourceForge git rebase master merge-johnnys-changes #put johny’s changes on top of latest changes from SourceForge git checkout master git merge merge-johnnys-changes git push
 * 1) check that everything is okay, then push changes back to SourceForge.

taken from here

Commit + Push
Unlike in SVN, publishing changes is a two-step process in git:


 * 1) Commit the changes. The changes are now "permanent" in your local clone of the repository.
 * 2) Push the new commits into the public repository.

This has the advantage over SVN that you can manipulate the changes after committing but before pushing. If you made a mistake with some commits, you can git reset them, erasing them from your local repository. Then you can recommit before pushing.

Highly recommended: Set your global git configuration so that git push with no arguments will push only the current branch. Otherwise, if you forget to say git push origin [branch], git will helpfully push all commits from all branches, including ones that you forgot about and didn't intend to make public. Once changes are pushed to the public repository, they can't be erased -- only reverted. Doing this will help to avoid headache-inducing mistakes.

git config --global push.default upstream

If you're using an older version of git, substitute "tracking" for "upstream."

git config --global push.default tracking

Branches
Another really helpful way to save you from yourself is to work in a local branch that doesn't exist in the public repository. If you are new to git, you will make mistakes. If you make mistakes in a published branch, such as "master," and you accidentally push those mistakes, it may take some effort to clean up. But if you work in a branch that exists only on your local machine, you can do anything you want with it, and then selectively move specific commits into a public branch.

With a local-only branch, the worst case (completely messing up the branch) is that you delete the local branch and re-create it, with no impact on the origin.

The "-b" option to git checkout creates a new branch from an existing one.

git checkout master -b my_master   #now you have your own disconnected branch of master ... work work work, commit stuff, blah blah...

git log  #take note of the commit IDs, which are 32 digit hexadecimal strings

git checkout master  #switch back to the real master branch git cherry-pick [ID]  #repeat for each ID git cherry -v   #doublecheck what will actually be pushed git push origin master

git checkout my_master  #safe again

git cherry-pick is a bit inconvenient for large numbers of commits. In that case, it would be better to use a "topic branch." See below, "Using a separate branch for work on a feature."

A common git workflow for development work on SuperCollider
Make sure you've done the "git clone" stuff above, then...

Simple work on your main (master) branch
Hack on existing files, create new files...

Display and check uncommitted changes:

git diff master

Stage changed and new files (mark them for inclusion in the next commit):

git add file1 file2 file3

Check which changed files are staged and which not:

git status

Commit the staged changes and additions:

git commit -m "This commit does this and that..."

Repeat the above procedure for as many separate commits as you want.

Update your local repository with latest commits in the public repository:

git pull --rebase git submodule update

Check what you will be pushing:

git log origin/master..

Push it:

git push

Using a separate branch for work on a feature
Sometimes you want to work on several unrelated features during the same period of time and you want to be able to switch between your work on one or another. You can do this by using several branches within your local repository. Each branch allows you to store your work on a feature in form of commits on top of the commit history at the time the branch was created. By default, each repository contains one branch named master, but you can create new ones (and even rename any of them later, including master).

- Create a new branch named "my_new_feature" containing all the commits in the current branch:

git checkout -b my_new_feature

By the way 'git checkout branch_name' switches between branches. 'git status' will tell you which branch you are currently on.

Now start coding your changes, and commit them into your feature branch with 'git add' and 'git commit' as explained in the previous section.

While you are coding your new feature you might need to update the branch with latest changes from the remote (public) repository, to keep up with other developments. The safest way to do this is to update your master branch and then rebase commits introduced by your feature branch on top of the master. Be sure to have all local changes committed before doing this:

1) git checkout master

2) git pull --rebase

3) git rebase master my_new_feature

When you are ready to push the work on the feature to the public repository, first do the above three steps to synchronize your local repository with the public one, then check what you are going to push with 'git log origin/master..' and do the following:

1) git checkout master

2) git merge my_new_feature

3) git push

This will merge the additional commits of your feature branch into the master and push them public. For additional details about rebase, see (4).

Common git commands
upstream - the SourceForge git repository.

fetch and merge changes from upstream:

git pull

commit all local changes:

git commit -a -m “message”

commit changes in specific files:

git add 

git commit -m “message”

get patch files for last N commits

git format-patch -N

get patch files for all commits that are in your current branch but not in upstream:

git format-patch origin/master

undo (delete) all current non-commited changes (Watch out !):

git reset --hard HEAD

undo last commit, but leave the changes in the working tree

git reset --soft HEAD^1

undo (delete) all commits since last time one was pulled from upstream (Watch out !). This should be done while in the master branch:

git reset --hard origin/master

undo all commits since the last time one was pulled from upstream but leave the changes in the working tree. This should be done while in the master branch:

git reset --soft origin/master

show uncommited local changes:

git diff [file]

discard local changes instead of commiting them:

git checkout —

add interactively

git add -i

To revert local commits, revert will create another commit that undoes the commit provided. Unlike reset the history is not erased.

git revert 

show changes compared to upstream:

git diff origin/master   # only diff

git show origin/master.. # log and diff

git log origin/master.. # only log

show latest log in upstream:

git log origin/master

see status of changes:

git status

Testing mailing list patches
To try out emailed patches (created with git send-mail) copy all the content of the original mail message in a file, e.g. patch.mbox, and remove all the empty/white-spaces lines from the beginning of that file. If the patch is a series of mails copy all in order in the same file (the subject has an order tag [PATCH 0/N], [PATCH 1/N], ..., [PATCH N/N]).

Note: in gmail go to the option "show original" and copy the plain text message.

Create a branch to try the patch

git checkout -b solve_problem_patch

Apply and merge the patch with am (apply mailbox)

git am -3 patch.mbox

After testing it the branch can be erased (be careful any change will be lost)

git branch -D solve_problem_patch

Note: this workflow is useful just to try a patch and discard changes for other solutions check the Resources.

Resources

 * 1) Git Book
 * 2) Pro Git Book
 * 3) Visual Git Tutorial
 * 4) Rebasing
 * 5) My Git Workflow

contributed by: Miguel Negrão, Jakob Leben, Jonatan Liljedahl, James Harkins