Fork and Branch Git Workflow
This is the definition of the workflow to manage iDempiere commits (starting April 30/2020)
This workflow is usually known as "Forking Workflow" or "Fork-and-Branch Git Workflow" - you can find good explanations about this kind of workflow searching in google.
The document explains how to do it for iDempiere:
- 1 Creating a fork
- 2 Clone locally
- 3 Asking for a pull request
- 4 Changing a pull request
- 5 Approving a pull request
- 6 After approval
- 7 Avoid committing to master
- 8 Summary
Creating a fork
It is encouraged that every developer contributing to iDempiere project creates his/her own fork.
Creating a fork is really easy, just navigate to:
and push the button "Fork".
This will create a fork in your userspace on GitHub.
To clone locally you can execute on the command line:
NOTE: in case you already cloned idempiere from the official repository, instead of doing a full clone again you can go to your cloned folder and execute:
git remote remove origin git remote add origin https://github.com/(your-github-user)/idempiere.git
Then set the original idempiere as the upstream
git remote add upstream https://github.com/idempiere/idempiere.git git branch --set-upstream-to=origin/master master
You can verify that you have the correct setup with
git remote -v
and you should see similar output to what I've below:
origin email@example.com:hengsin/idempiere.git (fetch) origin firstname.lastname@example.org:hengsin/idempiere.git (push) upstream https://github.com/idempiere/idempiere.git (fetch) upstream https://github.com/idempiere/idempiere.git (push)
And now proceed to configure your development environment as explained in Installing iDempiere
Asking for a pull request
Sync with upstream
You must always ensure that your clone is in sync with the master repository:
git checkout master git pull upstream master git push origin master
Create feature branch
Every commit must be done in a feature branch created for the specific ticket, please never use master or a release branch to commit:
Create a feature branch for the JIRA ticket you're solving:
git checkout -b IDEMPIERE-(Jira-ticket-number)
Develop or integrate a patch
Then you can do the changes or integrate patch being peer-reviewed.
The usual ways to apply patches are:
- normal patch format (f.e. coming from mercurial)
git apply (patch-file)
- patches in git format are normally created using the instruction "git format-patch -1 --stdout (commit) > (patch-file)", these patches can be imported using:
git am --keep-cr (patch-file)
You must always ensure you conducted tests before committing, never commit untested code (seriously, your reputation suffers).
Test your changes, and even more important, always check for collaterals of the code you changed, figure out other use cases affected and test them too!
When all tests are OK add the changed files to stage
git add .
And then commit, two important things here:
- use one of your GitHub registered emails
- the commit message must contain the IDEMPIERE-(Jira-ticket-number)
- if your commit resolves completely the JIRA ticket you can add the smart commit message #resolve
- also you can add a final comment to the ticket adding #comment (your-final-comment-for-ticket)
Now push your commit to your own fork:
If it doesn't work try
git push origin IDEMPIERE-(Jira-ticket-number) [your branch]
And then navigate in your browser to the URL indicated in the console output, it usually has the form:
Write a proper message there, explaining the impact of the changes, the tests conducted for your use case and other use cases affected.
The more information about the impact and how to test, the easier will be for the peer reviewer to accept the change.
And then submit the request pushing the button "Create pull request".
Changing a pull request
Adding more commits
In case the peer reviewer request changes on the pull request, you can simply do the changes and push the new commits to your repository, github will automatically update the pull request accordingly.
Editing the commit message
The commit message must always contain the JIRA ticket that solves it (and also it can use smart commit message to solve it automatically, in case you're requested to modify the commit message to follow this rules, you can use the next commands to edit the message of the last commit (there is a possibility to edit older commit messages, this instruction is just for the latest):
git checkout -b IDEMPIERE-(Jira-ticket-number) git commit --amend git push --force-with-lease
Approving a pull request
Our workflow is configured to require at least 1 approval from a core developer (different than the requester).
The reviewer can visit the link of the pull request, and follow the instructions there if it is a small commit, a code peer review maybe is enough, if it is a big change, is better to conduct local tests, there are instructions in GitHub about how to test locally the pull request.
In this process, the pull request can be approved, commented requesting changes, or rejected.
The core developer approving the commit usually pushes the button "Squash and merge" to integrate the code into the official master.
After that you can pull the changes again from the upstream:
git checkout master git pull upstream master
Push the change to your fork:
git push origin master
And delete your temporary feature branch locally:
git branch -d IDEMPIERE-(Jira-ticket-number)
And delete your temporary feature branch on the remote repository (NOTE this is not required if you your repository setting "Automatically delete head branches" is set to true):
git push origin --delete IDEMPIERE-(Jira-ticket-number)
And finally, resolve the JIRA ticket if the development is complete (this step is not required if you used smart commit message as explained above).
if your local working directory have changes that you need to temporarily put aside, git stash is a very useful tool for that.
Avoid committing to master
To avoid committing by mistake to the master branch you can create the file
.git/hooks/pre-commit with the following content:
#!/bin/sh branch="$(git rev-parse --abbrev-ref HEAD)" if [ "$branch" = "master" ]; then echo "You can't commit directly to master branch" exit 1 fi
And then make the file executable:
chmod +x .git/hooks/pre-commit
Summarizing, this is how a commit travels between repositories:
- local: push to origin feature branch
- github: pull request to the upstream master
- github: approve
- github: merge to upstream master
- local: pull it back from upstream
- local: push back to your origin master