Also read gitfaq which has other workflows and PHP git tips.
Git does not enforce a certain workflow. For php-src we will use a workflow that is similar to the existing (SVN) workflow.
We will use release branches for the php-src.git repository. We will have branches for actively maintained versions. For example: 5.3, 5.4, 5.5, 5.6 and master (what would be trunk in SVN). A patch will be applied to the oldest possible branch. If the Release Manager of 5.3 accepts the change, commit it to the 5.3 branch. We will use regular merging between the release branches. Bigger features can use feature branches, but developers are encouraged to fork php on github and start implementing the feature there on the respective branch.
Core developers that have access to the php-src.git repository apply changes to the lower possible branch and then merge the change upwards. The repository is prepared in a way, that only new changes will be merged upwards. E.g. Git will not attempt to synchronize the whole 5.3 and 5.4. branch. Only your commit will be merged.
Here is a visualization of a standard Patch Workflow
Let's go through the process of setting it up and doing the merges.
The initial setup:
$ git clone firstname.lastname@example.org:php-src.git
Please refer to Git FAQ for alternative cloning methods via HTTP or the Git Protocol.
$ cd php-src $ git checkout -b PHP-5.3 origin/PHP-5.3 $ git checkout -b PHP-5.4 origin/PHP-5.4 $ git checkout -b PHP-5.5 origin/PHP-5.5 $ git checkout -b PHP-5.6 origin/PHP-5.6
Patching the PHP 5.3 branch
$ git checkout PHP-5.3 ... hack hack ... $ git commit <changed files> ... USE A GOOD COMMIT MESSAGE ... ... run tests ... $ git checkout PHP-5.4 $ git merge --no-ff --log PHP-5.3 ... run tests ... $ git checkout PHP-5.5 $ git merge --no-ff --log PHP-5.4 ... run tests ... $ git checkout PHP-5.6 $ git merge --no-ff --log PHP-5.5 ... run tests ... $ git checkout master $ git merge --no-ff --log PHP-5.6 ... run tests ... $ gitk master ... review the merges ... $ git push origin ... push to the official repository ...
When you use 'git push –all origin', make sure there are not any unwanted branches in local repository or set branch.<name>.remote properly via git-config.
Johannes has created a tool to easily close pull requests. It requires a valid PHP account.
In case you want to merge a pull request that someone else opened on github into the 5.4 branch, use the following commands:
$ git checkout PHP-5.4 $ git fetch git://github.com/<user>/web-php pull/23/head:pull-request/23 $ git log -p pull-request/23 ... REVIEW IT ... $ git merge --no-ff pull-request/23 .. Merge it, add a GOOD commit message ... $ make test .. you better don't forget that ... $ git checkout PHP-5.5 $ git merge --no-ff --log PHP-5.4 $ make test $ git checkout PHP-5.6 $ git merge --no-ff --log PHP-5.5 $ make test $ git checkout master $ git merge --no-ff --log PHP-5.6 $ make test $ git push origin master ... everything okay? good, let's push it ...
In case you have to merge a commit from a higher branch. E.g from PHP-5.4 into PHP-5.3 make sure you still merge upwards as described above afterwards:
$ git checkout PHP-5.3 $ git cherry-pick <SHA1-OF-PATCH-TO-MOVE> $ git checkout PHP-5.4 $ git merge --no-ff --log PHP-5.3 $ git checkout PHP-5.5 $ git merge --no-ff --log PHP-5.4 $ git checkout PHP-5.6 $ git merge --no-ff --log PHP-5.5 $ git checkout master $ git merge --no-ff --log PHP-5.6 $ git push
TL;DR: Always try to merge PHP-5.3 into PHP-5.4, PHP-5.4 into PHP-5.5, PHP-5.5 into PHP-5.6 and then PHP-5.6 into master. If you are unsure ask dsp
If patches are created with “git format-patch”, you can easily apply them with git's am command:
$ git am 000*
Normal diff-patches can be applied with git apply:
$ git apply <patchfile>
Feature development can take a lot of time. You might not know to which branch the feature will be commited or you want to combine commits before pushing the final bits. Therefore it is adviced to use a separate branch while you develop your feature. This approach is called a feature branch:
The workflows aims for a feature to be included into the master branch. So we branch of the master branch first:
$ git checkout -b feature/featurename master .. hack hack hack ... $ git commit
Update your branch regularly so it's up to date:
$ git checkout feature/featurename $ git rebase master
Once the feature is accepted merge it into master:
$ git checkout master $ git merge --no-ff --log feature/featurename
The standard workflow for external contributors:
Fork the php-src to your own github account. Setup your issue branch on your development system:
$ git clone email@example.com:<account>/php-src.git php $ cd php $ git remote add upstream https://github.com/php/php-src.git $ git fetch upstream $ git branch --track issue-<issuenr> origin/PHP-5.4 (or use origin/master) $ git checkout issue-<issuenr>
Do your stuff and add/commit your work accordingly. Optionally, you can rebase your work:
$ git pull --rebase upstream PHP-5.4 (or use upstream master)
Push your branch to your github repository:
$ git push origin issue-<issuenr>
Before you send in your pull request:
We accept patches in several ways. We prefer getting pull requests from github:
If you prefer mail use git format-patch and send the created patch using mail:
$ git format-patch origin/PHP-5.4 0001-bug-fix.patch ... 0005-another-commit.patch
If you don't have an issue-number, just make the branch name self-descriptive (ie: “json_encoding_fix” instead of “branch-001”). As stated before, branch from the lowest version possible. When you want to create a patch that needs to be incorporated into several branches, like a security fix for something in PHP-5.3, PHP-5.4, PHP-5.5 and the master, make sure you checkout a branch from PHP-5.3. You don't need to create separate pull requests for PHP-5.4, PHP-5.5 and master.
We propose the following commit message format for PHP:
<max 79 characters short description>\n \n <long description, 79 chars per line> \n
An Example from the git project (commit 2b34e486bc):
pack-objects: Fix compilation with NO_PTHREDS It looks like commit 99fb6e04 (pack-objects: convert to use parse_options(), 2012-02-01) moved the #ifdef NO_PTHREDS around but hasn't noticed that the 'arg' variable no longer is available.
Git commands like log, shortlog, etc support this format and make use of the short description. Please stick to the format.