wiki:HowToGit

Version 66 (modified by hcho, 5 years ago) ( diff )

git merge should be done into the same local branch; otherwise, getting a lot of conflicts in and contaminating the master branch

Contributing guidelines

The development workflow changes notably after migration from Subversion to Git (GitHub).

The repo is here: https://github.com/OSGeo/grass

Important changes:

  • direct committing to "master" (former "trunk") is a no-go and disabled
  • hence: you will create a feature branch and open a pull request for a change
    • Rationale: pull requests are the perfect platform to discuss/improve changes before merging.
    • also applies to core developers (to be discussed)

Workflow

  • fork the GRASS GIS repository, and create feature branch(es) with the changes, and suggest your changes as pull requests.

Workflow for core GRASS GIS git repository

- to be discussed -

Preparation: cloning the repo

First fork the GRASS GIS repo in the GitHub UI to your_GH_account. This is the same as what GitHub documentation suggests. See: Fork a repo and Syncing a fork in GitHub help.

Note: add SSH key, see GitHub documentation.

# "origin" points to your fork repo - IMPORTANT
git clone git@github.com:your_GH_account/grass.git

# add "upstream" remote
cd grass/
git remote add upstream git@github.com:OSGeo/grass.git

git remote -v
# you should see something like
origin	  git@github.com:your_GH_account/grass.git (fetch)
origin	  git@github.com:your_GH_account/grass.git (push)
upstream  git@github.com:OSGeo/grass.git (fetch)
upstream  git@github.com:OSGeo/grass.git (push)

Working with git

Note: this requires the "remotes" to be set as shown above.

# updating from git server: fetch all branches from all remotes
git fetch --all

### a) updating MASTER
# merge updates into local master
git merge upstream/master

# at this point we have reached:
# (HEAD -> master, upstream/master)

### b) updating releasebranch_7_6
# switch to branch
# only once
git checkout -b releasebranch_7_6 origin/releasebranch_7_6
# next time, git checkout releasebranch_7_6

# merge updates into local branch
git merge upstream/releasebranch_7_6

# at this point we have reached:
# (HEAD -> releasebranch_7_6, upstream/releasebranch_7_6)

# update own remote
# - clears "Your branch is ahead of 'origin/master' by XX commits.", and
# - avoids "This branch is XX commits behind OSGeo:master." on GitHub web interface
git push origin master

# list existing branches
git branch -a

##### Implementation of own changes
# create new local branch (pick a new name for feature_branch_name)
git checkout -b feature_branch_name

# <make local source code changes>
vim ...

# list local changes
git status
git add file1.c file2.py ...
git commit -m 'my change with reasonable explanation...'

# push feature branch to origin, i.e. your fork of the OSGeo/grass repo
git push origin feature_branch_name
# create pull request in GitHub Web interface (the link is then shown in the terminal)

# during PR review phase, make more local changes if needed
git add .
git commit -m 'my second change'
git push origin feature_branch_name
# ..... will be added to existing pull request

NOTE: for different pull requests, simply create different feature branches.

Keep your local source code up to date

[from https://github.com/OSGeo/gdal/blob/master/CONTRIBUTING.md#working-with-a-feature-branch]

You may need to resynchronize against master if you need some bugfix or new capability that has been added since you created your branch

# assuming that "upstream" points to OSGeo/grass
git fetch upstream
git rebase upstream/master

# if rebase fails with "error: cannot rebase: You have unstaged changes...", then move your uncommitted local changes to "stash"
git stash
# now you can rebase
git rebase upstream/master
# apply your local changes on top
git stash apply && git stash pop

Continue do your changes and commit/push them (ideally to a feature branch, see above).

Workflow for grass-addons repository

- to be discussed -

Direct commits are allowed, but you can still use alternatively the same workflow as defined for core repository based on PRs.

One time only:

# "origin" points to your grass-addons repo - no fork needed
git clone git@github.com:OSGeo/grass-addons.git

Work with git:

# <make local source code changes>
vim ...

# list local changes
git status
git add file1.c file2.py ...
git commit -m 'my change with reasonable explanation...'

# assuming that "origin" points to OSGeo/grass-addons
git fetch origin
# IMPORTANT - ALWAYS REBASE IN ORDER TO AVOID NOT NEEDED MERGE COMMITS (!!!)
git rebase origin/master

# push feature branch to origin, i.e. directly to OSGeo/grass-addons repo
git push origin

Switching between branches

For an elegant way of multi-branches in separate directories with only a single repo clone, see

https://lists.osgeo.org/pipermail/grass-dev/2019-May/092653.html

Testing pull requests from other contributors in master

GitHub provides command line instructions under each pull request ("Pulls" tab). Please check there.

Fixing bugs in a release branch

TODO: verify

To directly fix bugs (ideally via feature branch), do

# push to release_branch, we assume it to be checked out

cd releasebranch_7_4/
# be sure to locally have all updates from server
git fetch --all
git branch --merged 

# create feature branch
git checkout -b r74_fix_xxx

# ... do changes...

git status
git add ...
git commit -m 'useful commit msg...'

# push to feature branch
git push upstream r74_fix_xxx

# create PR in GitHub UI. IMPORTANT: switch there to release_branch_X_Y!

# ... after review, merge:

# switch to release branch
git checkout releasebranch_7_4 

# be sure to locally have all updates
git fetch --all
git branch --merged 

git branch -D changelog_fix_msg_74 
git fetch --all --prune
git branch -a

Backporting to release branches

Preparation

If you checked out the release branch into a separate directory, be sure to have "upstream" enabled as a remote:

git remote -v
# if upstream is missing, execute
git remote add upstream git@github.com:OSGeo/grass.git

Backporting of a single commit

# temporarily switch to master
git checkout master

# update master to fetch the commit to be backported
git fetch --all --prune 

# ??? With git log, identify the sha1sum of the commit you want to backport (example: backport into releasebranch_7_6)
git log

# Note: only needed if you have your fork as "origin" (see above)
# update local repo 
## NO git pull origin releasebranch_7_6 --rebase

# switch to branch
git checkout releasebranch_7_6

# merge updates into local releasebranch_7_6
git merge upstream/releasebranch_7_6

# at this point we have reached:
# (HEAD -> master, upstream/releasebranch_7_6, releasebranch_7_6)

# ??? update own remote
git push origin releasebranch_7_6

# now backport the commit (edit conflicts if needed)
git cherry-pick the_sha1_sum

# verify
git show

# push backport to upstream
git push upstream releasebranch_7_6 

See also https://github.com/OSGeo/gdal/blob/master/CONTRIBUTING.md#backporting-bugfixes-from-master-to-a-stable-branch

Backporting of a merged pull request from master

Same as "Backporting of single commits" but with multiple git cherry-pick .... Importantly, in the right order.

TODO: there must be a better way!!

Made a mess? Fix it

Example: mess happened on releasebranch_7_6:

git reset --hard upstream/releasebranch_7_6 
git pull upstream releasebranch_7_6 --rebase

# now all should be clean again

Code review: generate a single diff for a PR with multiple commits

To speed up reviewing of a PR with multiple commits by reading a single diff file, you may diff the branch against the branch origin point. For example, if you PR 28 is on local branch pr_28, branched from master, you can do:

git checkout pr_28

# note: with the three dots, it will only show diffs from changes on your side:
git diff master...

For more hints, see e.g. this Stackoverflow discussion.

Merging of Pull Requests

Rationale: We should try to have clean history and good commit messages. This helps really a lot when you try to understand why something is implemented the way it is.

When a Pull Requests (PR) has multiple commits, the merge commit is more or less mandatory because if you don't have it, you can't use git revert.

PR with single commit

Proposed: when a PR only has a single commit, the "merge commit" doesn't offer anything and it can be avoided by rebasing the feature branch:

Workflow: GitHub > button "Merge pull request" > "Rebase and merge"

Next, you may locally delete the feature branch.

PR with multiple commits

Proposed: it is a good idea to try to squash the accumulated commits in a PR before merging, especially if those are trivial fixes.

As an example, PRxx contains 5 commits. Esp. in case that several commits of them are trivial fixes that only add noise to the history, "squashing" those results in a cleaner history and, among other things, makes it easier to use git bisect and git blame.

Importantly, not always commits of each and every PR need to be squashed before merging. When extensive changes are being made, it often makes sense to keep them unsquashed (e.g. to make reviewing easier), but trivial fixes should still be squashed to the main commits.

Further reading

Note: See TracWiki for help on using the wiki.