Much of the workflow for contributing to CodeIgniter (or any project) involves understanding how Git is used to manage a shared repository and contributions to it. Examples below use the Git bash shell, to be as platform neutral as possible. Your IDE may make some of these easier.
Some conventions used below, which you will need to provide appropriate values for when you try these:
ALL_PROJECTS // folder location with all your projects in subfolders, eg /lampp/htdocs
YOUR_PROJECT // folder containing the project you are working on, inside ALL_PROJECTS
ORIGIN_URL // the cloning URL for your repository fork
UPSTREAM_URL // the cloning URL for the CodeIgniter4 repository
- All bug fix PRs should be sent to the "develop" branch, this is where the next bug fix version will be developed.
- PRs with any enhancement should be sent to next minor version branch, e.g. "4.6"
The "master" branch will always contain the latest stable version and is kept clean so a "hotfix" (e.g: an emergency security patch) can be applied to master to create a new version, without worrying about other features holding it up. Any sent to "master" will be closed automatically.
If you have multiple changes to submit, please place each change into their own branch on your fork.
One thing at a time: a pull request should only contain one change. That does not mean only one commit, but one change - however many commits it took. The reason for this is that if you change X and Y but send a single pull request for both at the same time, we might really want X but disagree with Y, meaning we cannot merge the request. Using the Git-Flow branching model you can create new branches for both of these features and send two requests.
You work with a fork of the CodeIgniter4 repository. This is a copy of our repository, in your GitHub account. You can make changes to your forked repository, while you cannot do the same with the shared one - you have to submit pull requests to it instead.
Creating a fork is done through the GitHub website. Navigate to our repository, click the Fork button in the top-right of the page, and choose which account or organization of yours should contain that fork.
You could work on your repository using GitHub's web interface, but that is awkward. Most developers will clone their repository to their local system, and work with it there.
On GitHub, navigate to your forked repository, click Clone or download, and copy the cloning URL shown. We will refer to this as ORIGIN_URL.
Clone your repository, leaving a local folder for you to work with:
> cd ALL_PROJECTS
> git clone ORIGIN_URLGit names your fork origin when you clone it. Add the main CodeIgniter4
repository as upstream so that you can fetch changes made by other
contributors. You only need to add this remote once:
> git remote add upstream https://github.com/codeigniter4/CodeIgniter4.git
> git remote -vIf upstream already exists but uses the wrong URL, update it instead:
> git remote set-url upstream https://github.com/codeigniter4/CodeIgniter4.gitFetch the latest upstream branches before rebasing:
> git fetch upstreamRebase bug-fix branches onto upstream/develop:
> git switch your-branch
> git rebase upstream/developFeatures and enhancements target the next minor-version branch. Replace 4.x
with the branch used by your pull request:
> git switch your-branch
> git rebase upstream/4.xImportant
Do not merge the upstream target branch into your contribution branch. A merge may add merge commits that make the pull request and project history harder to follow. Rebasing keeps the commit history linear and easier to review.
Make sure local work is committed or stashed before rebasing. If Git reports a conflict, edit the affected files, mark them as resolved, and continue:
> git add path/to/resolved-file
> git rebase --continueRepeat these commands until the rebase is complete. To cancel the rebase and return the branch to its previous state, run:
> git rebase --abortIf the branch was already pushed to your fork, update it safely after rebasing:
> git push --force-with-lease origin your-branchUse --force-with-lease rather than --force so that Git does not overwrite
remote changes that you have not fetched.
The top of this page talked about the master and develop branches. The best practice for your work is to create a feature branch locally, to hold a group of related changes (source, unit testing, documentation, changelog, etc).
This local branch should be named appropriately, for instance "fix/problem123" or "new/mind-reader". The slashes in these branch names is optional, and implies a sort of namespacing if used.
- All bug fix PRs should be sent to the "develop" branch, this is where the next bug fix version will be developed.
- PRs with any enhancement should be sent to next minor version branch, e.g. "4.6"
For instance, if you send a PR to "develop" branch, make sure you are in the develop branch, and create a new bugfix branch, based on develop, for a new feature you are creating:
> git switch develop
> git switch -c fix/problem123If you send a PR with an enhancement, make sure you are in the next minor version branch, and create a new feature branch, based on, e.g., "4.6", for a new feature you are creating:
> git switch 4.6
> git switch -c new/mind-readerSaving changes only updates your local working area.
Your local changes need to be committed to save them in your local repository. This is where contribution signing comes in.
Now we don't have detailed rules on commits and its messages. But atomic commit is recommended. Keep your commits atomic. One commit for one change.
There are some references for writing good commit messages:
If there are intermediate commits that are not meaningful to the overall PR, such as "Fix error on style guide", "Fix phpstan error", "Fix mistake in code", and other related commits, you can squash your commits so that we can have a clean commit history. But it is not a must.
Commit messages are important. They communicate the intent of a specific change, concisely. They make it easier to review code, and to find out why a change was made if the code history is examined later.
The audience for your commit messages will be the codebase maintainers, any code reviewers, and debuggers trying to figure out when a bug might have been introduced.
Make your commit messages meaningful.
Commit messages are expected to be descriptive of why and what you changed specifically. Commit messages like "Fixes #1234" would be asked by the reviewer to be revised.
You can have as many commits in a branch as you need to "get it right". For instance, to commit your work from a debugging session:
> git add .
> git commit -S -m "Fix the broken reference problem"Just make sure that your commits in a feature branch are all related.
Note
We recommend to Set Default Signing for
secure signing commits without the -S option in git commit.
Any developer can forget GPG-signing their commits with the option -S, like
git commit -S -m 'Signed GPG'. In such a case, all you need to do is the following:
Latest commit only:
> git switch your-branch
> git commit --amend --no-edit --no-verify -S
> git push --force-with-lease origin your-branchOnly the specified number of commits:
> git switch your-branch
> git rebase -i HEAD~3 --exec 'git commit --amend --no-edit --no-verify -S'
> git push --force-with-lease origin your-branchNote
HEAD~3 specifies the last 3 commits in the PR. Change 3 to the actual number of commits.
All commits:
> git switch your-branch
> git rebase -i --root --exec 'git commit --amend --no-edit --no-verify -S'
> git push --force-with-lease origin your-branchAs a faster alternative, you can still securely sign commits without the -S
option in git commit. See Set Default Signing.
If you are working on two features at a time, then you will want to switch between them to keep the contributions separate. For instance:
> git switch new/mind-reader
> ## work away
> git add .
> git commit -S -m "Added adapter for abc"
> git switch fix/issue-123
> ## work away
> git add .
> git commit -S -m "Fixed problem in DEF\Something"
> git switch developThe last switch makes sure that you end up in your develop branch as a starting point for your next session working with your repository. This is a good practice, as it is not always obvious which branch you are working in.
At some point, you will decide that your feature branch is complete, or that it could benefit from a review by fellow developers.
Before pushing, follow Configuring Upstream and Rebasing to bring your contribution branch up to date and resolve any conflicts.
And finally push your local branch to your GitHub repository:
> git push --force-with-lease origin fix/issue-123On GitHub, you propose your changes one feature branch at a time, by switching to the branch you wish to contribute, and then clicking on "New pull request".
Make sure the pull request is for the shared "develop" or next minor version branch, e.g. "4.6", or it may be rejected.
Make sure that the PR title is helpful for the maintainers and other developers. Add any comments appropriate, for instance asking for review.
Note
If you do not provide a title or description for your PR, the odds of it being summarily rejected rise astronomically.
When your PR is submitted, a continuous integration task will be triggered, running all the unit tests as well as any other checking we have configured for it. If the unit tests fail, or if there are merge conflicts, your PR will not be mergeable until those are fixed.
Fix such changes locally, commit them properly, and then push your branch again. That will update the PR automatically, and re-run the CI tests. You don't need to raise a new PR.
If your PR does not follow our contribution guidelines, or is incomplete, the codebase maintainers will comment on it, pointing out what needs fixing.
If you have the privilege of labeling PRs, you can help the maintainers.
Label your PRs with the one of the following labels:
- bug ... PRs that fix bugs
- enhancement ... PRs to improve existing functionalities
- new feature ... PRs for new features
- refactor ... PRs to refactor
And if your PRs have the breaking changes, label the following label:
- breaking change ... PRs that may break existing functionalities
If you are asked for changes in the review, commit the fix in your branch and push it to GitHub again.
If the "develop" or next minor version branch, e.g. "4.6", progresses and conflicts arise that prevent merging, or if you are asked to rebase, you may first create a backup branch:
> git branch fix/problem123.bk fix/problem123Then follow Configuring Upstream and Rebasing.
Occasionally, the Composer packages for development may be updated. Run the following command to use the latest packages:
composer updateAnd finally push your local branch to your GitHub repository:
> git push --force-with-lease origin fix/problem123If you have sent a PR to the wrong branch, you need to create a new PR branch.
When you have the PR branch feat-abc and you should have sent the PR to "4.6",
but you created the PR branch from develop and sent a PR.
Copy the IDs of any commits you made that you want to keep:
> git logFetch the latest upstream branches:
> git fetch upstream(Optional) Create a new branch as a backup, just in case:
> git branch feat-abc.bk feat-abcRebase your PR branch from develop onto "4.6":
> git rebase --onto upstream/4.6 develop feat-abcForce push.
> git push --force-with-lease origin feat-abcOn the GitHub PR page, change the base branch to the correct branch "4.6".
If your PR is accepted and merged into the shared repository, you can delete that branch in your GitHub repository as well as locally.