summaryrefslogtreecommitdiffstats
path: root/doc/README_CN.md
blob: 23a9102d00c1eb3c100967e022fe756d7a898fba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
[![PyPi version](https://img.shields.io/pypi/v/gita.svg?color=blue)](https://pypi.org/project/gita/)
[![Build Status](https://travis-ci.org/nosarthur/gita.svg?branch=master)](https://travis-ci.org/nosarthur/gita)
[![codecov](https://codecov.io/gh/nosarthur/gita/branch/master/graph/badge.svg)](https://codecov.io/gh/nosarthur/gita)
[![licence](https://img.shields.io/pypi/l/gita.svg)](https://github.com/nosarthur/gita/blob/master/LICENSE)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/gita.svg)](https://pypistats.org/packages/gita)
[![Gitter](https://badges.gitter.im/nosarthur/gita.svg)](https://gitter.im/nosarthur/gita?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![English](https://img.shields.io/badge/-English-lightgrey.svg)](https://github.com/nosarthur/gita)

```
 _______________________________
(  ____ \__   __|__   __(  ___  )
| (    \/  ) (     ) (  | (   ) |
| |        | |     | |  | (___) |
| | ____   | |     | |  |  ___  |
| | \_  )  | |     | |  | (   ) |
| (___) |__) (___  | |  | )   ( |
(_______)_______/  )_(  |/     \|   v0.16
```

# Gita:一个管理多个 git 库的命令行工具

这个工具有两个功能:

- 并排显示多个库的状态信息,比如分支名,编辑状态,提交信息等
- 在任何目录下(批处理)代理执行 git 指令

![gita screenshot](https://github.com/nosarthur/gita/raw/master/doc/screenshot.png)

在这个截屏里,`gita ll`显示所有库的状态信息,`gita remote dotfiles`等价于在
`dotfiles`库里运行`git remote -v`,`gita fetch`对所有库做`fetch`操作,在这个例子
里,两个库有更新.

本地和远程分支之间的5种关系分别用5种颜色对应:

颜色|含义
----|----
 绿色|本地和远程保持一致
 红色|本地和远程产生了分叉
 黄色|本地落后于远程(适合合并merge)
 白色|本地没有指定远程
 紫色|本地超前于远程(适合推送push)

紫色作为超前,黄色作为落后,绿色作为基准的理由取自蓝移和红移:
[blueshift](https://en.wikipedia.org/wiki/Blueshift)、[redshift](https://en.wikipedia.org/wiki/Redshift).

额外的状态符号意义:

- `+`: 暂存(staged)
- `*`: 未暂存(unstaged)
- `_`: 未追踪(untracked)

基础指令:

- `gita add <repo-path(s)>`: 添加库
- `gita add -a <repo-parent-path(s)>`: 递归添加路径下的所有库并自动产生层级分组,见
  [customization section](#custom)
- `gita add -b <bare-repo-path(s)>`: 添加bare库
  [customization section](#custom)
- `gita add -r <repo-parent-path(s)>`: 递归添加路径下的所有库
- `gita clone <config-file>`: 克隆`<config-file>` (由`gita freeze`生成)里的库
- `gita clone -p <config-file>`: 克隆`<config-file>`里的库并放到指定路径
- `gita context`: 情境命令
    - `gita context`: 显示当前的情境
    - `gita context none`: 去除情境
    - `gita context <group-name>`: 把情境设置成`group-name`, 之后所有的操作只作用到这个组里的库
- `gita color`:
    - `gita color [ll]`:显示颜色设置
    - `gita color set <situation> <color>`:给本地/远程关系设置颜色
- `gita flags`:
    - `gita flags set <repo-name> <flags>`:给库设置flags
    - `gita flags [ll]`:显示已有的flags
- `gita freeze`:显示URL, 路径之类的库信息(配合`gita clone`使用)
- `gita group`: 组群命令
    - `gita group add <repo-name(s)>`: 把库加入新的或者已经存在的组
    - `gita group [ll]`: 显示已有的组和它们的库
    - `gita group ls`: 显示已有的组名
    - `gita group rename <group-name> <new-name>`: 改组名
    - `gita group rm group(s): 删除组
    - `gita group rmrepo -n <group-name>:删除组里的库
- `gita info`: 显示已用的和未用的信息项
    - `gita info [ll]`
    - `gita info add <info-item>`
    - `gita info rm <info-item>`
- `gita ll`: 显示所有库的状态信息
- `gita ll <group-name>`: 显示一个组群中库的状态信息
- `gita ls`: 显示所有库的名字
- `gita ls <repo-name>`: 显示一个库的绝对路径
- `gita rename <repo-name> <new-name>`: 重命名一个库
- `gita rm <repo-name(s)>`: 移除库(不会删除文件)
- `gita -v`: 显示版本号

库的路径存在`$XDG_CONFIG_HOME/gita/repos.csv` (多半是`~/.config/gita/repos.csv`)。

代理执行的子命令有两种格式:

- `gita <sub-command> [repo-name(s) or group-name(s)]`: 库名或组群名是可选的,缺失表示所有库
- `gita <sub-command> <repo-name(s) or group-name(s)>`: 必须有库名或组群名

默认只有`fetch`和`pull`是第一种格式。

如果输入了多个库名,
而且被代理的git指令不需要用户输入,
那么各个库的代理指令会被异步执行。

## 安装指南

正常人类安装:

```
pip3 install -U gita
```

神奇码农安装:先下载源码,然后

```
pip3 install -e <gita-source-folder>
```

装完之后在命令行下执行`gita`可能还不行。那就把下面这个昵称放到`.bashrc`里。
```
alias gita="python3 -m gita"
```

Windows用户可能需要额外的设置来支持彩色的命令行, 见[这个帖子](https://stackoverflow.com/questions/51680709/colored-text-output-in-powershell-console-using-ansi-vt100-codes)。

## 自动补全

下载
[.gita-completion.bash](https://github.com/nosarthur/gita/blob/master/.gita-completion.bash)
并在`.bashrc`里点它。

## 超人模式

超人模式可以代理执行任何git命令/别名。它的格式是

```
gita super [repo-name(s) or group-name(s)] <any-git-command-with-or-without-options>
```

其中库名或组群名是可有可无的。举几个例子

- `gita super checkout master`会把所有库都弄到主库杈上
- `gita super frontend-repo backend-repo commit -am 'implement a new feature'`
  会对`frontend-repo`和`backend-repo`运行`git commit -am 'implement a new feature'`

## 私人定制

定制的代理子命令要放在`$XDG_CONFIG_HOME/gita/cmds.yml` (多半是`~/.config/gita/cmds.yml`)。
如果存在命名冲突,它们会覆盖掉默认的指令。

默认代理子指令的定义可见
[cmds.yml](https://github.com/nosarthur/gita/blob/master/gita/cmds.yml)。
举个栗子,`gita stat <repo-name(s)>`的定义是

```yaml
stat:
  cmd: diff --stat
  help: show edit statistics
```

它会执行`git diff --stat`。

如果被代理的指令是一个单词,`cmd`也可以省略。比如`push`。
如果要取消异步执行,把`disable_async`设成`true`。比如`difftool`。

如果你想让定制的命令跟`gita fetch`等命令一样,可以作用于所有的库,
就把`allow_all`设成`true`。
举个栗子,`gita comaster [repo-names(s)]`会生成一个新的定制命令,对于这个命令,库名是可选输入。comaster的解释如下:

```yaml
comaster:
  cmd: checkout master
  allow_all: true
  help: checkout the master branch
```
另一个自定义功能是针对`gita ll`展示的信息项。
`gita info`可以展示所有用到的和没用到的信息项,并且可以通过修改`$XDG_CONFIG_HOME/gita/info.csv`支持自定义。举个栗子,默认的信息项显示配置相当于是:

```csv
branch,commit_msg,commit_time
```
为了创建自己的信息项,命名一个目录为`extra_info_items`。
在`$XDG_CONFIG_HOME/gita/extra_repo_info.py`中,要把信息项的名字作为字符串映射到方法中,该方法将库的路径作为输入参数。举个栗子:

```python
def get_delim(path: str) -> str:
    return '|'

extra_info_items = {'delim': get_delim}
```
如果没有遇到问题,你会在`gita info`的输出内容中的`unused`小节中看到这些额外信息项。

## 先决条件

因为用了[f-string](https://www.python.org/dev/peps/pep-0498/)
和[asyncio module](https://docs.python.org/3.6/library/asyncio.html),系统必须要用Python 3.6或以上。

暗地里老夫用`subprocess`来代理执行git指令。所以git的版本有可能会影响结果。
经测试,`1.8.3.1`, `2.17.2`, 和`2.20.1`的结果是一致的。

## 有所作为

要想有所作为,你可以

- 报告/治理虫子
- 建议/实现功能
- 加星/推荐本作

聊天请入[![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)

在本地跑单元测试可以直接用`pytest`。更多的细节可见
[design.md](https://github.com/nosarthur/gita/blob/master/doc/design.md)。

如果你愿意资助我,请访问[GitHub Sponsors](https://github.com/sponsors/nosarthur)。

## 他山之石

没用过,听说不错

- [myrepos](https://myrepos.branchable.com/)
- [repo](https://source.android.com/setup/develop/repo)