Git Introduction: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(Add "cleanup" tag)
(fixed markup, etc.)
Line 1: Line 1:
{{Cleanup | reason=Auto-imported from ExpressionEngine.}}
h1. Developing and maintaining patches on top of Qt with Git
This document is a simple guide showing the procedures necessary to develop and maintain patches on top of Qt. It is not a replacement for the Git manual.
This document is a simple guide showing the procedures necessary to develop and maintain patches on top of Qt. It is not a replacement for the Git manual.


== Setting up for Git and Gerrit ==
== Setting up for Git and Gerrit ==


[[Setting-up-Gerrit]] explains how to configure git, and how to clone Qt repositories.
[[Setting up Gerrit]] explains how to configure git, and how to clone Qt repositories.


== Getting the Qt source code ==
== Git Repositories ==


This section shows how to download the source code and explains the concept of a Git repository.
This section explains the concept of a Git repository.


<code>
<pre>
$ git clone git://gitorious.org/qt/qt.git
$ git clone git://code.qt.io/qt/qt.git
cd qt
cd qt
</code>
</pre>


This creates a new directory called “qt” 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”.
This creates a new directory called “qt” 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”.
Line 30: Line 26:
Run the log command to view recent changes:
Run the log command to view recent changes:


<code>
<pre>
$ git log
$ git log
</code>
</pre>


This command launches a pager program allowing you to scroll through the list of committed changes with the cursor and Page Up/Down keys. To return to the shell press the 'q' key.
This command launches a pager program allowing you to scroll through the list of committed changes with the cursor and Page Up/Down keys. To return to the shell press the 'q' key.
Line 38: Line 34:
The log command accepts options, such as -n to limit the number of changes. For example to list the last three changes run:
The log command accepts options, such as -n to limit the number of changes. For example to list the last three changes run:


<code>
<pre>
$ git log -n3
$ git log -n3
</code>
</pre>


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:
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:


<code>
<pre>
$ git log src/corelib/kernel
$ git log src/corelib/kernel
$ git log src/gui/kernel/qwidget.cpp
$ git log src/gui/kernel/qwidget.cpp
$ git log examples/examples.pro examples/painting/basicdrawing/main.cpp
$ git log examples/examples.pro examples/painting/basicdrawing/main.cpp
</code>
</pre>


There are various ways of limiting the output of the log command, beyond the ones described here. Refer to "git log's documentation":http://www.kernel.org/pub/software/scm/git/docs/git-log.html or more details, particularly the "Commit Limiting" section.
There are various ways of limiting the output of the log command, beyond the ones described here. Refer to "git log's documentation":http://www.kernel.org/pub/software/scm/git/docs/git-log.html or more details, particularly the "Commit Limiting" section.
Line 54: Line 50:
Changes in Git are identified with a unique SHA1 checksum. The checksum is on the first line of the git log output. For example:
Changes in Git are identified with a unique SHA1 checksum. The checksum is on the first line of the git log output. For example:


<code>
<pre>
commit 211bea9838bcc2acd7f54b65468fe1be2d81b1e0
commit 211bea9838bcc2acd7f54b65468fe1be2d81b1e0
Author: Denis Dzyubenko <denis.dzyubenko@nokia.com>
Author: Denis Dzyubenko <denis.dzyubenko@nokia.com>
Date: Fri Apr 24 14:18:17 2009 ''0200
Date: Fri Apr 24 14:18:17 2009 +0200


Re-send network request properly when the socket is in Closing state.
Re-send network request properly when the socket is in Closing state.


This fixes the "QAbstractSocket::connectToHost() called when already
This fixes the "QAbstractSocket::connectToHost() called when already
connecting/connected to <hostname>". The issue was that we were trying
connecting/connected to <hostname>". The issue was that we were trying
to call connect on a socket that was in a Closing state. We have to
to call connect on a socket that was in a Closing state. We have to
wait for the disconnected signal before we try to connect again.
wait for the disconnected signal before we try to connect again.


Reviewed-by: Prasanth
Reviewed-by: Prasanth
</code>
</pre>


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:
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:


<code>
<pre>
$ git show 211bea9838bcc2acd7f54b65468fe1be2d81b1e0
$ git show 211bea9838bcc2acd7f54b65468fe1be2d81b1e0
</code>
</pre>


To see the last commit you made use show without any arguments:
To see the last commit you made use show without any arguments:


<code>
<pre>
$ git show
$ git show
</code>
</pre>


