#automation #cli #developer-tools #git #productivity

bin+lib repo-cli

A sane way to manage all of your git repositories

4 releases

0.1.3 Nov 24, 2021
0.1.2 May 13, 2020
0.1.1 Apr 19, 2020
0.1.0 Apr 18, 2020

#241 in Command line utilities

29 downloads per month
Used in commit-email

Apache-2.0

170KB
4.5K SLoC

Rust 3.5K SLoC // 0.0% comments Zsh 458 SLoC BASH 307 SLoC // 0.0% comments

Repo

Continuous Integration Dependabot Crates.io Apachie 2.0

Repo is a command line repository management tool written in rust. Track your remote repositories with repo and manage your workspace.

demo

Table of Contents

Click here to show

Installation

Install the latest released version of repo from crates.io with cargo. If you don't have a rust environment setup check the rust book's setup chapter.

cargo install repo-cli

This will install repo in your default cargo path $CARGO_HOME/bin/repo. Once repo is in your path, the work helper function and completion needs to be sourced in order to let repo change your shell's cwd. The work command has fzf integration. If you have fzf installed then add --fzf option to init.

Bash

# ~/.bashrc
[ -x "$(command -v repo)" ] && eval "$(repo init bash)"

# With `fzf` integration
[ -x "$(command -v repo)" ] && {
    [ -x "$(command -v fzf)" ] && eval "$(repo init bash --fzf)" || eval "$(repo init bash)"
}

Zsh

# ~/.zshrc
[ -x "$(command -v repo)" ] && eval "$(repo init zsh)"

# With `fzf` integration
[ -x "$(command -v repo)" ] && {
    [ -x "$(command -v fzf)" ] && eval "$(repo init zsh --fzf)" || eval "$(repo init zsh)"
}

Fish

# ~/.config/fish/config.conf
test -x $(command -v repo) && repo init fish | source

# With `fzf` integration
test -x $(command -v repo) && {
    test -x $(command -v fzf) && repo init fish --fzf | source || repo init fish | source
}

Quick Start

# Track a new remote repository with repo
repo add edeneast/repo

# Create a tag that will repositories into a folk folder
repo tag add fork --path fork --tag fork

# Add your fork of a project
repo add edeneast/cargo --remote 'upstream,rust-lang/cargo' --path 'forks'

# Update workspace by pulling from remote
repo update

# Execute command on all repos. This gets the behind/ahead of a branch relative to its origin
repo foreach 'b=$(git rev-parse --abbrev-ref HEAD) ; git rev-list --left-right --count origin/$b...$b'

# Check if all forks can be fast-forward merged with upstream
repo foreach -t fork 'git merge-base --is-ancestor upstream/master master ; echo $?'

# Run the work command to cd into the repository folder in the workspace
work repo

# Not sure about something... Check the help
repo help

Usage

Dotfiles

Repo stores it's information in a config folder. Repo calls these locations caches. There are two different caches repo uses, global and local.

Location Type Default Path Environment Override
Global $XDG_CONFIG_HOME/repo $REPO_CONFIG_PATH
Local $XDG_DATA_HOME/repo $REPO_LOCAL_PATH

Depending on your operating system the definition of XDG_CONFIG_HOME and XDG_DATA_HOME will be different. Check the links to see the default for your os.

Just like how git allows you to have global and local configuration, repo allows the same flexibility. This means that you can commit your global configuration into your versioned dotfiles and save any local machine only changes. The local cache will override anything in the global cache. This means that you can define things like the root workspace path in your local config and will override the one set globally.

Using the configuration's include and exclude tag filters in your local config you can make sure that one repo's with a tag can be operated on, or vice versa you can exclude any repos that contain a tag. This comes in useful when you use your personal dotfiles on a work machine. Maybe you want to use repo to manage your internal work's repo and you want to filter out your personal repos so they are not accessible on your work machine. You can add a personal tag to all of your personal repos and exclude that tag in your local work's configuration cache. This would filter out all of your personal repos on your work machine making sure that you cant pull anything on your work machine.

Example

# personal computer
repo tag add personal # Add a marker tag to denote that this is a personal repo
repo add my-github/project --tag personal # Defaults to the global config cache
dotfiles add $REPO_CONFIG_PATH # Commit global config to dotfiles
dotfiles commit -m "Add global repo config cachce"

# work machine
repo add https://internal-host.com/org/work --local # Save work to local machine config cache
repo config exclude personal --local # Set repo to exclude repos with personal tag on work machine
repo list # Will only contain the work repo as our personal project is excluded

Components

Repository

A repository represents a project that is hosted on some remote. A repository contains a bunch of optional values that can be set.

Name Type Description
path Path The path relative to the workspace root, the repository location in the workspace
clone String The command that will be executed on the after clone hook
work String The command that will be executed on the after work hook
cli bool A flag to determine if repo should execute git from command line or libgit2
tags TagList The list of tag names associated with the repository
remotes RemoteList The list of remotes for this repository. Note convention that origin is first in list

Example config file

# ~/.config/repo/repository/repo.toml
name = 'repo'
path = 'app'
work = 'echo after work hook'
clone = 'echo after clone hook'
tags = [
  'personal',
  'rust',
]

[[remotes]]
name = 'origin'
url = 'https://github.com/edeneast/repo'

[[remotes]]
name = 'upstream'
url = 'https://github.com/upstream-fork/repo'

Tag

A tag represents values that can be applied to multiple repositories. If you want to reuse configuration values on multiple repositories then create a tag. A tag can also be just for marking a project. For example if the project is a personal project you can create an empty tag and associate it with all your personal projects. You can then filter out personal tags in the config file on machines where you want want personal projects like a work machine.

Name Type Description
path Path The path relative to the workspace root, the repository location in the workspace
clone String The command that will be executed on the after clone hook
work String The command that will be executed on the after work hook
cli bool A flag to determine if repo should execute git from command line or libgit2
priority Number The order in which tags are applied. The lower the number the higher the priority

Example

# ~/.config/repo/tag/rust.toml
name = 'rust'
path = 'rust'
clone = 'cargo fetch'
work = 'cargo check'
priority = 20

Config

As discussed in the dotfiles section, repo stores it's configuration in two main configuration cache locations. There is the global and local config caches. In these cache folder locations there is a config.toml file.

Name Default Description
root $HOME/repo The path relative to the workspace root, the repository location in the workspace.
cli false A flag to determine if repo should execute git from command line or libgit2.
default_host github.com The default host to use if a query is just 'user/repo'
default_scheme https The scheme type of the generated url: [http, https, git, ssh]
default_ssh_user git Default ssh user when generating a url with ssh scheme.
shell bash -c The shell that all external command line calls will use.
include empty A list of tags. Repositories that have these tags will be shown and operated on
exclude empty A list of tags. Repositories that have these tags will be excluded from operations

Example

# ~/.config/repo/config.toml
root = '~/dev/workspace'
cli = false
default_host = 'github.com'
default_scheme = 'ssh'
default_ssh_user = 'git'
shell = [
    'bash',
    '-c',
]
include = ['personal']
exclude = ['work']

Development

repo is currently under development and subject to change before a v1.0 release. Have an idea for repo? Open an issue or fork the project and create a pull request.

Licence

Repo is licenced under Apache Licence (Version 2.0)

See LICENSE file for more details.

Dependencies

~19MB
~447K SLoC