gerrit-change-list
Recursively scan git repositories under a path and list commits merged within a time range — by committer date, not author date — across every repo it finds, with Gerrit patch links.
Built for the recurring question: "a problem showed up; who landed what into these repos in this window, and what are the patch links?"
Why committer date
In a Gerrit workflow the author date is when the developer wrote the
patch; the committer date is when it actually landed on the branch
(merged / cherry-picked / rebased in). When you git pull / repo sync
to latest and ask "what got merged on July 5th", you want committer date.
git log --since/--until filter on committer date, so that is what this
tool uses.
Features
- Three time selectors (pick one):
--day,--hour, or--since/--until. - Cross-repo by default: recursively finds every
.gitunder the path — standalone repos andrepo-tool-managed multi-repos. Nested submodules are picked up too. - Gerrit patch links: host derived from each repo's
originremote; link ishttps://<host>/q/<Change-Id>(clickable, no network/auth needed). - Two outputs: a colored terminal table grouped by repo, plus a Markdown report file.
- Zero runtime dependencies — standard library only.
Install
Prerequisite: git must be on PATH (the tool shells out to git log /
git config). Python ≥ 3.10.
From PyPI:
pip install gerrit-change-list
gerrit-change-list --version
Editable install (for development, with test/lint deps):
pip install -e ".[dev]"
Or run from source with no install:
./main.py --version
Usage
# Whole calendar day (local timezone)
gerrit-change-list /path/to/workspace --day 2026-07-05
# Whole calendar hour
gerrit-change-list /path/to/workspace --hour "2026-07-05 14"
# Precise range (--until defaults to now when omitted)
gerrit-change-list /path/to/workspace --since "2026-07-05 14:00" --until "2026-07-05 15:30"
# Force a timezone for the selectors
gerrit-change-list . --day 2026-07-05 --tz Asia/Shanghai
# Filter by submitter; show committer instead of author
gerrit-change-list . --since "2026-07-05" --author "alice" --by-committer
[!NOTE] The tool only reads local state — it does not pull. Run
git pull/repo syncto latest first.
Example
Terminal output (colors shown when stdout is a TTY and NO_COLOR is unset):
$ gerrit-change-list /path/to/workspace --day 2026-07-05
gerrit-change-list range: 2026-07-05 .. 2026-07-06
3 commit(s) across 2 repo(s)
platform/native (2)
Merge time Patch Submitter Subject
2026-07-05 09:12:33 +0800 https://gerrit.example.com/q/I1a2b3c4d5e6 Alice <a@x.example> Fix audio underrun on cold start
2026-07-05 14:45:10 +0800 https://gerrit.example.com/q/I2b3c4d5e6f7 Bob <b@x.example> Refactor PCM open path
vendor/hal (1)
Merge time Patch Submitter Subject
2026-07-05 10:03:55 +0800 https://gerrit.example.com/q/I3c4d5e6f7g8 Carol <c@x.example> Lower default buffer size
A Markdown report with the same content is written next to the run
(gerrit-change-list-report-<timestamp>.md by default).
Output
- Terminal: a color table grouped by repo, columns
Merge time | Patch | Submitter | Subject. Color is gated on TTY andNO_COLOR. - Markdown report: written to
gerrit-change-list-report-<timestamp>.md(override with-o, suppress with--no-markdown).
[!TIP] To preview the rendered Markdown report:
grip <file.md>(local server) orpandoc <file.md> -s -o <file.html>(standalone HTML).
Options
| Option | Description |
|---|---|
path |
root path to scan (default: current directory) |
--day YYYY-MM-DD |
whole calendar day |
--hour "YYYY-MM-DD HH" |
whole calendar hour |
--since ... |
start time (inclusive); --until defaults to now |
--until ... |
end time |
--tz ... |
+0800 | +08:00 | Z | Asia/Shanghai (default: system local) |
--author REGEX |
match author name/email |
--by-committer |
show committer (not author) as the submitter column |
--max-count N |
per-repo commit cap |
--reverse |
oldest-first within each repo |
-o, --output PATH |
Markdown report path |
--no-markdown |
do not write a Markdown report file |
-V, --version |
show version and exit |
How it works
- Repo discovery: a "repo" is any directory containing a
.gitentry — a.gitdirectory (normal checkout) or a.gitfile (worktree / submodule). The scan never enters.git/or.repo/metadata, but keeps walking a found repo's subdirectories so nested submodules are found. Eachrepo-tool project is itself a normal git repo, so it is covered. - Time field:
git log --since/--untilfilter on the committer date. Author date is not used for filtering. - Patch link: the Gerrit host is parsed from each repo's
originremote URL. Forssh://remotes the port (e.g. Gerrit's 29418) is dropped — that's the push port; the web UI runs on HTTPS (443). The linkhttps://<host>/q/<Change-Id>is Gerrit's search-redirect URL. Commits without aChange-Idfall back to the commit hash.
Development
pip install -e ".[dev]"
pytest # tests
black --check src tests # format check (CI-enforced)
python -m build # build wheel
License
Apache License 2.0 — see LICENSE.
Release files for gerrit-change-list 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gerrit_change_list-0.0.1.tar.gz | 18.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gerrit_change_list-0.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.8 kB
Release files / gerrit_change_list-0.0.1.tar.gz
| Download URL | gerrit_change_list-0.0.1.tar.gz |
|---|---|
| Size | 18.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8dd78774f89d48bb44cb56577c98fc329368fbfed00c06552cd3a01c22f597f4
|
|
BLAKE2b-256 checksum How to use checksums |
705d1417bd3716b6e625dfabb4f0793ce336b6c0f0292711ccd7d7402da4d60c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|
Release files / gerrit_change_list-0.0.1-py3-none-any.whl
| Download URL | gerrit_change_list-0.0.1-py3-none-any.whl |
|---|---|
| Size | 17.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
447e8b7ffa293edd22672c4751beb6eea02812d5a6a16d07d0030a2748707953
|
|
BLAKE2b-256 checksum How to use checksums |
bd747b92cd45ea1d71eb44dbcc30654830bbd370e72e4c9a0e6c4cd522f88522
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.10.12
|