Skip to content

focusate/git-trunk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Test & Deploy

Git Trunk based workflow

Adds git-trunk commands that automates some common git procedures.

Usage: git trunk <command>

Possible commands:

  • init: initialize trunk configuration to be used for other commands.
  • start: create new branch specifying custom name or use patterns to fetch/filter remote branches. First match is used to create local branch.
  • finish: finish active branch by merging it to trunk (then remove it).
  • release: create tag with new release version.
  • refresh: update trunk branch and rebase it on active branch.
  • squash: squash commits on active branch.
  • submodule-update: update submodules.

Code was tested using git version 2.43.2.

Source code in:

Quick Start

For easier use, commands should be called when git repository is your working directory. If you need to call outside working directory, you can use --repo-path argument, where you specify for which repository it should be called.

To know which commands are available, use git trunk -h

To know what arguments are available and what they do for each command, use git trunk <command> -h or git trunk <command> --help

Remote used is identified by your current branch tracking branch remote. If your current branch does not have tracking branch, then trunk branch tracking branch is checked. If trunk branch does not have tracking branch set, then it is assumed no remote is used for git-trunk workflow.

Submodules

All possible commands can be used same way as on main superproject repository. Note configuration is still saved on main superproject repository config (submodules do not have git config file), but it is separated by including submodule relative path on sections. E.g. main repository section is named [trunk], where in submodule case, it is named [trunk "relpath/to/submodule"].

init

init command is used to initialize git trunk configuration that is later reused for other commands. usually it is meant to be called once, where you specify options to set on configuration. Configuration is saved on your repository inside .git/config file. Trunk sections are named trunk.

When using init command, by default it runs in "interactive" mode, where you have to confirm default option values or enter new ones. If you want to specify all options without a prompt, use --no-confirm flag. With this flag, you can specify other argument and it will set without asking you to confirm it.

If you need to change configuration, you can just call init command again by specifying options you want to change. Options not specified, will be assumed that old values must be kept.

start

start command is used to create new branch locally.

Branch that is created, uses your trunk branch as a fork. trunk branch is always rebased from remote trunk before creating new branch (if of course remote is used).

When branch is created using start command, by default it will also try to set upstream for it. To not set upstream, use --no-set-upstream flag when running start command.

If you need to create new branch that is not already on remote, you can use --name argument. It will simply try to create new branch (given it does not exist already) forking from your trunk branch.

If you use system where branches are created on remote automatically (like tasks), you can configure git-trunk to fetch specific branches only that are meant for you. start command will try to fetch the first one (naturally sorting branch names) from remotely existing branches you filtered. If remote branch is already used as tracking branch for existing local branch, such branch is ignored and not used in automatic branch creation.

There are two ways to filter (can be combined):

  • First one is by using fetchbranchpattern option. By default it fetches all available branches from your remote. To limit what is fetched, with init command, for example you can set *-my value for argument --fetch-branch-pattern. With such pattern, it will only fetch branches which names end with -my part. Pattern uses git refspec. With init command, you can change asterisk part, but skeleton remains the same: refs/heads/<pattern>:refs/remotes/<remote>/<pattern>
  • Second can be specified every time you want to create new branch. For that you use --pattern argument when calling git trunk start command. Here you specify regex pattern to further filter branches. This filtering option is used after fetched branches are filtered by refpsec pattern.

finish

finish command is used to finish your temporary branch. In usual case, it is merged into trunk branch, pushed remotely and then remote respective branch is removed alongside local copy.

Currently the only exception is if you use branch that has release prefix (init command argument is --release-branch-prefix). In this case such branch is recognized as release branch. When such branch is finished, it is only deleted, but not meged back into trunk. The reason is that release branches usually should not be merged into trunk.

Branches by default will be merged with --ff-only flag. You can change to --no-ff flag with init command.

release

release command is used to create release tag.

By default version is created using current latest commit on a branch you are on. But it is possible to use specific reference to tag on (with --ref argument).

Also release will be cancelled if there are no new changes after latest tag was created.

Currently there are two possible ways to manage versions:

  • Generic versioning. With generic, you need to manually specify new version every time. For that you use --version argument, where you enter new version.
  • Semver versioning, which uses python semver module as a base to manage version bumping. By default minor part is used, but with --part argument, you can specify other parts semver module currently supports.

It is also possible to specify prefix for version. If prefix is used (it is set with init command), custom version must be specified without prefix, so prefix would not be "duplicated".

Tag default message uses default template, where header line is version name and body is filled with abbreviated commits and their header lines being tagged. By default, tag message is opened for editing before being saved. Can be disabled if needed.

refresh

refresh command is used to update your current branch with new changes from trunk. It can also be used on trunk branch itself.

When you are on working branch, and refresh command is called, your changes are stashed, then branch is changed to trunk, which then is rebased with its tracking branch (if it has upstream). Then branch is changed back to your working one, new trunk changes rebased on your working branch and stashed changes applied (if there were any).

Some other git-trunk commands use refresh command internally to update code before executing command specific actions.

If there are conflicts during refresh, command execution stops and conflicts must be resolved (if stashes were applied, dont forget to reapply them after solving conflicts).

squash

squash command is used to squash multiple commits. Squash can't be done on trunk branch.

Before initiating squash itself, branch is refreshed with newest trunk branch changes, to make sure branch is up to date.

By default it tries to squash all ahead trunk commits into first one. It is possible to specify how many commits to squash with --count argument. Value cant be greater than maximum possible commits to squash on that branch (or actually default count that is used).

By default squash message generated is to concatenate all commit messages (including commit other commits are being squashed into). It is also possible to specify custom commit message, which replaces default message. It is also possible to not specify any message (but then edit mode must be enabled to enter one manually).

By default squash message edit is enabled, which allows to edit tag message before it is saved. Can be disabled if needed.

submodule-update

submodule-update command is used to run submodule updates.

It is possible to manage these options via configuration:

  • pathspec: paths for which submodules to do updates. If left empty, will update all.
  • depth: how many commits to fetch. If its 0, then it will fetch all history normally.
  • single-branch: whether to fetch single default branch.
There is also --cleanup argument when initiating command (not able to set via
configuration). With this option you can do full cleanup of existing local submodules.

Do note that all local changes (that are not saved on remote) will be deleted.

Also if submodules have have been moved around, automatic cleanup might fail. So you might need to do manual cleanup, deleting all submodules where it is currently located and then .git/modules/ content as well.

Testing

To test with newer git, adding submodules from files must be enabled:

git config --global protocol.file.allow always

This is used as a workaround, because setting this on temp tested repo does not work for some reason.

Contributors

  • Andrius Laukavičius (Focusate)