To inspect a whole series of commits, use:
To inspect a whole series of commits, use:


<code>
<pre>
$ git log -p
$ git log -p
</code>
</pre>


The git show and log commands allow you 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:
The git show and log commands allow you 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:


<code>
<pre>
$ git blame src/gui/kernel/qwidget.cpp
$ git blame src/gui/kernel/qwidget.cpp
</code>
</pre>


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.
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.
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.
Line 105: Line 101:
The first step is to identify on what branch of development we are working. In Git, branches are a very lightweight concept that allows identifying commits by name. Each commit has a reference to its parent commit(s), which forms the history. The Git branch command, without any arguments, displays the list of local branches as well as the branch currently checked out:
The first step is to identify on what branch of development we are working. In Git, branches are a very lightweight concept that allows identifying commits by name. Each commit has a reference to its parent commit(s), which forms the history. The Git branch command, without any arguments, displays the list of local branches as well as the branch currently checked out:


<code>
<pre>
$ git branch
$ git branch
* master
* master
</code>
</pre>


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.
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":
Besides your local branches Git also remembers the branches in the origin repository. The "-r" option shows them, prefixed with "origin":


<code>
<pre>
$ git branch -r
$ git branch -r
origin/4.5
origin/4.5
origin/HEAD-> origin/master
origin/HEAD-> origin/master
origin/master
origin/master
</code>
</pre>


For the purpose of developing a new feature we can create a new branch with the same command:
For the purpose of developing a new feature we can create a new branch with the same command:


<code>
<pre>
$ git branch my-feature origin/master
$ git branch my-feature origin/master
</code>
</pre>


The "my-feature" branch is based on the origin's "master" branch, now visible in the list of branches:
The "my-feature" branch is based on the origin's "master" branch, now visible in the list of branches:


