Introduction
This document is a simple guide showing the procedures necessary to develop and maintain patches for a git-based project. It is not a replacement for the Git manual and deliberately skips over other established but different git-based workflows.
Getting the source code
This section shows how to download the source code and explains the concept of a git repository.
First, we have to retrieve Qt Creator’s source code, using the git clone command:
$ git clone git://labs.trolltech.com/creator
cd creator
This creates a new directory called “creator” and downloads the source code into it. It also downloads the entire history of all files in all versions, therefore creating an identical copy – called repository – of what is stored on the server. That is why the process is called cloning. The source of the clone is remembered as the “origin”.
You can create new clones by simply copying the directory, for example onto a USB stick. The new directory will also be entirely self-contained.
Now that you have all the changes inside the repository, you can work entirely offline. Connection to the labs.trolltech.com server is only necessary when you need to fetch new source code changes.
Inspecting the source code
This section introduces the git log, show and blame commands to inspect the history of the project.
Run the log command to view recent changes:
$ git log
This command launches a pager program allowing you to scroll through the list of committed changes with the cursor and Page Up/Down keys. You can return to the shell by pressing the ‘q’ key.
The log command accepts options, such as -n to limit the number of changes. To list the last three changes run:
$ git log -n3
To limit the output of the log command, e.g., to show only changes that affect one or multiple files/directories, you can use the following options:
$ git log src/plugins/subversion/
$ git log src/app/main.cpp
$ git log qtcreator.pro src/plugin/plugins.pro
There are various ways of limiting the output of the log command, beyond the ones described here. Refer to git log’s documentation for more details, particularly in the “Commit Limiting” section.
Changes in git are identified with a unique SHA1 checksum. In the output of git log, the checksum is shown on the first line. For example:
commit 48739839e4e260a7d3024e2de406c6656e75360a
Author: Roberto Raggi <roberto.raggi@nokia.com>
Date: Fri Feb 20 14:55:28 2009 +0100
Improved qdoc support.
src/plugins/cpptools/cppdoxygen.cpp | 1413 ++++++++++++++++++++++++++++++++++-
src/plugins/cpptools/cppdoxygen.h | 349 ++++++----
2 files changed, 1602 insertions(+), 160 deletions(-)
You can inspect commits using the git show command with the commit id as argument. The following command shows the entire change above including a
diff:
$ git show 48739839e4e260a7d3024e2de406c6656e75360a
To see the last command you made (without any arguments), use:
$ git show
The git show and log commands allow to inspect the history of the project or individual files. Sometimes it is also useful to inspect source code on a line-by-line basis, for example when you would like to find out who introduced a certain snippet of code. Git provides this functionality with the blame command:
$ git blame src/plugins/cpptools/cppcodecompletion.cpp
The output of this command – shown in a pager – is split into columns. The first column shows the commit id, followed by the author and date for each line.
Git specializes in tracking the content of files, the name of a file is less important than the source code it contains. Therefore git blame can automatically detect, for example, that a function was moved from one file to another.
Making changes
The previous sections explained how to clone the repository and how to inspect the history of the project. This section finally shows how to make history,
through the recording of changes in new commits and the tracking of commits in branches.
However, first you have to register your name and e-mail address with git, to be used for commits we create. You need to run these commands only once:
$ git config user.name "Your Name"
$ git config user.email "me@example.com"
The next step is to identify on what branch of development we are on. In git branches are a very lightweight concept that allow identifying a commit by
name. Each commit has a reference to its parent commit(s), which forms the history. The git branch command, without any arguments, shows us the list of local branches as well as the branch currently checked out:
$ git branch
* master
The output shows that we have only one local branch called “master” and the “*” indicates that it is the current branch. The name “master” in git development usually describes the main line of development.
Besides your local branches git also remembers the branches in the origin repository. The “-r” option shows them, prefixed with “origin”.
$ git branch -r
origin/0.9.1-beta
origin/0.9.2-rc
origin/HEAD
origin/master
For the purpose of developing a new feature we can create a new branch with the same command:
$ git branch my-feature origin/master
The “my-feature” branch is based on the origin’s “master” branch, and it is now visible in the list of branches:
$ git branch
* master
my-feature
The git checkout command allows changing the current branch:
$ git checkout my-feature
Switched to branch "my-feature"
$ git branch
master
* my-feature
This will also update the files in your working directory to match the latest commit in the new current branch. New commits will be recorded in “my-feature” instead of the previous “master” branch.
You can have as many local branches as you like, they are very cheap. Each branch uses only a few bytes of extra disk space. Please see the documentation of the git branch command for instructions on how to delete branches.
Now we can go ahead and start making changes:
$ edit src/app/main.cpp
The diff command shows us what we have changed:
$ git diff
diff --git a/src/app/main.cpp b/src/app/main.cpp
index c10c476..e05297f 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -197,6 +197,8 @@ static inline QStringList getPluginPaths()
return rc;
}
+// This is the main function, that serves as entry point
+// into Qt Creator.
int main(int argc, char **argv)
{
#ifdef Q_OS_DARWIN
The status command gives an overview of what “git commit” would do:
$ git status
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: src/app/main.cpp
#
no changes added to commit (use "git add" and/or "git commit -a")
Following the recommendation in the output we mark main.cpp as a file to be included in the next commit:
$ git add src/app/main.cpp
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: src/app/main.cpp
#
# Untracked files not listed (use -u option to show untracked files)
And finally we create a new commit:
$ git commit -m "Added a tiny bit of documentation"
[my-feature c1e3713] Added a tiny bit of documentation
1 files changed, 2 insertions(+), 0 deletions(-)
Omitting the -m option, which allows specifying the commit message on the command line directly, makes the commit command open a text editor.
Marking files to be included in commits means adding them to git’s staging area. The staging area is a powerful concept, making it easy to work on
multiple files simultaenously while still creating small incremental commits.
Common operations and fixing mistakes
This section gives recipes for fixing common mistakes and explains common operations such as reviewing your changes before committing using the diff
command.
You can undo changes to a file before it is committed with the checkout command:
$ git checkout HEAD -- src/app/main.cpp
If you have accidentally marked a file for the next commit you can reset it like this:
$ git reset HEAD -- src/app/main.cpp
This will exclude the file from the next commit while preserving your modifications, leaving the file in your working directory unchanged.
After changing a file the git diff command will show the lines you have modified. The difference shown is calculated from the file in your working
directory and the file when it was marked for inclusion in the next commit – added to the staging area using git add.
If you want to show the difference between the file in the staging area and the last commit you have to pass an option to the diff command:
$ git diff --cached
he diff command optionally takes directories and files as argument, to limit the output to modifications to the specified paths.
Files are renamed in git by simply renaming them in your working directory using a command/tool of your choice. Only after you've renamed a file you have to tell git:
[ rename oldfile.cpp to newfile.cpp using a graphical file manager ]
$ git rm oldfile.cpp
$ git add newfile.cpp
Alternatively you can use the convenience mv command:
$ git mv oldfile.cpp newfile.cpp
One of git’s strengths is that it does not care how exactly you change your files. It is optimized to find out what exactly changed after the fact. For
example when copying an copying a file in your source code it is enough to simply run “git add” with the new file. Git automatically finds out where the
file was copied from.
Sending and updating your changes
After studying the previous chapters you should be able to develop small changes by creating commits in your local branches. This chapter guides you
through the steps of combining your changes with the latest changes from the upstream repository and explains how to create separate patch files for
submission into the project.
While developing code in your local clone of the project, the original repository evolves and sees new changes. As a first step we update our mirror of the commits in the original repository using the fetch command:
$ git fetch
remote: Counting objects: 3013, done.
remote: Compressing objects: 100% (395/395), done.
remote: Total 1730 (delta 1455), reused 1582 (delta 1332)
Receiving objects: 100% (1730/1730), 1.13 MiB | 392 KiB/s, done.
Resolving deltas: 100% (1455/1455), completed with 892 local objects.
From git://labs.trolltech.com/creator
0220b45..f3cbcb1 master -> origin/master
The output indicates that the “master” branch in the original labs.trolltech.com repository has been updated with new commits and that these commits are now available in the locally mirrored origin/master branch.
You can inspect the new changes using the log or show commands:
$ git log -p origin/master
The optional -p arguments makes the log command include the diffs of the individual commits in the output.
To combine the new changes with our own local commits we use a technique called rebasing:
$ git checkout my-feature
$ git rebase origin/master
After making “my-feature” the current branch git rebase will first re-initialize the branch to be identical to origin/master, which includes the new commits. Then it will apply each of our own commits one by one, basing them on top of the newly initialized branch.
If you decide that the work in your “my-feature” branch is complete then the next step is to prepare your commits for submission upstream. This is done by using git to create patch files for each of your commits, using the format-patch command:
$ git format-patch origin/master
0001-Doc-fixes.patch
0002-Bugfix-in-.pro-file.patch
The command creates numbered patch files and outputs their names. The patch files contain all the information necessary to re-create commits. They should be sent via email to the project mailing list, where they can be reviewed and discussed.
The maintaining developer may decide to include the patch using the apply-mailbox command:
$ git am 0001-Doc-fixes.patch
This will create a new commit in git which is identical to your local commit.
Conclusion
We hope that these guidelines help you to become familiar with the use of git for contributing and that we have raised the interest to learn more. The official Git documentation web page is a very good continuation point for this:

