gitworkflow:triangularworkflow

Git Triangular Workflow

The main characteristics of this workflow are:

  • Develop changes on top of FreeBSD release branch, e.g. releng/X.Y
  • Publish these changes in a personal/corporate git repository for testing and use in production
  • Once these changes have been tested and have matured enough, up-port them on top of HEAD for review
  • Once review accepted, push them in HEAD
  • Rebase changes that have not yet been accepted to old releng/X.Y branch to new releng/X.(Y+1) branch

For experimented git users (i.e. users that already fell in every git pitfalls) this workflow is common sense, but might help some to start FreeBSD contributions with a straightforward workflow.

Introduction

This workflow assumes you use multiple repositories, i.e.:

  • origin repository: Our own personal/corporate repository with full access, e.g. https://github.com/user/freebsd/
  • upstream repository: The official FreeBSD repository with read-only access, e.g. https://github.com/freebsd/freebsd/
  • Main workflow rules being
    • Changes coming from upstream repository are merged
    • Changes developed in origin repository are rebased

Local Git Repository First Steps

Clone personal FreeBSD git repository (can be empty at first)

$ git clone git@github.com:user/freebsd.git
$ cd freebsd/

Add FreeBSD upstream as remote repository and fetch changes

$ git remote add upstream git@github.com:freebsd/freebsd.git
$ git fetch upstream
  • Note: $ git fetch upstream command will take roughly 5/10 minutes depending on our internet connection

Origin Repository Branches

Origin repository branches will look like:

8.3-next/
8.4-next/
10.0-next/
10.1-next/
10.2-next/
master

The X.Y-next branches are where changes/fixes are developed. These branches are created from corresponding upstream release branches releng/X.Y/ from upstream repository. master branch is just CURRENT, and used for review creation. See below how they are created.

Create a X.Y-next Branch and Publish it

Get last upstream changes

$ git fetch upstream

Create new X.Y-next branch from corresponding upstream/releng/X.Y release branch

$ git checkout -b 10.2-next upstream/releng/10.2

Publish branch to origin repository

$ git push -u origin 10.2-next

If the X.Y-next is already present in origin repository:

$ git fetch origin
$ git checkout -t origin/10.2-next

Create master Branch and Publish it

Get last upstream changes

$ git fetch upstream

Create new master branch from corresponding upstream/master CURRENT branch

$ git checkout -t upstream/master

Publish master branch to origin repository

$ git push origin HEAD

Make and Publish Custom Changes in Origin Repository

Checkout X.Y-next branch and get last origin changes

$ git checkout 10.2-next
$ git pull --rebase

Make changes and locally commit them

$ vim foo/bar.c
# Hack, test, hack
$ git add foo/bar.c
$ git commit -m "[bz#42]: Fix this issue/Improve performances"

Once tested, rebase on top of last origin repository changes, and publish

$ git pull --rebase
$ git push origin HEAD

Merge Errata/Security Patches from Upstream

  • Note: No Operating System is without sins, thus you need to merge Errata/Security patches from corresponding release branch in a timely manner

Checkout X.Y-next branch and get last origin changes

$ git checkout 10.2-next
$ git pull --rebase

Get last upstream changes and check the log for Errata/Security details

$ git fetch upstream
$ git log upstream/releng/10.2

Merge last upstream changes from corresponding release branch

$ git merge upstream/releng/10.2 -m "Merge Errata/Security from releng/10.2 into 10.2-next"

Resolve conflicts if any, than check the result

$ git log -p -m --first-parent

Publish merged upstream changes in origin

$ git push origin HEAD

Next you can update FreeBSD release number in release/Makefile and create your own tag for release/testing purpose. See below.

$ git tag -a v10.2.4.0 -m "My FreeBSD Release 10.2.4.0"
$ git push --tags
$ git checkout -t tags/v10.2.4.0

Rebase Custom Changes onto a New Release Branch

