Table of Contents

Using git

git is a general purpose version control system that supports numerous workflows. This document discusses two key ways to use git.

Testing Workflow

If you don't plan on submitting code changes, you can track development using just a few git commands.

First, you'll want to make a clone of the git repo on your local machine. This is similar to “svn checkout”.

git clone git://git.code.sf.net/p/rosegarden/git rosegarden-git

That will create a rosegarden-git directory where you can build and test as usual. See the README in that directory for build instructions.

cd rosegarden-git
less README

If you want to get the latest, you can pull. This is similar to “svn update”.

git pull --tags

To examine your local copy of the history, use git log.

git log

Or even nicer is the gitk GUI.

gitk &

And that should be everything you need for testing and using the latest. Questions are always welcome on the users mailing list.

Developer Workflow (Fork)

A note on learning git… With git it helps to understand a little about the internals. E.g. the fact that it is just a branching linked list of commits. Then it starts to make sense. Also playing with a small experimental repo can build confidence quickly.

Before you use git for the first time, you must tell it your name and email address.

git config --global user.name "Joe Smith" 
git config --global user.email j.smith@gmail.com

This will appear in all of your commits, so make sure it's correct.

Next, you'll need to fork the repo you want to work on. This makes a public copy that can only be modified by you. In sourceforge, click the “fork” link in the left column of the code viewer.

https://sourceforge.net/p/rosegarden/git/ci/master/tree/

It will allow you to set the home project (use the default which is your sourceforge userid), the label (this is the unique name that appears in your profile), and the mount point (the name in the URL it creates). Just go with defaults for your first fork. Usually, defaults will be fine.

The fork will take a while. It is making a copy of the entire 150+MB rosegarden repo for your personal use on the sourceforge servers. Then it is analyzing that copy which takes a minute or so.

Wait a few moments and do a refresh and the repo should appear. Now you can clone it using “ssh” protocol so you can write (push) to it. Use the command that appears in the “Read/Write SSH access” box to do your clone. It will look something like this:

git clone ssh://tedfelix@git.code.sf.net/u/tedfelix/rosegarden rosegarden-git

That will create a local “rosegarden-git” directory that you can build and test from. And since this will be connected to your remote fork, you can make changes locally and push them to the remote server as well.

From here on out we'll assume you are in your local rosegarden-git directory.

cd rosegarden-git

As a final step, you'll need to configure a remote called “upstream” so that you can stay in sync with the official Rosegarden repo.

git remote add upstream git://git.code.sf.net/p/rosegarden/git

After that you should have two remotes configured appropriately:

$ git remote -v
origin	ssh://tedfelix@git.code.sf.net/u/tedfelix/rosegarden (fetch)
origin	ssh://tedfelix@git.code.sf.net/u/tedfelix/rosegarden (push)
upstream	git://git.code.sf.net/p/rosegarden/git (fetch)
upstream	git://git.code.sf.net/p/rosegarden/git (push)

Now you are ready to make changes.

Making Changes

Before making any changes, make sure you are on the right branch with git status.

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Currently we are on the master branch. You should never commit changes to master. But at some point it will happen and fortunately it's relatively easy to fix. (See “Committing to the Wrong Branch” below.) For now let's assume we are doing things the Right Way and we are going to work in a new branch.

Let's say we want to do some work on bug #123. Before we begin we create a local bug123 branch to work in and base it on master:

$ git checkout -b bug123 master
Switched to a new branch 'bug123'

This creates the new local branch and checks it out. Use git status to make sure you are where you think you are:

$ git status
On branch bug123
nothing to commit, working tree clean

Now you can make changes and commit them to your local bug123 branch. As with svn, you can use “git status” to see what you have changed:

$ git status
On branch bug123
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   README

no changes added to commit (use "git add" and/or "git commit -a")

git diff provides all the details.

$ git diff
diff --git a/README b/README
index b17b6c4a5..f93535a00 100644
--- a/README
+++ b/README
@@ -139,7 +139,7 @@ data/appdata.  It is named rosegarden.appdata-old.xml.
 Authors and copyright
 ---------------------
 
-Rosegarden is Copyright 2000-2020 The Rosegarden Development Team
+Rosegarden is Copyright 2000-2021 The Rosegarden Development Team
 
 See http://rosegardenmusic.com/resources/authors/ for a complete list of
 developers past and present, and to learn something about the history of our

Or get a summary with “–stat”.

$ git diff --stat
 README | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

When you are ready to commit to your local git repo, use git add/rm and git commit.

$ git add .
$ git status
On branch bug123
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   README

$ git commit
[bug123 7e717ac63] Update README
 1 file changed, 1 insertion(+), 1 deletion(-)

The git book covers all of this in far more detail:

https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository

Merge Request

Once your changes are ready to be incorporated into the project, you'll want to push them from your local repo (fork) to your remote fork on sourceforge (origin). Make sure you are on the correct branch. In this case, bug123:

git checkout bug123

The first time you push a local branch to your remote fork, you will need to set the local branch's “upstream” to origin (your remote fork) and specify the name for the new remote branch:

