summaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md356
1 files changed, 267 insertions, 89 deletions
diff --git a/README.md b/README.md
index d6efa14..79c6009 100644
--- a/README.md
+++ b/README.md
@@ -14,67 +14,122 @@
| | ____ | | | | | ___ |
| | \_ ) | | | | | ( ) |
| (___) |__) (___ | | | ) ( |
-(_______)_______/ )_( |/ \| v0.10
+(_______)_______/ )_( |/ \| v0.16
```
# Gita: a command-line tool to manage multiple git repos
-This tool does two things
+This tool has two main features
- display the status of multiple git repos such as branch, modification, commit message side by side
-- (batch) delegate git commands/aliases from any working directory
-
-If several repos are related, it helps to see their status together too.
-I also hate to change directories to execute git commands.
+- (batch) delegate git commands/aliases and shell commands on repos from any working directory
![gita screenshot](https://github.com/nosarthur/gita/raw/master/doc/screenshot.png)
-Here the branch color distinguishes 5 situations between local and remote branches:
-
-- white: local has no remote
-- green: local is the same as remote
-- red: local has diverged from remote
-- purple: local is ahead of remote (good for push)
-- yellow: local is behind remote (good for merge)
+In this screenshot, the `gita ll` command displays the status of all repos.
+The `gita remote dotfiles` command translates to `git remote -v`
+for the `dotfiles` repo, even though we are not in the repo.
+The `gita fetch` command fetches from all repos and two of them have updates.
+To see the pre-defined commands, run `gita -h` or take a look at
+[cmds.json](https://github.com/nosarthur/gita/blob/master/gita/cmds.json).
+To add your own commands, see the [customization section](#custom).
+To run arbitrary `git` command, see the [superman mode section](#superman).
+To run arbitrary shell command, see the [shell mode section](#shell).
+
+I also made a youtube video to demonstrate the common usages
+[![Img alt text](https://github.com/nosarthur/gita/raw/master/doc/video-outline.png)](https://www.youtube.com/watch?v=ySWbwQcbhqI)
+
+The branch color distinguishes 5 situations between local and remote branches:
+
+color | meaning
+---|---
+ white| local has no remote
+ green| local is the same as remote
+ red| local has diverged from remote
+ purple| local is ahead of remote (good for push)
+ yellow| local is behind remote (good for merge)
The choice of purple for ahead and yellow for behind is motivated by
[blueshift](https://en.wikipedia.org/wiki/Blueshift) and [redshift](https://en.wikipedia.org/wiki/Redshift),
using green as baseline.
+You can change the color scheme using the `gita color` command.
+See the [customization section](#custom).
The additional status symbols denote
-- `+`: staged changes
-- `*`: unstaged changes
-- `_`: untracked files/folders
+symbol | meaning
+---|---
+ `+`| staged changes
+ `*`| unstaged changes
+ `?`| untracked files/folders
The bookkeeping sub-commands are
-- `gita add <repo-path(s)>`: add repo(s) to `gita`
-- `gita rm <repo-name(s)>`: remove repo(s) from `gita` (won't remove files from disk)
-- `gita group`: show grouping of the repos
-- `gita group <repo-name(s)>`: group repos
-- `gita ungroup <repo-name(s)>`: remove grouping for repos
+- `gita add <repo-path(s)> [-g <groupname>]`: add repo(s) to `gita`, optionally into an existing group
+- `gita add -a <repo-parent-path(s)>`: add repo(s) in <repo-parent-path(s)> recursively
+ and automatically generate hierarchical groups. See the [customization section](#custom) for more details.
+- `gita add -b <bare-repo-path(s)>`: add bare repo(s) to `gita`. See the [customization section](#custom) for more details on setting custom worktree.
+- `gita add -r <repo-parent-path(s)>`: add repo(s) in <repo-parent-path(s)> recursively
+- `gita clear`: remove all groups and repos
+- `gita clone <URL>`: clone repo from `URL` at current working directory
+- `gita clone <URL> -C <directory>`: change to `directory` and then clone repo
+- `gita clone -f <config-file>`: clone repos in `config-file` (generated by `gita freeze`) to current directory.
+- `gita clone -p -f <config-file>`: clone repos in `config-file` to prescribed paths.
+- `gita context`: context sub-command
+ - `gita context`: show current context
+ - `gita context <group-name>`: set context to `group-name`, all operations then only apply to repos in this group
+ - `gita context auto`: set context automatically according to the current working directory
+ - `gita context none`: remove context
+- `gita color`: color sub-command
+ - `gita color [ll]`: Show available colors and the current coloring scheme
+ - `gita color reset`: Reset to the default coloring scheme
+ - `gita color set <situation> <color>`: Use the specified color for the local-remote situation
+- `gita flags`: flags sub-command
+ - `gita flags set <repo-name> <flags>`: add custom `flags` to repo
+ - `gita flags [ll]`: display repos with custom flags
+- `gita freeze`: print information of all repos such as URL, name, and path. Use with
+ `gita clone`.
+- `gita group`: group sub-command
+ - `gita group add <repo-name(s)> -n <group-name>`: add repo(s) to a new or existing group
+ - `gita group [ll]`: display existing groups with repos
+ - `gita group ls`: display existing group names
+ - `gita group rename <group-name> <new-name>`: change group name
+ - `gita group rm <group-name(s)>`: delete group(s)
+ - `gita group rmrepo <repo-name(s)> -n <group-name>`: remove repo(s) from existing group
+- `gita info`: info sub-command
+ - `gita info [ll]`: display the used and unused information items
+ - `gita info add <info-item>`: enable information item
+ - `gita info rm <info-item>`: disable information item
- `gita ll`: display the status of all repos
- `gita ll <group-name>`: display the status of repos in a group
+- `gita ll -g`: display the repo summaries by groups
- `gita ls`: display the names of all repos
- `gita ls <repo-name>`: display the absolute path of one repo
- `gita rename <repo-name> <new-name>`: rename a repo
-- `gita info`: display the used and unused information items
+- `gita rm <repo-name(s)>`: remove repo(s) from `gita` (won't remove files on disk)
- `gita -v`: display gita version
-Repo paths are saved in `$XDG_CONFIG_HOME/gita/repo_path` (most likely `~/.config/gita/repo_path`).
-
-The delegating sub-commands are of two formats
+The `git` delegating sub-commands are of two formats
- `gita <sub-command> [repo-name(s) or group-name(s)]`:
- optional repo or group input, and no input means all repos.
+ optional repo or group input, and **no input means all repos**.
- `gita <sub-command> <repo-name(s) or groups-name(s)>`:
required repo name(s) or group name(s) input
-By default, only `fetch` and `pull` take optional input.
+They translate to `git <sub-command>` for the corresponding repos.
+By default, only `fetch` and `pull` take optional input. In other words,
+`gita fetch` and `gita pull` apply to all repos.
+To see the pre-defined sub-commands, run `gita -h` or take a look at
+[cmds.json](https://github.com/nosarthur/gita/blob/master/gita/cmds.json).
+To add your own sub-commands or override the default behaviors, see the [customization section](#custom).
+To run arbitrary `git` command, see the [superman mode section](#superman).
+
+If more than one repos are specified, the `git` command runs asynchronously,
+with the exception of `log`, `difftool` and `mergetool`,
+which require non-trivial user input.
-If more than one repos are specified, the git command will run asynchronously,
-with the exception of `log`, `difftool` and `mergetool`, which require non-trivial user input.
+Repo configuration global is saved in `$XDG_CONFIG_HOME/gita/repos.csv`
+(most likely `~/.config/gita/repos.csv`) or if you prefered at project configuration add environment variable `GITA_PROJECT_HOME`.
## Installation
@@ -84,22 +139,21 @@ To install the latest version, run
pip3 install -U gita
```
-If development mode is preferred,
-download the source code and run
+If you prefer development mode, download the source code and run
```
pip3 install -e <gita-source-folder>
```
In either case, calling `gita` in terminal may not work,
-then you can put the following line in the `.bashrc` file.
+then put the following line in the `.bashrc` file.
```
alias gita="python3 -m gita"
```
-Windows users may need to enable the ANSI escape sequence in terminal, otherwise
-the branch color won't work.
+Windows users may need to enable the ANSI escape sequence in terminal for
+the branch color to work.
See [this stackoverflow post](https://stackoverflow.com/questions/51680709/colored-text-output-in-powershell-console-using-ansi-vt100-codes) for details.
## Auto-completion
@@ -108,11 +162,11 @@ Download
[.gita-completion.bash](https://github.com/nosarthur/gita/blob/master/.gita-completion.bash)
or
[.gita-completion.zsh](https://github.com/nosarthur/gita/blob/master/.gita-completion.zsh)
-and source it in the .rc file.
+and source it in shell.
-## Superman mode
+## <a name='superman'></a> Superman mode
-The superman mode delegates any git command/alias.
+The superman mode delegates any `git` command or alias.
Usage:
```
@@ -126,66 +180,192 @@ For example,
- `gita super frontend-repo backend-repo commit -am 'implement a new feature'`
executes `git commit -am 'implement a new feature'` for `frontend-repo` and `backend-repo`
-## Customization
+## <a name='shell'></a> Shell mode
+
+The shell mode delegates any shell command.
+Usage:
+
+```
+gita shell [repo-name(s) or group-name(s)] <any-shell-command>
+```
+
+Here `repo-name(s)` or `group-name(s)` are optional, and their absence means all repos.
+For example,
+
+- `gita shell ll` lists contents for all repos
+- `gita shell repo1 repo2 mkdir docs` create a new directory `docs` in `repo1` and `repo2`
+- `gita shell "git describe --abbrev=0 --tags | xargs git checkout"`: check out the latest tag for all repos
+
+## <a name='custom'></a> Customization
+
+### define repo group and context
+
+When the project contains several independent but related repos,
+we can define a group and execute `gita` command on this group.
+For example,
+
+```
+gita group add repo1 repo2 -n my-group
+gita ll my-group
+gita pull my-group
+```
+
+To save more typing, one can set a group as context, then any `gita` command
+is scoped to the group
+
+```
+gita context my-group
+gita ll
+gita pull
+```
+
+The most useful context maybe `auto`.
+In this mode, the context is automatically determined from the
+current working directory (CWD): the context is the group whose member repo's
+path contains CWD. To set it, run
+
+```
+gita context auto
+```
+
+To remove the context, run
+```
+gita context none
+```
+
+It is also possible to recursively add repos within a directory and
+generate hierarchical groups automatically. For example, running
+
+```
+gita add -a src
+```
+on the following folder structure
+```
+src
+├── project1
+│   ├── repo1
+│   └── repo2
+├── repo3
+├── project2
+│   ├── repo4
+│   └── repo5
+└── repo6
+```
+gives rise to 3 groups:
+```
+src:repo1,repo2,repo3,repo4,repo5,repo6
+src-project1:repo1,repo2
+src-project2:repo4,repo5
+```
+
+### add user-defined sub-command using json file
-Custom delegating sub-commands can be defined in `$XDG_CONFIG_HOME/gita/cmds.yml`
-(most likely `~/.config/gita/cmds.yml`).
+Custom delegating sub-commands can be defined in `$XDG_CONFIG_HOME/gita/cmds.json`
+(most likely `~/.config/gita/cmds.json`)
And they shadow the default ones if name collisions exist.
Default delegating sub-commands are defined in
-[cmds.yml](https://github.com/nosarthur/gita/blob/master/gita/cmds.yml).
+[cmds.json](https://github.com/nosarthur/gita/blob/master/gita/cmds.json).
For example, `gita stat <repo-name(s)>` is registered as
-```yaml
-stat:
- cmd: diff --stat
- help: show edit statistics
+```json
+"stat":{
+ "cmd": "git diff --stat",
+ "help": "show edit statistics"
+}
```
-which executes `git diff --stat`.
+which executes `git diff --stat` for the specified repo(s).
+
+To disable asynchronous execution, set `disable_async` to be `true`.
+See the `difftool` example:
-If the delegated git command is a single word, the `cmd` tag can be omitted.
-See `push` for an example.
-To disable asynchronous execution, set the `disable_async` tag to be `true`.
-See `difftool` for an example.
+```json
+"difftool":{
+ "cmd": "git difftool",
+ "disable_async": true,
+ "help": "show differences using a tool"
+}
+```
-If you want a custom command to behave like `gita fetch`, i.e., to apply
-command to all repos if nothing is specified,
-set the `allow_all` option to be `true`.
+If you want a custom command to behave like `gita fetch`, i.e., to apply to all
+repos when no repo is specified, set `allow_all` to be `true`.
For example, the following snippet creates a new command
`gita comaster [repo-name(s)]` with optional repo name input.
-```yaml
-comaster:
- cmd: checkout master
- allow_all: true
- help: checkout the master branch
+```json
+"comaster":{
+ "cmd": "checkout master",
+ "allow_all": true,
+ "help": "checkout the master branch"
+}
+```
+
+Any command that runs in the [superman mode](#superman) mode or the
+[shell mode](#shell) can be defined in this json format.
+For example, the following command runs in shell mode and fetches only the
+current branch from upstream.
+
+```json
+"fetchcrt":{
+ "cmd": "git rev-parse --abbrev-ref HEAD | xargs git fetch --prune upstream",
+ "allow_all": true,
+ "shell": true,
+ "help": "fetch current branch only"
+}
```
-Another customization is the information items displayed by `gita ll`.
-The used and unused information items are shown with `gita info` and one can
-create `$XDG_CONFIG_HOME/gita/info.yml` to customize it. For example, the
-default information items setting corresponds to
+### customize the local/remote relationship coloring displayed by the `gita ll` command
+
+You can see the default color scheme and the available colors via `gita color`.
+To change the color coding, use `gita color set <situation> <color>`.
+The configuration is saved in `$XDG_CONFIG_HOME/gita/color.csv`.
+
+### customize information displayed by the `gita ll` command
+
+You can customize the information displayed by `gita ll`.
+The used and unused information items are shown with `gita info`, and the
+configuration is saved in `$XDG_CONFIG_HOME/gita/info.csv`.
-```yaml
-- branch
-- commit_msg
+For example, the default setting corresponds to
+
+```csv
+branch,commit_msg,commit_time
+```
+
+Here `branch` includes both branch name and status.
+The status symbols are similar to the ones used in [spaceship-prompt](https://spaceship-prompt.sh/sections/git/#Git-status-git_status).
+
+To customize these symbols, add a file in `$XDG_CONFIG_HOME/gita/symbols.csv`.
+The default settings corresponds to
+
+```csv
+dirty,staged,untracked,local_ahead,remote_ahead,diverged,in_sync,no_remote
+*,+,?,↑,↓,⇕,,∅
```
+Only the symbols to be overridden need to be defined.
+You can search unicode symbols [here](https://www.compart.com/en/unicode/).
-To create your own information items, define a dictionary called `extra_info_items`
-in `$XDG_CONFIG_HOME/gita/extra_repo_info.py`. It should map strings to functions,
-where the strings are the information item names and the functions take repo path
-as input. A trivial example is shown below.
+### customize git command flags
-```python
-def get_delim(path: str) -> str:
- return '|'
+One can set custom flags to run `git` commands. For example, with
-extra_info_items = {'delim': get_delim}
+```
+gita flags set my-repo --git-dir=`gita ls dotfiles` --work-tree=$HOME
```
-If it works, you will see these extra items in the 'Unused' section of the
-`gita info` output. To use them, edit `$XDG_CONFIG_HOME/gita/extra_repo_info.py`.
+any `git` command/alias triggered from `gita` on `dotfiles` will use these flags.
+Note that the flags are applied immediately after `git`. For example,
+`gita st dotfiles` translates to
+
+```
+git --git-dir=$HOME/somefolder --work-tree=$HOME status
+```
+
+running from the `dotfiles` directory.
+
+This feature was originally added to deal with
+[bare repo dotfiles](https://www.atlassian.com/git/tutorials/dotfiles).
## Requirements
@@ -193,11 +373,18 @@ Gita requires Python 3.6 or higher, due to the use of
[f-string](https://www.python.org/dev/peps/pep-0498/)
and [asyncio module](https://docs.python.org/3.6/library/asyncio.html).
-Under the hood, gita uses subprocess to run git commands/aliases.
+Under the hood, gita uses `subprocess` to run git commands/aliases.
Thus the installed git version may matter.
I have git `1.8.3.1`, `2.17.2`, and `2.20.1` on my machines, and
their results agree.
+## Tips
+
+effect | shell command
+---|---
+enter `<repo>` directory|`` cd `gita ls <repo>` ``
+delete repos in `<group>` | `gita group ll <group> \| xargs gita rm`
+
## Contributing
To contribute, you can
@@ -206,27 +393,18 @@ To contribute, you can
- request/implement features
- star/recommend this project
+Read [this article](https://www.dataschool.io/how-to-contribute-on-github/) if you have never contribute code to open source project before.
+
Chat room is available on [![Join the chat at https://gitter.im/nosarthur/gita](https://badges.gitter.im/nosarthur/gita.svg)](https://gitter.im/nosarthur/gita?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-To run tests locally, simply `pytest`.
+To run tests locally, simply `pytest` in the source code folder.
+Note that context should be set as `none`.
More implementation details are in
[design.md](https://github.com/nosarthur/gita/blob/master/doc/design.md).
A step-by-step guide to reproduce this project is [here](https://nosarthur.github.io/side%20project/2019/05/27/gita-breakdown.html).
You can also sponsor me on [GitHub](https://github.com/sponsors/nosarthur). Any amount is appreciated!
-## Contributors
-
-[![nosarthur](https://github.com/nosarthur.png?size=40 "nosarthur")](https://github.com/nosarthur)
-[![mc0239](https://github.com/mc0239.png?size=40 "mc0239")](https://github.com/mc0239)
-[![dgrant](https://github.com/dgrant.png?size=40 "dgrant")](https://github.com/dgrant)
-[![samibh](https://github.com/github.png?size=40 "samibh")](https://github.com/samibh)
-[![wbrn](https://github.com/wbrn.png?size=40 "wbrn")](https://github.com/wbrn)
-[![TpOut](https://github.com/TpOut.png?size=40 "TpOut")](https://github.com/TpOut)
-[![PabloCastellano](https://github.com/PabloCastellano.png?size=40 "PabloCastellano")](https://github.com/PabloCastellano)
-[![cd3](https://github.com/cd3.png?size=40 "cd3")](https://github.com/cd3)
-[![Steve-Xyh](https://github.com/Steve-Xyh.png?size=40 "Steve-Xyh")](https://github.com/Steve-Xyh)
-
## Other multi-repo tools
I haven't tried them but I heard good things about them.