Make sure you read the section Getting started before the rest so you are aware of how the flow is supposed to work.
Just run npm i -g gut-flow. You're all set!
This package hasn't been released to npmjs.org because it's not stable enough at the moment. It'll be released soon but in the meantime, you can try it out by cloning the repository and running npm link at the top-level.
Some features gut provides change the terminal's directory or maintain variables that should have the same life span as the terminal.
It was not possible to implement those in pure NodeJS so some features are implemented in bash. You can find the list of available shell scripts in the folder shell.
To use these features, run gut install and paste the following code to your .bashrc:
# Installation of Gut scripts, see https://github.com/quilicicf/Gut/blob/master/specs/user_documentation.md#shell-features
# If the link is broken, you probably want to read the README again https://github.com/quilicicf/Gut/blob/master/README.md
installGutScripts() {
local script
test -d ~/.config/gut && {
while read script; do
. "$script"
done <<< "$(find ~/.config/gut -name '*.sh')"
}
}
installGutScriptsGut keeps a configuration file in ~/.config/gut/config.json.
You'll be guided to build this file when you run any gut command if it does not exist.
To change the configuration, run gut configure, it is recommended not to update the file by hand.
Contents of the file:
{
"accounts": {
"github": {
"username": "your GitHub username",
"pullRequestToken": "your OAuth 2.0 token for creating pull requests"
}
},
"repositoriesPath": "The path to your folder containing git repositories. Yes it's assumed all are in one place!",
"preferredGitServer": "The git server you are using, only github supported ATM"
}For preferredGitServer the only git server supported at the time is github. Other servers will potentially be
added - as well as the possibility to configure yours - in the future.
Gut will search for a file named .gut-config.json at the root of your repositories to retrieve the repository-specific configuration. This file is supposed to be committed and shared among developers. It should never contain something you don't want to be online.
Contents of the file:
{
"ci": {
"<CI tool name>": {
"<job name>": {
"server": "the tool's server name",
"uri": "the job's URI, relative to the selected server's URI",
"body": "the body that should be POSTed to the job's URI"
}
}
},
"commitMessageSuffixTemplate": "Template of the suffix that should be added to your commit messages",
"reviewTool": "Name of the review tool (only github supported ATM)"
}Example of configuration:
{
"ci": {
"jenkins": {
"build": {
"server": "personal",
"uri": "/jobs/gut",
"body": {
"branch_or_tag": "$currentBranch"
}
}
}
},
"commitMessageSuffixTemplate": "#$ticketNumber",
"reviewTool": "github"
}ci: contains the jobs configuration of your CI tools<CI tool name>: the name of the CI tool. Onlyjenkinsis supported ATM.<job name>: configure your repository's jobs here.server: the name of the server to use. The server configuration will be retrieved by this name in your global configuration. This allows you to share your repository configurations without putting the URLs to your CI tool on the internet.uri: the job's URI, relative to the URI of your server.body: the JSON body that will be POSTed to the job's URI. See the ci command for more information.
commitMessageSuffixTemplate: when committing on a branch that contains a ticket number, gut will look for the suffix template. If a suffix is found, the template will be used to suffix the commit message, replacing$ticketNumberwith the actual ticket number, retrieved from the branch name (see branch naming).reviewTool: the review tool to be used for this repository. Onlygithubis supported ATM.
It is assumed you'll keep all your repositories into a single folder, which will be named forge in the rest of this document and is structured like the following.
forge
├── github
│ ├── owner1
│ │ ├── repo1
│ │ └── repo2
│ └── owner2
│ ├── repo1
│ └── repo2
└── gitlab
├── owner1
│ ├── repo1
│ └── repo2
└── owner2
├── repo1
└── repo2
Branch types:
- Master: The branch
masteris a branch that strictly follows the production. It is therefore a faithful representation of what's in production at ANY MOMENT - Version branches: When starting the development of a version, a branch is created from master.
- Feature branches: A version can contain multiple features. In case two or more developers work on a feature, they can create a branch from the version branch. To allow for scope adjustment, the feature can be merged in the next version if need be.
- Dev branches: When working on a ticket, a dev creates a branch from the feature or version branch.
The following rules apply to the branches:
- It is allowed to force-push on branches that are only used by a single developer (to create a clean history).
- As soon as two developers start working on the same branch, force-push is prohibited (I'll implement safe-guards but that's a little further down the roadmap).
- To have a clean history, the rebase is preferred to update the version/feature/dev branches to the last modifications. They should be done when there's the fewest branches open and the branch that's to be rebased must be duplicated first of course (there'll be tooling down the roadmap for that too).
- The rebase-and-merge feature is to be preferred when merging branches down.
- Delivery to the QA team is done y creating a tag named as a time stamp (ISO 8601)
- When the QA validates a tag, it is merged into master, then production tag is created and named
v<full version> - Build
- All version branches and master should be built every time their source code changes
- Feature branches can specify they should be built by adding
buildbefore the# - Dev branches should be built when the PR is done or on-demand (a feature is coming to make the on-demand part a
- command away
Benefits of this flow:
- there is a branch that follows the production so it's easy to know what's in prod and debug it
- the history is linear and really easy to read
- forgetting to merge something seldom happens
- even if the rebase was not done on alive branches after a merge to master, there should never be devs lost in translation
Attention points:
- the tag that goes to production is not exactly the tag validated by the QA. If the merge is not smooth, the QA might need to re-check things
- when a tag is merged into production, all live branches must be rebased
- Version branches:
<major version>.<minor version>.<patch version>ex:2.3.19 - Feature branches:
<full version>_#<feature>ex:2.3.19_#whatsNewDialog - Dev branches:
<full version>_#<feature>_<ticket number>_<dev>ex:2.3.19_#whatsNewDialog_8495_optOutor if there's no feature branch2.3.19_456_noLogsBug
Benefits of this naming:
- No need to look at the commit tree to find where a dev started
- Easy to spot if a branch is not rebased to the right origin (merging
1.2.2_123_totoFeaturein1.3.0should raise an alarm in your head) - Easy to clean the old local branches, just filter them with regex (there's gonna be a utility for that)
- Easy to interact with CI/CD, the branch is parsable, the ticket number easy to retrieve
Commit messages should be suffixed with the ticket number so that your bug tracker/CI/CD can track them and associate the commit to the ticket.
In GitHub, you can suffix your commit message with #<ticket number> and GitHub will reference the commit in the
issue.
In JIRA, you can suffix the commit message with (<project id>-<ticket number>) to get the same result.
The features in this section are mostly syntactic sugar over existing git features. You might wonder why their names are poor homonyms of the git features they replace. It's simply because git and gut are really close to one another and easily mistyped. The changed names make it clearer what you are using.
Usage: gut audit.
Inspects a git diff and displays a summary. Displayed items are:
- Lines added/removed
- Oddities found in the added code
- TODO
- FIXME
- Abusive printing (console.log in JS, System.out.print in Java)
- Local paths (looks for your home directory)
Arguments:
-ninspect the n last commits (exclusive with -f and -t)-fthe commit from which to start the diff-tthe commit where the diff ends
Example output:
Usage: gut burgeon -v 2.10.0
Creates a new branch and checks it out.
Arguments:
-vcreate a new version branch, the value of the parameter is the version (follows semver). You can only create a version branch from master or another version branch.-fcreate a new feature branch, the value of the parameter is the feature's description. It can't contain an underscore. You can only create a feature branch from master or a version branch.-ionly usable with-f. If set, the feature branch will be built each time your commit on the branch.-dcreate a new dev branch, the value of the parameter is the dev's description. It can't contain an underscore. You can create dev branches from every type of branches but dev branches.-nonly usable with-d. The ticket number associated with the dev.
Examples:
gut burgeon -v 2.35.9(called frommaster) creates a version branch named2.35.9gut burgeon -f myFeature -i(called from2.35.9) creates a feature branch named2.35.9_build#myFeaturegut burgeon -d myDev -n 123(called from2.35.9_build#myFeature) creates a dev branch named2.35.9_build#myFeature_123_myDev
Usage: gut divisions -r o.
Displays the branches on a specific remote. The parameter r is the name of the remote or all to show all branches. There are a few shortcuts to go faster:
- a stands for all
- l stands for local
- o stands for origin
- u stands for upstream
If the parameter is omitted, only the local branches are shown.
Usage: gut execute -m <message>.
Creates a commit with the provided message.
Arguments:
-m: The commit message. It will be automatically suffixed with the ticket number if available (in the branch name) and the repository is configured (see Repository configuration file) withcommitMessageSuffixTemplate. The commit message is an array, you don't need to quote it (see examples).-c: Creates a code review commit, the message is set to:eyes: Code review, suffixed with the ticket number if applicable. Mutually exclusive with-m
Examples:
gut execute -m :memo: Specify better commit messageswill create a commit with a message set to:memo: Specify better commit messages. Note: you will need to quote it if you have a word that begin with-in the commit message, otherwise it will be seen as a parameter to the gut command.gut execute -m ':memo: Specify better commit messages'will create a commit with a message set to:memo: Specify better commit messages.gut execute -cwill create a commit with a message set to:eyes: Code review.
The commit should fail if the user has unstaged changes.
Usage: gut history.
Displays commits history (equivalent to git log).
Arguments:
-fformat, the format in the list of predefined formats (see list below, defaults topretty)-sskip the n first commits in the history (defaults to 0)-nshows only n commits (default to 100)-rreverses the order in which the commits are shown. If not specified, the commits will be displayed from newest to oldest.
Available formats:
pretty: a colored and well indented format, see screenshot belowjson: the commits are returned as a JSON arraysha: only the shas are returned. Very useful when used with reverse to cherry-pick a few commits!
Log format pretty:
Usage: gut obliterate -b master_deleteSpec -r o
Deletes an item on the specified remote. Can delete branches and tags.
Arguments:
-rThe remote where the item should be deleted, defaults tolocal. Can be:- local: if not defined or in
['l', 'local']) - origin: if in
['o', 'origin'] - upstream: if in
['u', 'upstream']
- local: if not defined or in
-bThe name of the branch to delete. Exclusive with-t-tThe name of the tag to delete. Exclusive with-b
Examples:
gut obliterate -b master_deleteSpec: deletes the branchmaster_deleteSpeclocally. Literally doesgit branch -D master_deleteSpecgut obliterate -t v1.2.3 -r odeletes the tagv1.2.3onorigin. Literally doesgit push --delete origin v1.2.3
Usage: gut pile.
Adds all the changes in the repository. Literally does git add <repository top level> -A.
Usage: pushb <branch name>; do things; popb
Works like pushd and popd but for GitHub branches.
Note: This feature is implemented in bash, it requires some specific installation steps.
Usage: gut replicate -s server -o owner -r repo.
Clones the repository in <forge>/<server>/<owner>/<repo>.
If you omit the server, the preferredGitServer from your configuration file will be used.
If you omit the owner, the username from your configuration file will be used.
Usage: gut switch -t <target branch>.
Checks out a branch.
Arguments:
-ttarget branch, if it exists-rregex to be used to search for the branch to check out-nsearch the branch by ticket number-mswitch to master-vswitch to the version branch-fswitch to the feature branch-bswitch to the base branch
Examples:
gut switch -t masterswitches to branchmastergut switch -r myDevwould match branch9.1.6_2345_myDevand check it out if it were the only matchgut switch -n 2345would match branch9.1.6_2345_myDevand check it out if it were the only matchgut switch -mwould switch tomastergut switch -von branch2.11.0_#myFeaturewould switch to2.11.0gut switch -fon branch2.11.0_#myFeature_123_myDevwould switch to2.11.0_#myFeaturegut switch -bon branch2.11.0_#myFeaturewould switch to2.11.0gut switch -bon branch2.11.0_#myFeature_123_myDevwould switch to2.11.0_#myFeature
Usage: gut thrust.
Pushes changes to the remote and sets the branches upstream to <remote>/<branchName>.
The user can always change the remote to push to but he must do it the first time he pushes a branch if there's more
than one remote configured.
Arguments:
-rremote, the remote to push to
Usage: gut undo -n 2.
Undoes the last n commits.
Arguments:
-ncommits number, the number or commits to undo-sstash, stashes the changes-ddescription, use withstash, stashes the changes with the given description as stash item name-hhard, erases the changes, a confirmation is shown to prevent unwanted data loss
The features in this section are the most powerful in gut. They allow you to configure your git flow precisely and to integrate with the tools you are using in your everyday life.
Usage: gut ci
Allows you to run CI jobs on your repository from the command line.
Configure the jobs for your repository in the repository configuration file. Make sure to add the CI server/account in your Gut configuration file.
When you run the command, it will either run the job if it's alone or display the list of existing jobs and ask you which one should be run.
Global configuration file (personal file):
{
"accounts": {
"jenkins": {
"username": "quilicicf",
"password": "tititatatoto"
}
},
"tools": {
"jenkins": {
"servers": {
"personal": "https://jenkins.quilicicf.fr",
"company": "https://jenkins.mycompany.com"
}
}
}
}Repository configuration file (shared via git):
{
"ci": {
"jenkins": {
"build": {
"server": "personal",
"uri": "/jobs/gut/build",
"body": {
"branch_or_tag": "$currentBranch"
}
}
}
}
}Usage: gut pr
Creates a pull-request on the tool of your choice (only GitHub implemented as of today). An audit of the commits added from the base branch is performed before anything else.
The review tool must be configured in the repository configuration file. A valid OAuth 2.0 token must be set in the Gut configuration file. You can create the token here, please note these tokens should not be used for multiple usages.
Global configuration file (personal file):
{
"accounts": {
"github": {
"username": "quilicicf",
"pullRequestToken": "tititatatoto"
}
}
}Repository configuration file (shared via git):
{
"reviewTool": "github"
}