git push -u origin bug123

Git will confirm that the push was successful and that the upstream was set:

To ssh://git.code.sf.net/p/rosegarden/git
 * [new branch]          bug123 -> bug123
Branch 'bug123' set up to track remote branch 'bug123' from 'origin'.

Git remembers the upstream and will use it the next time you push. There is no need to specify -u origin bug123 again:

git push

Now you can send a merge request to the owner of the original repo that you forked. On the sourceforge website, bring up your fork and click on the “Request Merge” link in the left column in sourceforge's code viewer. Then fill in the summary and an optional description. Source Branch for this example would be “bug123”. Target Branch would probably be “master”.

The owner of the original repo will then get the merge request and decide what to do with it.

Note that with git the term “upstream” is used for two different things. Most commonly it's used to refer to the remote branch that a local branch will push to. It's also used to refer to the remote repo that was the source of your fork.

Branching

Branching is so easy with git that it's not unusual to end up doing work on the wrong branch. Use git status frequently to confirm which branch you are on. Then switch to the right one before continuing.

Switching local branches is simply a checkout.

$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ git checkout bug123
Switched to branch 'bug123'
Your branch is up to date with 'origin/bug123'.

Check which local branch you are on with git status.

$ git status
On branch bug123
Your branch is up to date with 'origin/bug123'.

nothing to commit, working tree clean

You can list your local branches.

$ git branch -v
* bug123    7e717ac63 Update README
  master    f04c831e0 cmake: Pre-compiled header comments

And examine your remote branches.

$ git remote show origin
* remote origin
  Fetch URL: ssh://tedfelix@git.code.sf.net/p/rosegarden/git
  Push  URL: ssh://tedfelix@git.code.sf.net/p/rosegarden/git
  HEAD branch: master
  Remote branches:
    bug123 tracked
    master tracked
  Local branches configured for 'git pull':
    bug123 merges with remote bug123
    master merges with remote master
  Local refs configured for 'git push':
    bug123 pushes to bug123 (up to date)
    master pushes to master (up to date)

Resyncing master

While working with branches, don't forget to periodically fetch the latest changes to master from the upstream repo and push to resync your fork's master. First switch to master and make sure the working directory is clean and up to date:

$ git checkout master
Already on 'master'
Your branch is up to date with 'origin/master'.

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

If it isn't clean and up to date, you'll want to fix that before continuing. Otherwise a git pull will make a mess of things. Assuming master is clean and up to date you can resync your master and your fork's master with a pull from upstream and a push to origin:

git pull --tags upstream master
git push --tags origin master

Deleting a Remote Branch

To delete a branch from your remote fork on sourceforge (origin):

$ git push origin --delete bug123
remote: <Repository /git/p/rosegarden/git.git> refresh queued.
To ssh://git.code.sf.net/p/rosegarden/git
 - [deleted]             bug123

Deleting a Local Branch

To delete a local branch, first make sure you don't have it checked out. Switching to master is safe:

git checkout master

Then use git branch -d:

$ git branch -d bug123
Deleted branch bug123 (was 7e717ac63).

Depending on whether it thinks commits may be lost, git might require you to specify -D to force the delete. Make sure nothing will be lost before using -D.

Creating a Safety Branch

And finally, if you're about to go through some scary git commands on a branch, you can always drop a safety branch that you can get back to at any time.

git branch my-safety-branch1
... (lots of scary git commands like ''git reset'' and ''git branch -D'')
git checkout my-safety-branch1

Committing to the Wrong Branch

It happens to all of us at some point. This is where you can learn more about the internals of git. Git implements its change history as a branching linked list pointing into the past. As such, we can manipulate it in almost any way we want.

Let's say we accidentally committed something to master that should have been committed into a new branch.

$ git commit -am "Update README"
[master 556976f7d] Update README
 1 file changed, 1 insertion(+), 1 deletion(-)

Oops. Ok, not a problem. Let's drop the branch we wanted to create here:

git branch bug222

Listing the branches we see that master and bug222 are in the same place.

$ git branch -v
  bug222    556976f7d Update README
* master    556976f7d [ahead 1] Update README

Also note that master is ahead by one commit that shouldn't be there. So we need to move our local master back one commit. There are a couple of ways to do that. But the one that makes the most sense is to put master back where it belongs at origin/master:

$ git reset --hard origin/master
HEAD is now at f04c831e0 cmake: Pre-compiled header comments

Now check the branches:

$ git branch -v
  bug222    556976f7d Update README
* master    f04c831e0 cmake: Pre-compiled header comments

That looks better. Now we can switch to the bug222 branch where we should have been:

$ git checkout bug222
Switched to branch 'bug222'

For handling more complex situations, look into the git cherry-pick command.

Resources

github has some good documentation on forking:

https://docs.github.com/en/github/getting-started-with-github/fork-a-repo

If you want to go even deeper into git, the git book will take you there:

https://git-scm.com/book/en/v2

Definitely read it after you are done with this.

The O'Reilly Git Book is pretty good as well.