Development/Git/Simple Workflow: Difference between revisions

From KDE TechBase
(→‎Clone your repository: projects.kde.org > quickgit)
 
(31 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== Simple KDE Git Workflow ==
DANGER WILL ROBINSON!!!  THIS IS AN INCOMPLETE DRAFT!!!


This Git Workflow is designed to be followed by a new Git user who needs a simple workflow for bug fixes and new features in a manner similar to the old SVN workflow.
= Simple Workflow =


Note that each module may choose to adopt a more complex workflow and you should check with your modules maintainers if this is the case.
This workflow is designed to be as close as possible to the KDE SVN Workflow.  It is only recommended to be used for the first week or two of using Git with KDE while you become familiar with the basic Git commands.  Once comfortable with the basic commands you should then move on to the [[Development/Git/Feature_Branch_Workflow|Feature Branch Workflow]].


The worked examples given will be for an imaginary app called KFoo in a git.kde.org repository called 'kfoo'.
In particular this workflow will not use git branches, merging or any remote features, all feature development work will be in the local master branch (the Git name for trunk).
 
More detailed information can be found on the main [[Development/Git|KDE Git page]], in particular the [[Development/Git#Git_for_SVN_Users|Git for Subversion Users]] section. More details on the various commands can be found on the [[Development/Git/Recipes|KDE Git Recipes]] page.


== Set-up ==
== Set-up ==
Line 13: Line 15:
=== Configure Git ===
=== Configure Git ===


Follow the [[Development/Git/Configuration|KDE Git Configuration]] page.
Follow all the instructions on the [[Development/Git/Configuration|KDE Git Configuration]] page, the instructions given below assume you are using the standard configuration.


=== Clone your repository ===
=== Clone your repository ===


You need to copy your repository from git.kde.org into your local KDE source directory.  In Git this process is called cloning.
You need to copy your central code repository from git.kde.org into your local KDE source directory.  In Git this process is called cloning.


To clone your project repository:
To clone your project repository:
Line 23: Line 25:
  cd your/source/dir
  cd your/source/dir
  git clone kde:<project>
  git clone kde:<project>
cd <project>


In our KFoo example:
For example to clone kdelibs:


  git clone kde:kfoo
  git clone kde:kdelibs
cd kdelibs


See the [[Getting_Started/Build/Environment#Source_Path]] page for advice on structuring your source directory.
See the [[Getting_Started/Build/Environment#Source_Path|KDE Build Environment]] page for advice on structuring your source directory.


If you have a slow internet connection then you may prefer to [[Getting_Started/Sources/Snapshots|download a snapshot tarball]] to bootstrap your clone.  You can copy the required command from the projects.kde.org Repository page for your project, but it will be of the form:
If you have a slow or intermittent internet connection then you may prefer to [[Getting_Started/Sources/Snapshots|download a snapshot tarball]] to bootstrap your clone.  You can copy the required command from the [https://quickgit.kde.org quickgit.kde.org] Repository page for your project, but it will be of the form:


  wget -c http://anongit.kde.org/<project>/<project>-latest.tar.gz
  wget -c http://anongit.kde.org/<project>/<project>-latest.tar.gz


== Basic Actions ==
== Local Feature Development ==
 
This section documents the basic workflow for developing a new feature for the master unstable branch (aka trunk in subversion).  You will first make local code changes and commit them in your local repository before pushing them to the central code repository.
 
=== Making Local Changes and Commits ===
 
Changing and building code itself is no different from when using subversion, but how changed files are managed and committed is very different, as are the names and commands used.  There are two key differences:
* Locally modified files can have different states that determine whether they get committed or not.
* Committing code is only local, it does not push your changes to the central repository which requires an extra step.
 
Files in a git repository can be in various states:
* Untracked: Files in your local repository directory that Git is not tracking changes to and are not in the central repository.
* Tracked: Files that git tracks changes to.
* Unstaged: Tracked files that have had modifications to them but have not yet been staged or committed.
* Staged: Tracked files that have had modifications made to them and have been marked to be included in the next commit
* Committed: Files that git is tracking and that have been included in a local commit that may or may not be included in the central repository.
 
Note that different versions of a file can be in the Untracked and Tracked states at the same time.
 
This difference between staged and unstaged changes allows you to choose what changes you want in each commit.
 
To see what the current status of your local repository is:
 
  git status


This section documents basic actions that are performed within your workflow.
This will show you the status as follows;


See also the [[Development/Git/Recipes|KDE Git Recipes]] page.
  # On branch master
  # Your branch is ahead of 'origin/master' by 1 commit.
  #
  # Changes to be committed:
  #  (use "git reset HEAD <file>..." to unstage)
  #
  #      modified:  src/kstagedfile.h
  #
  # 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/kchangedfile.h
  #
  # Untracked files:
  #  (use "git add <file>..." to include in what will be committed)
  #
  #      src/kuntrackedfile.txt


=== Create a Work Branch ===
To add a changed file to the staging area, or to add a new file to be tracked by the repository:


By default when you first create a repository clone there is only a single local branch called 'master'.  It is not good practice to do development in master, it is better kept clean for reference.  Instead all work should be performed in a new local branch, even bug fixes.
  git add <filename>


To see what local branches you have:
You can also partially add the contents of a file to the staging area, so that it is easier to commit sets of related changes;


git branch
  git add -p <filename>


To see all local and remote branches:
To delete a file from the repository and add the deletion to the staging area:


git branch -a
  git rm <filename>


To create a new local branch:
To reset a staged file to be unstaged but without losing your changes:


git branch <new-branch>
  git reset HEAD <filename>
git checkout <new-branch>


This will create a new branch based on whatever local branch you were already in, i.e. that includes all the history of the original branch, which can be useful in building a hierarchy of dependent changes.
To reset an unstaged file to the currently committed version and irretrievably throw away your changes:


You may prefer to base your new branch on a remote branch such as the master branch of the central repository so you can integrate any new development.  This is called 'tracking' and is recommended for most branches:
  git checkout <filename>


  git branch --track <local-branch> <remote-branch>
The git commit command differs from the svn commit command in only creating a commit in your local clone of the repository, it does not merge the changes into the central repository.  This allows you to queue up a series of small changes before merging them into the central repository.  This local commit history can [[Development/Git/Recipes#Interactive_Rebasing|also be modified]] before you finally do push the changes.
 
The git commit command adds all files in the staged state into a new commit:
 
  git commit
 
If you have only changed tracked files then you can automatically add all tracked files that have been changed into staging and commit all the staged files in one command:
 
  git commit -a
 
=== Seeing What You Changed ===
 
To see a list of what files have been changed but not yet committed:
 
git status
 
To see what code changes have been made but not yet staged:
 
git diff
git diff <filename>
 
To see what code changes have been staged but not committed:
 
git diff --staged
  git diff --staged <filename>
 
To see all the commits made:
 
git log
 
To see what changes were made in a commit:
 
git show <sha5>


For our KFoo example:
The Git diff, log and show commands have many options for changing what is shown.  In particular diff can show the difference in a file between any two commits.


git branch --track new-bar-feature origin/master
=== Pushing Your Changes To The Central Repository ===


=== Commit Your Changes ===
When you are ready to push all your local commits to the central repository, you first need to update to the latest version of the master code in the central repository:


=== Push Your Changes ===
  git pull --rebase


== Local Feature Development ==
This will update the underlying master code and apply your commits on the top of the latest version of the central repository, this is known as a rebase.  Normally the rebase should apply cleanly, but sometimes there will be a conflict which you will need to resolve before you can complete applying your commits.  There will be instructions given by git on how to complete the commit if required [TODO: get a copy of the output text].


This example workflow is for locally working on new features in unstable branch and pushing them to the central repository.
Note that you cannot rebase if you have uncommitted changes.  If you need to rebase but have changes that you don't want to commit, then you will need to [[Development/Git/Recipes#Stashing_Changes|stash the changes]].


This workflow is only recommended for small features or where you are the only developer on a project.
Depending on how much the underlying master code has changed you may want to rebuild and test the code after doing the rebase, before doing a final rebase.  It is recommended to do regular rebase's between commits to keep the possibility of conflicts to a minimum.


== Remote Feature Development ==
Once your local commits have been cleanly reapplied you can push your changes to the central repository:


This example workflow is for working on new features in a feature branch hosted on the central repository.
  git push origin master:master


This workflow is recommended for larger features or where there are many developers on a project.
Git will report if the push was successful or explain why it failed.


== Local Bug Fixing ==
== Local Bug Fixing ==


This example workflow is for locally fixing bugs in both the stable and unstable branches and pushing them to the central repository.
If your bug fix is only for unstable master then no special actions are required, just follow the same steps as the feature development workflow above.
 
If your bug fix is for a stable branch then this cannot be done without using git branches.  The steps required will be given below but not explained in any detail.  If possible it is recommended you wait until you are familiar with using the [[Development/Git/Feature_Branch_Workflow|Feature Branch Workflow]].
 
The steps detailed below are very inefficient as they use the same build tree and environment for unstable and stable which may cause a lot of rebuilding.  A more efficient method is detailed in the [[Development/Git/Feature_Branch_Workflow#Local_Bug_Fixing|Feature Branch Workflow]].
 
First, find out the name of the stable branch you want to bug fix:
 
git branch -r
 
This will list all the branches on the central repository, for example kdelibs includes the following branches:
 
  origin/HEAD -> origin/master
  origin/KDE/4.5
  origin/KDE/4.6
  origin/kdecore/klocale-win
  origin/kdeui/kdatetimeedit
  origin/master
 
Here origin/KDE/4.6 is the 4.6 release of kdelibs which we will use for this example.
 
Next, create a local branch pointing to the stable release branch you want to bug fix:


In Git, stable branches are just regular branches that have special meaning to a project and a possibly a special naming scheme to distinguish them. For example, the KFoo app may have the following branches on the central repository:
  git branch --track <local-branch> <remote-branch>
git checkout <local-branch>


origin/master
For example, to create a local kdelibs 4.6 stable branch:
origin/feature/hot-new-stuff
origin/feature/cool-newer-stuff
origin/release/1.0
origin/release/1.1
origin/release/2.0


Making bug fixes to stable branches is thus fundamentally the same as working on a feature branch, but with the added step of needing to push the bug fix to both the stable and unstable branch in the central repository.
git branch --track KDE/4.6 origin/KDE/4.6
git checkout KDE/4.6


Two workflow's are described here, a basic workflow for small apps or where bug-fixes are infrequent, and an advanced workflow for larger apps or more frequent bug-fixes.
If you have previously created the stable branch and want to do a new bug fix, then simply check it out again and update it:


=== Basic Bug Fix Workflow ===
git checkout <local-branch>
git pull --rebase


To make bug fixes on the 2.0 release you could simply checkout a local copy of the origin/release/2.0 branch and make you bug fixes there:
Now make your required changes to the code, build and test. Once done commit the code changes to your local repository, remembering to include the BUG: and FIXED-IN: [http://community.kde.org/Sysadmin/GitKdeOrgManual#Commit_hook_keywords keywords in the commit message].  


git branch --track bug-fix-2.0 origin/release/2.0
git checkout bug-fix-2.0
<make changes, build, test>
  git commit -a
  git commit -a
  git push origin bug-fix-2.0:release/2.0
 
  git branch --track bug-fix-master origin/master
Make a note of the sha5 of the commit as you will need it later to copy the commit to the unstable master branch.
  git checkout bug-fix-master
 
Now you can push your changes into the central code repository:
 
git pull --rebase
  git push origin <local-branch>:<remote-branch>
 
For your kdelibs example this would be:
 
  git pull --rebase
git push origin KDE/4.6:KDE/4.6
 
The next step is to apply the bug fix to the unstable master branch.  First check the master branch back out and update it:
 
  git checkout master
git pull --rebase
 
Next, Git makes it easy to apply the existing bug fix from the stable branch by using the cherry-pick command:
 
  git cherry-pick -x -e <sha5 of stable commit>
  git cherry-pick -x -e <sha5 of stable commit>
<build, test>
git push origin bug-fix-master:master


=== Advanced Bug Fix Workflow ===
This will allow you to edit the commit message as required before the change is committed.  If the patch does not apply cleanly a message will appear and the changes will not be committed.  You will then have to edit the changes and finish the commit manually.


the basic workflow works fine except switching between unstable and stable branches inside a single Git repository can lead to large rebuilds if the unstable branch has diverged too much from the stable branch.  On a small app this overhead may be small enough to not be a problem, but in most cases this constant rebuilding will be a waste of time.
Once cleanly applied and committed you can build and test the change, then push them to the central code repository:


This workflow uses the [[http://techbase.kde.org/Development/Git/Configuration#Multiple_Work_Branches|git-new-workdir script]] to create separate work directories and builds for stable and unstable branches. This depends on you setting different up KDE Environments for the separate builds.
git pull --rebase
git push origin master:master

Latest revision as of 23:42, 17 May 2016

DANGER WILL ROBINSON!!! THIS IS AN INCOMPLETE DRAFT!!!

Simple Workflow

This workflow is designed to be as close as possible to the KDE SVN Workflow. It is only recommended to be used for the first week or two of using Git with KDE while you become familiar with the basic Git commands. Once comfortable with the basic commands you should then move on to the Feature Branch Workflow.

In particular this workflow will not use git branches, merging or any remote features, all feature development work will be in the local master branch (the Git name for trunk).

More detailed information can be found on the main KDE Git page, in particular the Git for Subversion Users section. More details on the various commands can be found on the KDE Git Recipes page.

Set-up

This section documents how to set up Git and your code repository for development.

Configure Git

Follow all the instructions on the KDE Git Configuration page, the instructions given below assume you are using the standard configuration.

Clone your repository

You need to copy your central code repository from git.kde.org into your local KDE source directory. In Git this process is called cloning.

To clone your project repository:

cd your/source/dir
git clone kde:<project>
cd <project>

For example to clone kdelibs:

git clone kde:kdelibs
cd kdelibs

See the KDE Build Environment page for advice on structuring your source directory.

If you have a slow or intermittent internet connection then you may prefer to download a snapshot tarball to bootstrap your clone. You can copy the required command from the quickgit.kde.org Repository page for your project, but it will be of the form:

wget -c http://anongit.kde.org/<project>/<project>-latest.tar.gz

Local Feature Development

This section documents the basic workflow for developing a new feature for the master unstable branch (aka trunk in subversion). You will first make local code changes and commit them in your local repository before pushing them to the central code repository.

Making Local Changes and Commits

Changing and building code itself is no different from when using subversion, but how changed files are managed and committed is very different, as are the names and commands used. There are two key differences:

  • Locally modified files can have different states that determine whether they get committed or not.
  • Committing code is only local, it does not push your changes to the central repository which requires an extra step.

Files in a git repository can be in various states:

  • Untracked: Files in your local repository directory that Git is not tracking changes to and are not in the central repository.
  • Tracked: Files that git tracks changes to.
  • Unstaged: Tracked files that have had modifications to them but have not yet been staged or committed.
  • Staged: Tracked files that have had modifications made to them and have been marked to be included in the next commit
  • Committed: Files that git is tracking and that have been included in a local commit that may or may not be included in the central repository.

Note that different versions of a file can be in the Untracked and Tracked states at the same time.

This difference between staged and unstaged changes allows you to choose what changes you want in each commit.

To see what the current status of your local repository is:

 git status

This will show you the status as follows;

 # On branch master
 # Your branch is ahead of 'origin/master' by 1 commit.
 #
 # Changes to be committed:
 #   (use "git reset HEAD <file>..." to unstage)
 #
 #       modified:   src/kstagedfile.h
 #
 # 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/kchangedfile.h
 #
 # Untracked files:
 #   (use "git add <file>..." to include in what will be committed)
 #
 #       src/kuntrackedfile.txt

To add a changed file to the staging area, or to add a new file to be tracked by the repository:

 git add <filename>

You can also partially add the contents of a file to the staging area, so that it is easier to commit sets of related changes;

 git add -p <filename>

To delete a file from the repository and add the deletion to the staging area:

 git rm <filename>

To reset a staged file to be unstaged but without losing your changes:

 git reset HEAD <filename>

To reset an unstaged file to the currently committed version and irretrievably throw away your changes:

 git checkout <filename>

The git commit command differs from the svn commit command in only creating a commit in your local clone of the repository, it does not merge the changes into the central repository. This allows you to queue up a series of small changes before merging them into the central repository. This local commit history can also be modified before you finally do push the changes.

The git commit command adds all files in the staged state into a new commit:

 git commit

If you have only changed tracked files then you can automatically add all tracked files that have been changed into staging and commit all the staged files in one command:

 git commit -a

Seeing What You Changed

To see a list of what files have been changed but not yet committed:

git status

To see what code changes have been made but not yet staged:

git diff
git diff <filename>

To see what code changes have been staged but not committed:

git diff --staged
git diff --staged <filename>

To see all the commits made:

git log

To see what changes were made in a commit:

git show <sha5>

The Git diff, log and show commands have many options for changing what is shown. In particular diff can show the difference in a file between any two commits.

Pushing Your Changes To The Central Repository

When you are ready to push all your local commits to the central repository, you first need to update to the latest version of the master code in the central repository:

 git pull --rebase

This will update the underlying master code and apply your commits on the top of the latest version of the central repository, this is known as a rebase. Normally the rebase should apply cleanly, but sometimes there will be a conflict which you will need to resolve before you can complete applying your commits. There will be instructions given by git on how to complete the commit if required [TODO: get a copy of the output text].

Note that you cannot rebase if you have uncommitted changes. If you need to rebase but have changes that you don't want to commit, then you will need to stash the changes.

Depending on how much the underlying master code has changed you may want to rebuild and test the code after doing the rebase, before doing a final rebase. It is recommended to do regular rebase's between commits to keep the possibility of conflicts to a minimum.

Once your local commits have been cleanly reapplied you can push your changes to the central repository:

 git push origin master:master

Git will report if the push was successful or explain why it failed.

Local Bug Fixing

If your bug fix is only for unstable master then no special actions are required, just follow the same steps as the feature development workflow above.

If your bug fix is for a stable branch then this cannot be done without using git branches. The steps required will be given below but not explained in any detail. If possible it is recommended you wait until you are familiar with using the Feature Branch Workflow.

The steps detailed below are very inefficient as they use the same build tree and environment for unstable and stable which may cause a lot of rebuilding. A more efficient method is detailed in the Feature Branch Workflow.

First, find out the name of the stable branch you want to bug fix:

git branch -r

This will list all the branches on the central repository, for example kdelibs includes the following branches:

 origin/HEAD -> origin/master
 origin/KDE/4.5
 origin/KDE/4.6
 origin/kdecore/klocale-win
 origin/kdeui/kdatetimeedit
 origin/master

Here origin/KDE/4.6 is the 4.6 release of kdelibs which we will use for this example.

Next, create a local branch pointing to the stable release branch you want to bug fix:

git branch --track <local-branch> <remote-branch>
git checkout <local-branch>

For example, to create a local kdelibs 4.6 stable branch:

git branch --track KDE/4.6 origin/KDE/4.6
git checkout KDE/4.6

If you have previously created the stable branch and want to do a new bug fix, then simply check it out again and update it:

git checkout <local-branch>
git pull --rebase

Now make your required changes to the code, build and test. Once done commit the code changes to your local repository, remembering to include the BUG: and FIXED-IN: keywords in the commit message.

git commit -a

Make a note of the sha5 of the commit as you will need it later to copy the commit to the unstable master branch.

Now you can push your changes into the central code repository:

git pull --rebase
git push origin <local-branch>:<remote-branch>

For your kdelibs example this would be:

git pull --rebase
git push origin KDE/4.6:KDE/4.6

The next step is to apply the bug fix to the unstable master branch. First check the master branch back out and update it:

git checkout master
git pull --rebase

Next, Git makes it easy to apply the existing bug fix from the stable branch by using the cherry-pick command:

git cherry-pick -x -e <sha5 of stable commit>

This will allow you to edit the commit message as required before the change is committed. If the patch does not apply cleanly a message will appear and the changes will not be committed. You will then have to edit the changes and finish the commit manually.

Once cleanly applied and committed you can build and test the change, then push them to the central code repository:

git pull --rebase
git push origin master:master