Manage workspaces where changes can be spread over several repositories
Each workspace needs a file at its root.
This acts as a marker so that agit
commands can be run
from anywhere in the workspace.
It also stores the initial base state of the repository
to handle the case where the default branch of each repo is different.
This file also contains the saves states of the repositories as differences from the initial state.
agit init
This will initialise a new workspace in the curent working directory. An alternative location can be specified via the -w/--workspace flag for example if you are already in one of the repositories.
agit -w .. init
This flag can also be used for each of the rest of the commands and is equivalent to running the command from the given location.
While working on a change across repositories, it makes sense to create a new branch in each. Saving the branch that each repository is on allows quick switching of multiple repositories at once. To save the current branch of each repository
agit state -c <name of state>
The name can anything, names similar to branch names make sense. To restore a previous state
agit state <name of state>
This will update each repository in turn to restore the branches to the state they were in when it was saved. Note that the branch names are saved not the commits so restoring a state will not necessarily restore files to the state they were in.
Without any state given, the workspace is restored to the initial state.
agit state
Saving the state using the state
command records the branch of each repo. This
means that the state can change as new commits are made to branches. To record
the exact state of the workspace so that it can be returned to the same commits
at any time in future, there is a snapshot
command.
The arguments follow those for the state
command but record commits instead of
branches
To create a new snapshot
agit snapshot -c <name of snapshot>
To return to a previously recorded snapshot
agit snapshot <name of snapshot>
This will return each repo to the commit it was on when the snapshot was created. Note that each repo will be left in a 'head-detached' state as there may no longer be a branch pointing to the relevant commit.
To replace an existing snapshot
agit snapshot -cf <name of snapshot>
These functions are not hugely useful on their own and are mainly intended for use in autocompletion functions.
agit info states
agit info snapshots
agit info root
Changes from gerrit can be checked out by change ID or number.
agit change 12345
will checkout change 12345. This can be run from any repository in the workspace with the change applied to the correct project as required. By default the change will be checked out into a branch named after the change number, but a custom name can be used instead if required.
agit change -b branch_name 12345
will create a new branch named branch_name holding the change from gerrit.
N.B any --state
flag passed to the top level agit
command is ignored when
checking out an individual change.
Gerrit topics allow changes to span multiple repositories and this maps
nicely onto agit
. Given a topic in Gerrit,
agit topic <topic-name>
will checkout the latest change in that topic for each repository and create a new saved state based on it.
As the SSH API offered by Gerrit is limited, it is not always possible to determine which changes to checkout. For instance, if a relation chain of changes has two changes marked with the topic but are not direct descendents of each other, it isn't possible to decide which should be included.
If two unrelated changes share the same topic, it is not possible to checkout the change.
If there are unstaged changes in a repository, it may cause problems checking out the fetched changes. For this reason, it is recommended to apply topics to the workspace when it is in a clean state.
Any command that is not recognised by agit is assumed to be a git command and is run in each repository in turn. eg
agit pull origin --ff-only
is equivalent to running
git pull origin --ff-only
in each repository. If any command fails, the later ones are not affected. As this is just running the git command as a sub process, all your standard git aliases will work as expected. One caveat to this is that if you have an alias that matches a subcommand, you will not be able to call it. Calling the command that it is aliased to will still work.
The external command will have an $AGIT_WORKSPACE
environment variable set so
that git extension scripts can be aware that they are being run as part of an
agit command if they need to.
There are two configuration entries required for agit
to be used.
agit.user
: the user name of the Gerrit user to authenticate with Gerritagit.gerrit-host
: The Gerrit hostname used to query topics
These should be added to the normal git config via
git config --global agit.user UserName
git config --global agit.gerrit-host ssh://gerrit.example.com:12345
Additionally, if the SSH key used for gerrit is not the default id_rsa{,.pub} pair, a third configuration entry can be used to specify the key to use:
git config --global agit.key-file /path/to/key
Completions are available and can be generated using the completions
command.
Zsh requires a script named _agit
to provide completion options in a directory
included in the fpath
variable. This can be set up in .zshrc
via something
like fpath+=${ZSH}/completions/
.
The completion function can be generated when required:
agit completions zsh > ~/${ZSH}/completions/_agit
compinit
is then required although this is often already called during
start up.
Bash uses a completion function that can be sourced at startup in .bashrc
source <(agit completion bash)
Running and building locally requires rust.
cargo build --release
It can be run directly from source via cargo run
. When passing arguments,
--
is required. Often it is useful to combine this with the -w
flag to
run in a different directory, eg
cargo run -- -w /path/to/workspace topic <topic>
- Peter Holloway - peter.holloway@diamond.ac.uk