Get all origin and upstream repositories changes. For example to rebase your changes made in 10.1-next to 10.2-next

$ git fetch upstream
$ git fetch origin
$ git checkout 10.1-next
$ git pull --rebase
$ git checkout 10.2-next
$ git pull --rebase

Start an interactive rebase for all changes made in X.Y to X.(Y+1)

$ git rebase -i --onto 10.2-next upstream/release/10.1.0 10.1-next
  • Note: Rebase is smart/dumb enough to skip all already accepted included the new X.(Y+1)-next branch
  • Note: Rebase will skip all Errata/Security merge commits, this is the default behaviour and that you actually want as all Errata/Security changes are already in X.(Y+1)-next branch by definition of a FreeBSD release branch

During the interactive rebase you have in opportunity to:

  • Remove now irrelevant changes
  • Squash changes related to same fix/feature implementation in only one commit:
    • Make things easier for future rebases
    • Make history easier to read
    • Cleaner patch for upstream proposal
  • Re-order your changes

This is different workflow than the classical SVN vendor model merge workflow, here we want to see our changes always on top of the last release branch:

  • Custom changes will appear clearly
  • Custom changes will be on top the last release version, and be easier to propose them to upstream

Advantages/Disadvantages

  • Use of last release branch for stability
  • Custom changes/fixed are used/tested in production before review
  • No need to wait upstream acceptation before enjoying fixes and improvements
  • These changes make great candidates for MFC (Merge From Current) once accepted in CURRENT
  • Keep patches clean over new release branches
  • The origin repository includes only the branches you are working on/you care about. It is not a full complete fork of the upstream repository
  • Interface nicely with FreeBSD reviews (Phabricator/arc) (see below)
  • Development is not done in CURRENT
  • Patches are “up-ported” to CURRENT once tested/have matured enough
  • Patches are in two branches until accepted:
    • X.Y-next (Release branch)
    • feature-review (Branch for upstream review) (see below)

More Usages Examples

Checkout last changes from upstream/master

$ git fetch upstream
$ git checkout master
$ git pull --rebase

Create review branch

$ git checkout -b feature-foo-review master
$ git push -u origin HEAD # It creates the base commit for the review

Cherry-pick changes related to “feature foo” from X.Y-next branch

$ git log origin/10.2-next # Note SHA strings of desired commits
$ git cherry-pick $SHA1 $SHA2

and create the review

$ arc which # Check that commit $SHA1 and $SHA2 will be part of the review
$ arc diff --create # Create review D1234

If during review changes are required, local commit the desired changes and include them in the review

$ vim foo/bar.c
# Hack, test, hack
$ git add foo/bar.c
$ git commit -m "Address comments from review D1234"
$ arc which # Check that all desired commits are part of the review
$ arc diff --update D1234 

If the review takes a while, you can rebase your changes on top of the current master and update the review.

First get last upstream changes

$ git checkout master
$ git pull --rebase

Then rebase your changes on it

$ git checkout feature-foo-review
$ git rebase master

And update the review

$ git push origin master:feature-foo-review # Update the review base commit
$ arc which # Check that the review includes all desired commit changes, and only them
$ arc diff --update D1234

Note: Sometimes You might want to get a change from CURRENT to your X.Y-next branch

Checkout X.Y-next branch and get last origin changes

$ git checkout 10.2-next
$ git pull --rebase

Get last upstream changes and check the log for the SHA of the desired commit(s) to cherry-pick

$ git fetch upstream
$ git log upstream/master

Cherry-pick desired changes from upstream/master

$ git cherry-pick SHA
  • Note: Where SHA is the SHA string of the commit to cherry-pick

Resolve conflicts and check result

$ git log -p

Publish cherry-picked changes to origin repository

$ git pull --rebase
$ git push origin HEAD
  • gitworkflow/triangularworkflow.txt
  • Last modified: 2015/09/14 20:34
  • by JulienCharbon