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:
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.
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
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
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, withinit
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. Withinit
command, you can changeasterisk
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 callinggit trunk start
command. Here you specifyregex
pattern to further filter branches. This filtering option is used after fetched branches are filtered by refpsec pattern.
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
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 defaultminor
part is used, but with--part
argument, you can specify other partssemver
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
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
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
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.
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)