This is an old revision of the document!
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 from
releng/X.Ybranch to newreleng/X.(Y+1)branch
For experimented git users this workflow is only common sense, but might help some to start FreeBSD contributions with a straighforward 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
upstreamrepository are merged - Changes develop in
originrepository 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 upstreamcommand 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/
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. 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
Checkout a X.Y-next Branch
If the X.Y-next is already present in origin repository:
$ git fetch origin $ git checkout -t origin/10.2-next
Make and Publish Custom Changes
Checkout local work branch and get last remote changes
$ git checkout 10.2-next $ git pull --rebase
Make source code 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"
Once tested, rebase on top of last origin repository changes, and publish yours
$ 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
Checkout local work 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 information
$ git fetch upstream $ git log upstream/releng/10.2
Merge last changes from upstream 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 final result
$ git log -p -m --first-parent
Publish merged upstream changes in orign
$ git push origin HEAD
Next you can update FreeBSD release number in release/Makefile and create your private tag for release purpose. See below.
Create Private Tag and Publish it
$ git tag -a v10.2.4.0 -m "My FreeBSD Release 10.2.4.0" $ git push --tags
Checkout a Private Tag
$ 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 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: See https://help.github.com/articles/interactive-rebase documentation
- Note: Rebase is smart enough to skip all already accepted changes the new
X.(Y+1)-nextbranch, i.e. git rebase skips all commit that introduce an exact same change
- Note: Rebase will skip all Errata/Security merge, this is the default git rebase behaviour and that you actually want as all Errata/Security changes you want are already in
X.(Y+1)-nextbranch by definition of a FreeBSD release branch
During the interactive rebase you have in opportunity to:
- Remove now irrelevant changes
- Squash (flatten) 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
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, and for future rebases
Advantages/Disadvantages
Advantages
- Use last release branch for stability
- Custom changes/fixed are used/tested in production first
- No need to wait upstream for fixes and improvements
- These changes make great candidates for MFC (Merge From Current) once accepted in CURRENT
- Keep patches clean over release branches
- The origin repository includes only the branches you are working on/ you care about (it is not a full fork of the upstream repository)
- Interface nicely with FreeBSD reviews (Phabricator/arc)
Disadvantages
- Development is not done in CURRENT first
- Patches are “up-ported” to HEAD once tested/have matured enough
- Patches are in two branches until accepted:
- X.Y-next (Release Branche)
- feature-review (Branch for Patch Proposed to Upstream)
More Usages examples
Cherry-pick Specific Commits from Upstream
Note: You might want sometimes to MFC a change from CURRENT to you X.Y-next branch
Checkout local work 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 commit(s) to cherry-pick
$ git fetch upstream $ git log upstream/master
- Note: One may select any branch from which to cherry pick specific commits.
Cherry-pick 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 commit merge diff
$ git log -p
Publish cherry-picked upstream changes to origin repository
$ git pull --rebase $ git push origin HEAD
Creating a Review for CURRENT from X.Y-next branch
Checkout last changes from upstream/master
$ git fetch upstream $ git checkout -b master upstream/master $ git pull --rebase
Create review branch, and put your changes related to “feature foo” in it, and create the review
$ git checkout -b feature-foo-review master $ git push -u origin HEAD # It creates the base commit for the review $ git log origin/10.2-next # Get SHA strings of desired commits $ git cherry-pick $SHA1 $SHA2 $ arc which # Check that commit $SHA1 and $SHA2 will be part of the review $ arc diff --create
Update your Review with more Changes
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 comment #X from review D1234" $ arc which # Check that all desired commits are part of the review $ arc diff --update D1234
Rebase your Review on more Recent CURRENT
If the review takes a while, you can rebase your changes on top of the current master and update the review.
First get last master changes
$ git checkout master $ git pull --rebase
Then rebase your changes on it
$ git checkout feature-foo-review $ git rebase master $ 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
