-
Notifications
You must be signed in to change notification settings - Fork 25
Fork based workflow
Developers should mainly use a fork-based workflow for contributions to BLOM/iHAMOCC, as this encourages regular code review of all changes. The layout we aim for is described in this coderefienry instruction page. Contributors are strongly encouraged to read through these instructions, and note in particular the respective roles of the central repository
, the fork
and the local clone
.
HINT: Rename your fork
When forking a repository, it can sometimes be an advantage to
give your personal fork a distinct name derived from the central
repository, e.g. "BLOM-<github user name>", to distinguish the
fork from the upstream source.
HOWTO: In your personal BLOM fork, open the "Settings" tab,
and change entry in "Repository name".
NOTE: This will change the URL of your fork, so do this before
you create a local clone.
When cloning your personal fork to your local computer, you will only be able to access your own work space. Running
$ git remote [-v, --verbose]
should produce an output
origin https://github.com/<personal gitHub account>/<BLOM-fork-name>.git (fetch)
origin https://github.com/<personal gitHub account>/<BLOM-fork-name>.git (push)
Make your local clone aware of changes in the central repository (upstream) by running
$ git remote add upstream https://github.com/NorESMhub/BLOM.git
Now you should be able to see the main repository as well
$ git remote -v
origin https://github.com/<personal gitHub account>/<BLOM-fork-name>.git (fetch)
origin https://github.com/<personal gitHub account>/<BLOM-fork-name>.git (push)
upstream https://github.com/NorESMhub/BLOM.git (fetch)
upstream https://github.com/NorESMhub/BLOM.git (push)
- Create and checkout
new_feature
branch in local clone
$ git checkout -b new_feature
- After making changes and committing to
new_feature
, push changes toorigin
(BLOM fork)
$ git push -u origin new_feature
- The '-u' flag is only needed when pushing a new branch to
origin
. When the branch is present inorigin
, any further changes can be pushed bygit push
from thenew_feature
branch. - In BLOM fork, create pull request from
new_feature
branch to BLOM repository (master
by default, or select an appropriate feature branch if it already exist).
HINT: Why not merge new_feature
with master
in local clone or fork?
This will cause your local/fork `master` branch to diverge from upstream.
You should aim to keep an identical history for local/fork branches that
exist in the upstream repository, as this will allow you to do a
"fast-forward" merge with upstream without creating a new merge commit.
If you get conflicts when doing the pull request, try to update your
local clone repository from upstream, and apply fixes to the
`new_feature` branch that removes the conflict.
Sometimes the feature branch you want to work on already exist on the remote side (origin
or upstream
)
- Create a local branch that tracks changes in an existing remote branch (2 methods): keep name
existing_feature
locally, or change name tomybranch
locally
$ git checkout --track origin/existing_feature
$ git checkout -b mybranch origin/existing_feature
- Normally you do not wish to track upstream in this way, as you should not push directly to upstream but use pull requests. To check out an existing upstream branch without tracking
$ git checkout --no-track upstream/existing_feature
If you follow the advice to always commit your work in local feature branches, your master
branch should remain clean and not contain commits other than those from upstream. In this case the "merge" should automatically be "-fast-forward". Otherwise, a separate "merge commit" will be created when you update your local branch.
- Fetch all changes from upstream
$ git fetch upstream
- Update your local branch, e.g.
master
, from upstream.
$ git checkout master
$ git merge upstream/master
- Now push changes to your fork (again, assuming fork branches are clean)
$ git push origin master
HINT: Why not update the gitHub fork from upstream directly?
In principle it is possible to pull changes from upstream to a fork in
gitHub, by doing a "reverse" pull request. However, this is almost always
a bad idea. The pull request will create a separate merge commit that exist
only on the fork, hence the fork history will diverge from upstream, and
you will get a message that the fork is ahead of the upstream by 1 commit.
Sometimes you may commit to the wrong branch by accident, or commit several changes to a branch that you later realize should be clean. How can you recover a clean state?
- Undo last commits in local clone, reset to commit with checksum SHA, but keep changes in files from deleted commits
$ git reset SHA
- Undo last commits in local clone, reset to commit with checksum SHA, and delete changes in files from deleted commits
$ git reset --hard SHA
- Local clone and fork has diverged from
upstream/master
in a bad way. Force branches to reset fromupstream/master
. Deletes local changes.
$ git fetch upstream
$ git checkout master
$ git reset --hard upstream/master
$ git push origin master --force
- Reset
master
toupstream/master
, but keep your local changes in anew_feature
branch.
- First create a
new_feature
branch (see earlier section) from your localmaster
branch that has diverged fromupstream/master
, and push this toorigin/new_feature
. - Then do a hard reset on
master
(see #3). You should now havemaster
synced withupstream/master
and your local changes innew_feature
branching offmaster
at their point of divergence in history. - (optional) Merge changes from
master
tonew_feature
, or rebasenew_feature
on top ofmaster
(see below)
More git reset options are discussed in this blog post about undoing git mistakes.
Git provides two main options for integrating changes between branches, merging and rebasing.
Assuming that you have just updated your local clone from upstream/master
, and want to merge changes to your feature branch.
$ git checkout new_feature
$ git merge master
$ git push origin new_feature
The git rebase
command allows changing of the branch point for a branch relative to its base. This is done by reapplying a series of changes from a branch to a different base, and reset the HEAD of that branch to the result.
WARNING: git rebase
changes the commit history. Do not use git rebase
on a repository that is shared among multiple users!
Assuming that you have just updated your local clone from upstream/master
, and want to rebase changes to your feature branch.
$ git checkout new_feature
$ git rebase master
$ git push --force origin new_feature
In this case you need to force the push to origin
(BLOM fork) since you are re-writing the commit history on the remote side. Only use rebase
and push --force
with forks that you do not share with others, as this will break history for any other clones of the fork than the one that you have pushed from.
It is usually best to resolve any conflicts in the local clone before pushing to origin
and committing a pull request. The pull request should give feedback if the merging to upstream can be done without conflicts.
- A coderefinery tutorial on how to deal with conflicts.
After a pull request has been accepted and merged, you will sometimes get the option to delete the branch used for the pull request. Deleting merged branches is safe, the commit history will be preserved, only the branch label will be removed. This may be a good option for single issue feature branches, e.g. bug fixes, but may not be appropriate in all cases.
If you decide to delete the branch, this will only affect the origin
(BLOM fork), not the local clone. To update the clone, do
$ git fetch upstream
$ git checkout master
$ git merge upstream/master
$ git branch -d new_feature
$ git fetch -p
$ git push
The '-p' (prune) flag in fetch removes any remote-tracking references that no longer exist on the remote. The last git push
is needed to update the master
branch on origin
, as this is not done as part of the pull request.
This can be done directly in the github web interface:
- Switch to the feature branch
<feature>
- Under the "contribute" button, click the "compare" button
This opens up a new web page where you can review the changes between <feature>
and master
. At the top of the page is an option to merge <feature>
into master
, but this sequence can be reversed.
- Reverse the suggested pull request
- base: master <- compare: feature
- base: feature <- compare: master
- Create the pull request
When comparing branches under github, the system will check if there are potential conflicts. When no conflicts are detected, a green check mark with the text "Able to merge" will appear at the top of the comparison web page. If instead you get a conflict at this stage, you may want to do the merge locally first, resolve the conflicts, and then create a pull request from your locally merged branch.
- From your local clone, check out the
master
branch - Create a new merge branch
<merge>
on top ofmaster
- Merge the
<merge>
branch into the feature branch<feature>
- Resolve conflicts
- Create a pull request from
<merge>
to<feature>
in the github repository - After completing the pull request, update the local
<feature>
branch with changes from github, and delete the now obsolete<merge>
branch.
BLOM wiki, © Copyright 2023, BLOM development team. This documentation is licensed under a ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.