git is a general purpose version control system that supports numerous workflows. This document discusses two key ways to use git.
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.
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.
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
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 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)
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
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
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
.
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
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.
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.