<code>
<pre>
$ git branch
$ git branch
''' master
* master
my-feature
  my-feature
</code>
</pre>


The git checkout command can also change the current branch:
The git checkout command can also change the current branch:


<code>
<pre>
$ git checkout my-feature
$ git checkout my-feature
Switched to branch "my-feature"
Switched to branch "my-feature"
$ git branch
$ git branch
master
  master
* my-feature
* my-feature
</code>
</pre>


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.
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.
Line 153: Line 149:
Now we can go ahead and start making changes:
Now we can go ahead and start making changes:


<code>
<pre>
$ edit src/corelib/tools/qstring.cpp
$ edit src/corelib/tools/qstring.cpp
</code>
</pre>


The diff command shows us what we have changed:
The diff command shows us what we have changed:


<code>
<code lang="diff">
$ git diff
$ git diff
diff —git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 375d672..d7345e6 100644
index 375d672..d7345e6 100644
a/src/corelib/tools/qstring.cpp
--- a/src/corelib/tools/qstring.cpp
'' b/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
&amp;#x40;&amp;#x40; –2855,6 ''2855,20 &amp;#x40;&amp;#x40; int QString::count(const QRegExp&amp;amp; rx) const
@@ –2855,6 +2855,20 @@ int QString::count(const QRegExp&amp;amp; rx) const
  Same as size().
  Same as size().
  */
  */


''/*!
+/*!
+ 4.6
+ 4.6
+
+
+ Returns this string in reverse order.
+ Returns this string in reverse order.
''*/
+ */
''QString QString::reversed() const
+QString QString::reversed() const
''{
+{
+ QString result;
+   QString result;
+ result.resize(d->size);
+   result.resize(d->size);
+ for (int i = 0; i < d->size; +''i)
+   for (int i = 0; i < d->size; ++i)
'' result[i] = d->data[d->size - 1 - i];
+    result[i] = d->data[d->size - 1 - i];
+ return result;
+   return result;
''}
+}
''
+


  /*!
  /*!
  QString::SectionFlag
  QString::SectionFlag
diff —git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 1493dce..077bda9 100644
index 1493dce..077bda9 100644
a/src/corelib/tools/qstring.h
--- a/src/corelib/tools/qstring.h
'' b/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
&amp;#x40;&amp;#x40; –195,6 ''195,8 &amp;#x40;&amp;#x40; public:
@@ –195,6 +195,8 @@ public:
  int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
  int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
  int count(const QString &amp;s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
  int count(const QString &amp;s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;


'' QString reversed() const;
+QString reversed() const;
+
+
  #ifndef QT_NO_REGEXP
  #ifndef QT_NO_REGEXP
  int indexOf(const QRegExp &amp;, int from = 0) const;
  int indexOf(const QRegExp &amp;, int from = 0) const;
Line 203: Line 199:
The status command gives an overview of what "git commit" would do:
The status command gives an overview of what "git commit" would do:


<code>
<pre>
$ git status
$ git status
# On branch master
# On branch master
# Changed but not updated:
# Changed but not updated:
# (use "git add <file>…" to update what will be committed)
# (use "git add <file>…" to update what will be committed)
# (use "git checkout <file>…" to discard changes in working directory)
# (use "git checkout -- <file>…" to discard changes in working directory)
#
#
# modified: src/corelib/tools/qstring.cpp
# modified: src/corelib/tools/qstring.cpp
# modified: src/corelib/tools/qstring.h
# modified: src/corelib/tools/qstring.h
#
#
no changes added to commit (use "git add" and/or "git commit -a")
no changes added to commit (use "git add" and/or "git commit -a")
</code>
</pre>


Following the recommendation in the output we mark qstring.cpp and .h as files to be included in the next commit:
Following the recommendation in the output we mark qstring.cpp and .h as files to be included in the next commit:


<code>
<pre>
$ git add src/corelib/tools/qstring.cpp src/corelib/tools/qstring.h
$ git add src/corelib/tools/qstring.cpp src/corelib/tools/qstring.h
$ git status
$ git status
# On branch master
# On branch master
# Changes to be committed:
# Changes to be committed:
# (use "git reset HEAD <file>…" to unstage)
# (use "git reset HEAD <file>…" to unstage)
#
#
# modified: src/corelib/tools/qstring.cpp
# modified: src/corelib/tools/qstring.cpp
# modified: src/corelib/tools/qstring.h
# modified: src/corelib/tools/qstring.h
#
#
# Untracked files not listed (use -u option to show untracked files)
# Untracked files not listed (use -u option to show untracked files)
</code>
</pre>


And finally we create a new commit:
And finally we create a new commit:


<code>
<pre>
$ git commit -m "Add a new reversed() function to QString"
$ git commit -m "Add a new reversed() function to QString"
[my-feature c8d9c54] Add a new reversed() function to QString
[my-feature c8d9c54] Add a new reversed() function to QString
</code>
</pre>


Normally Git will open a new text editor if you omit the -m parameter.
Normally Git will open a new text editor if you omit the -m parameter.
Line 242: Line 238:
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.
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.


Use the <code>git gui</code> command for a comfortable way to create highly selective commits.
Use the <tt>git gui</tt> command for a comfortable way to create highly selective commits.


== Common operations and fixing mistakes ==
== Common operations and fixing mistakes ==
Line 250: Line 246:
You can undo changes to a file before it is committed with the checkout command:
You can undo changes to a file before it is committed with the checkout command:


<code>
<pre>
$ git checkout HEAD src/corelib/tools/qstring.cpp
$ git checkout HEAD -- src/corelib/tools/qstring.cpp
</code>
</pre>


If you have accidentially marked a file for the next commit you can reset it like this:
If you have accidentially marked a file for the next commit you can reset it like this:


<code>
<pre>
$ git reset HEAD src/corelib/tools/qstring.cpp
$ git reset HEAD -- src/corelib/tools/qstring.cpp
</code>
</pre>


This will exclude the file from the next commit and leave it in your working directory unchanged with your modifications intact.
This will exclude the file from the next commit and leave it in your working directory unchanged with your modifications intact.
Line 266: Line 262:
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:
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:


<code>
<pre>
$ git diff —staged # —cached in old git versions
$ git diff --staged # --cached in old git versions
</code>
</pre>


The diff command optionally takes directories and files as argument, to limit the output.
The diff command optionally takes directories and files as argument, to limit the output.
Line 274: Line 270:
Files are renamed in Git by renaming them in your working directory using a command/tool of your choice. Once you've renamed a file you have to tell Git:
Files are renamed in Git by renaming them in your working directory using a command/tool of your choice. Once you've renamed a file you have to tell Git:


<code>
<pre>
[ rename oldfile.cpp to newfile.cpp using a graphical file manager ]
[ rename oldfile.cpp to newfile.cpp using a graphical file manager ]
$ git rm oldfile.cpp
$ git rm oldfile.cpp
$ git add newfile.cpp
$ git add newfile.cpp
</code>
</pre>


Alternatively you can use the convenience mv command:
Alternatively you can use the convenience mv command:


<code>
<pre>
$ git mv oldfile.cpp newfile.cpp
$ git mv oldfile.cpp newfile.cpp
</code>
</pre>


One of Git's strengths is that it does not care how exactly you change your files. It is optimized to find out what changed after the fact. For example when 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.
One of Git's strengths is that it does not care how exactly you change your files. It is optimized to find out what changed after the fact. For example when 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.
Line 296: Line 292:
While developing code in your local clone of the project, the original repository evolves and sees new changes. First we update our mirror of the commits in the original repository using the fetch command:
While developing code in your local clone of the project, the original repository evolves and sees new changes. First we update our mirror of the commits in the original repository using the fetch command:


<code>
<pre>
$ git fetch
$ git fetch
remote: Counting objects: 3013, done.
remote: Counting objects: 3013, done.
remote: Compressing objects: 100% (395/395), done.
remote: Compressing objects: 100% (395/395), done.
remote: Total 1730 (delta 1455), reused 1582 (delta 1332)
remote: Total 1730 (delta 1455), reused 1582 (delta 1332)
Receiving objects: 100% (1730/1730), 1.13 MiB | 392 KiB/s, done.
Receiving objects: 100% (1730/1730), 1.13 MiB | 392 KiB/s, done.
Resolving deltas: 100% (1455/1455), completed with 892 local objects.
Resolving deltas: 100% (1455/1455), completed with 892 local objects.
From git://gitorious.org/qt/qt.git
From git://gitorious.org/qt/qt.git
be7384d..822114e master-> origin/master
be7384d..822114e master -> origin/master
</code>
</pre>


The output indicates that the "master" branch in the original gitorious.org repository has been updated with new commits and these commits are now available in the locally mirrored origin/master branch.
The output indicates that the "master" branch in the original gitorious.org repository has been updated with new commits and these commits are now available in the locally mirrored origin/master branch.
Line 311: Line 307:
You can inspect the new changes using the log or show commands:
You can inspect the new changes using the log or show commands:


<code>
<pre>
$ git log -p origin/master
$ git log -p origin/master
</code>
</pre>


The log command will include the diffs of the individual commits if you specify the -p argument.
The log command will include the diffs of the individual commits if you specify the -p argument.
Line 321: Line 317:
To combine the new changes with our own local commits we use a technique called rebasing:
To combine the new changes with our own local commits we use a technique called rebasing:


<code>
<pre>
$ git checkout my-feature
$ git checkout my-feature
$ git rebase origin/master
$ git rebase origin/master
</code>
</pre>


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 your commits, basing them on top of the newly initialized branch.
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 your commits, basing them on top of the newly initialized branch.
Line 332: Line 328:
When you decide that the work in your "my-feature" branch is complete then the next step is to make your changes available for upstream inclusion.
When you decide that the work in your "my-feature" branch is complete then the next step is to make your changes available for upstream inclusion.


This is described in the [[Gerrit-Introduction]].
This is described in the [[Gerrit Introduction]].


== Conclusion ==
== Conclusion ==

Revision as of 18:07, 3 March 2015

This document is a simple guide showing the procedures necessary to develop and maintain patches on top of Qt. It is not a replacement for the Git manual.

Setting up for Git and Gerrit

Setting up Gerrit explains how to configure git, and how to clone Qt repositories.

Git Repositories

This section explains the concept of a Git repository.

$ git clone git://code.qt.io/qt/qt.git
cd qt

This creates a new directory called “qt” 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 simply by copying the directory, for example onto a USB stick. The new directory will be self-contained, too.

Now that you have all the changes inside the repository, you can work 100% offline. An internet connection is necessary only when you need to fetch new source code changes or push upstream.

Inspecting the source code

This section introduces the Git log, show and blame commands to find out 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. To return to the shell press the 'q' key.

The log command accepts options, such as -n to limit the number of changes. For example 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/corelib/kernel
$ git log src/gui/kernel/qwidget.cpp
$ git log examples/examples.pro examples/painting/basicdrawing/main.cpp

There are various ways of limiting the output of the log command, beyond the ones described here. Refer to "git log's documentation":http://www.kernel.org/pub/software/scm/git/docs/git-log.html or more details, particularly the "Commit Limiting" section.

Changes in Git are identified with a unique SHA1 checksum. The checksum is on the first line of the git log output. For example:

commit 211bea9838bcc2acd7f54b65468fe1be2d81b1e0
Author: Denis Dzyubenko <denis.dzyubenko@nokia.com>
Date: Fri Apr 24 14:18:17 2009 +0200

Re-send network request properly when the socket is in Closing state.

This fixes the "QAbstractSocket::connectToHost() called when already
connecting/connected to <hostname>". The issue was that we were trying
to call connect on a socket that was in a Closing state. We have to
wait for the disconnected signal before we try to connect again.

Reviewed-by: Prasanth

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 211bea9838bcc2acd7f54b65468fe1be2d81b1e0

To see the last commit you made use show without any arguments:

$ git show

To inspect a whole series of commits, use:

$ git log -p

The git show and log commands allow you 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/gui/kernel/qwidget.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

Setting up for changes

The previous sections explained how to clone the repository and how to find out the history of the project. This section finally shows how to create history, through the recording of changes in new commits and the tracking of commits in branches.

The first step is to identify on what branch of development we are working. In Git, branches are a very lightweight concept that allows identifying commits by name. Each commit has a reference to its parent commit(s), which forms the history. The Git branch command, without any arguments, displays 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/4.5
origin/HEAD-> origin/master
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, now visible in the list of branches:

$ git branch
* master
  my-feature

The git checkout command can also change 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 few bytes of disk space. Please see the "documentation of the git branch command":http://git-scm.com/docs/git-branch for instructions on how to delete branches.

Actually making the changes

Now we can go ahead and start making changes:

$ edit src/corelib/tools/qstring.cpp

The diff command shows us what we have changed:

$ git diff
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 375d672..d7345e6 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ –2855,6 +2855,20 @@ int QString::count(const QRegExp&amp;amp; rx) const
 Same as size().
 */

+/*!
+ 4.6
+
+ Returns this string in reverse order.
+ */
+QString QString::reversed() const
+{
+    QString result;
+    result.resize(d->size);
+    for (int i = 0; i < d->size; ++i)
+    result[i] = d->data[d->size - 1 - i];
+    return result;
+}
+

 /*!
 QString::SectionFlag
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 1493dce..077bda9 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ –195,6 +195,8 @@ public:
 int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
 int count(const QString &amp;s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;

+QString reversed() const;
+
 #ifndef QT_NO_REGEXP
 int indexOf(const QRegExp &amp;, int from = 0) const;
 int lastIndexOf(const QRegExp &amp;, int from = –1) const;

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/corelib/tools/qstring.cpp
# modified: src/corelib/tools/qstring.h
#
no changes added to commit (use "git add" and/or "git commit -a")

Following the recommendation in the output we mark qstring.cpp and .h as files to be included in the next commit:

$ git add src/corelib/tools/qstring.cpp src/corelib/tools/qstring.h
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>…" to unstage)
#
# modified: src/corelib/tools/qstring.cpp
# modified: src/corelib/tools/qstring.h
#
# Untracked files not listed (use -u option to show untracked files)

And finally we create a new commit:

$ git commit -m "Add a new reversed() function to QString"
[my-feature c8d9c54] Add a new reversed() function to QString

Normally Git will open a new text editor if you omit the -m parameter.

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.

Use the git gui command for a comfortable way to create highly selective 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/corelib/tools/qstring.cpp

If you have accidentially marked a file for the next commit you can reset it like this:

$ git reset HEAD -- src/corelib/tools/qstring.cpp

This will exclude the file from the next commit and leave it in your working directory unchanged with your modifications intact.

After changing a file the git diff command shows the lines you have modified. The difference is calculated from the file in your working directory and the file when it was 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 --staged # --cached in old git versions

The diff command optionally takes directories and files as argument, to limit the output.

Files are renamed in Git by renaming them in your working directory using a command/tool of your choice. Once 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 changed after the fact. For example when 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.

Obtaining updates

While developing code in your local clone of the project, the original repository evolves and sees new changes. First 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://gitorious.org/qt/qt.git
be7384d..822114e master -> origin/master

The output indicates that the "master" branch in the original gitorious.org repository has been updated with new commits and 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 log command will include the diffs of the individual commits if you specify the -p argument.

Updating your branch with the downloaded, new changes

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 your commits, basing them on top of the newly initialized branch.

Sending your feature for review

When you decide that the work in your "my-feature" branch is complete then the next step is to make your changes available for upstream inclusion.

This is described in the Gerrit Introduction.

Conclusion

We hope that this introductions helps you familiarize yourself with the use of Git. The official "Git documentation web page":http://git-scm.com/documentation is a very good continuation point.