Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ dist
gih_dev

.worktrees/
tasks/
tasks/
.claude/improve-memory-md/
21 changes: 5 additions & 16 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
# Repository Guidelines

## Project Structure & Module Organization
`gih/main.go` is the CLI entry point. Core behavior lives in `syncer/`: `dir.go` discovers direct child repositories, `git.go` runs git commands, and `syncer.go` coordinates parallel execution. Output formatting lives in `printer/`. Tests sit next to the code as `*_test.go`. CI and templates are under `.github/`.

## Build, Test, and Development Commands
Use Go 1.26.

- `make build`: builds a development binary as `./gih_dev`.
- `make install`: installs `gih` from `./gih`.
- `make test`: runs `go test -v -race ./...`.
- `make lint`: runs `golangci-lint` as used in CI.
- `make tidy`: normalizes `go.mod` and `go.sum`.
- `DEBUG=* go run ./gih status`: handy for manual CLI checks.

Before opening a PR, run `make build && make test && make lint`.
Before opening a PR, run `make build && make test && make lint` (`make lint` matches CI).

## Coding Style & Naming Conventions
Follow standard Go formatting with `gofmt`; keep packages small and focused. Prefer the standard library over new dependencies when possible. Use clear package scopes such as `feat(syncer)` or `fix(printer)` when naming changes. Keep filenames lowercase, and keep tests in the same package unless black-box coverage is required.
Prefer the standard library over new dependencies when possible. Keep tests in the same package unless black-box coverage is required.
Repositories are processed in parallel, so every public `printer.Printer` method must hold `p.mu` while writing; cover new ones with a `*_ConcurrentSafe` test.

## Testing Guidelines
This repository uses Go’s `testing` package plus `github.com/matryer/is`. Write focused tests with `t.Run(...)`; avoid table-driven tests here. Use `t.Parallel()` whenever the case is safe to parallelize. Name receiver-related tests as `Test{Struct}_Xxx`, for example `TestSync_Execute`. Run targeted checks with `go test -v ./syncer/` and use `go test -cover ./...` when touching behavior broadly.
This repository uses Go’s `testing` package plus `github.com/matryer/is`. Write focused tests with `t.Run(...)`; avoid table-driven tests here. Use `t.Parallel()` whenever the case is safe to parallelize. Name receiver-related tests as `Test{Struct}_Xxx`, for example `TestSync_Execute`.

## Commit & Pull Request Guidelines
Recent history follows Conventional Commits, for example `feat(gih): ...`, `refactor(syncer): ...`, and `fix(printer): ...`. Keep commit titles in English and scoped when helpful. PRs should follow `.github/PULL_REQUEST_TEMPLATE.md` with `## Issue` and `## Overview`, link the related issue, and describe behavioral changes briefly in Japanese. Include tests for functional changes and update `README.md` when CLI behavior changes.
Follow Conventional Commits with English titles, scoped by package when helpful, for example `feat(gih): ...`, `refactor(syncer): ...`, and `fix(printer): ...`. PRs should follow `.github/PULL_REQUEST_TEMPLATE.md` with `## Issue` and `## Overview`, link the related issue, and describe behavioral changes briefly in Japanese. Include tests for functional changes and update `README.md` when CLI behavior changes.

## Worktree Workflow
Do not work directly on the default branch (currently `master`). Start each non-trivial change from a dedicated branch and worktree under `.worktrees/`, for example `git worktree add .worktrees/feat-x -b feat/x`.
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![unittest](https://github.com/takecy/git-here/workflows/unittest/badge.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/takecy/git-here)](https://goreportcard.com/report/github.com/takecy/git-here)
![Go Version](https://img.shields.io/badge/golang-1.26+-blue.svg?style=flat-square)
![Go Version](https://img.shields.io/badge/golang-1.27+-blue.svg?style=flat-square)
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/takecy/git-here)

**Efficiently run git commands across multiple repositories in parallel**
Expand All @@ -29,19 +29,20 @@ I created it because I was tired of managing dozens of microservice repositories
prints a bordered summary table with totals at the end:

```
==> Running pull origin master on 3 repositories
✓ takecy/git-here Already up to date. 0.4s
✗ takecy/adk-test fatal: couldn't find remote ref master 1.2s
✓ takecy/another-repo Already up to date. 0.5s
$ gih pull
==> Running pull on 3 repositories
✓ workspace/api-server Already up to date. 0.4s
✓ workspace/docs Updating a17b0e2..c52d9f4 0.7s
✓ workspace/web-frontend Updating 3f9c2a1..8d4e7b6 1.1s
==> Summary
+-------------------------+--------+----------+----------------------------------------+
| Repository | Status | Duration | Message |
+-------------------------+--------+----------+----------------------------------------+
| takecy/git-here | ✓ | 0.4s | Already up to date. |
| takecy/adk-test | ✗ | 1.2s | fatal: couldn't find remote ref master |
| takecy/another-repo | ✓ | 0.5s | Already up to date. |
+-------------------------+--------+----------+----------------------------------------+
Total: 3 Success: 2 Failed: 1 Timeout: 0 Elapsed: 1.2s
+------------------------+--------+----------+---------------------------+
| Repository | Status | Duration | Message |
+------------------------+--------+----------+---------------------------+
| workspace/api-server | ✓ | 0.4s | Already up to date. |
| workspace/docs | ✓ | 0.7s | Updating a17b0e2..c52d9f4 |
| workspace/web-frontend | ✓ | 1.1s | Updating 3f9c2a1..8d4e7b6 |
+------------------------+--------+----------+---------------------------+
Total: 3 Success: 3 Failed: 0 Timeout: 0 Elapsed: 1.1s
```

Failed rows are colored red and timed-out rows yellow when the output
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
module github.com/takecy/git-here

go 1.26
go 1.27

require (
github.com/fatih/color v1.19.0
github.com/matryer/is v1.4.0
github.com/pkg/errors v0.9.1
golang.org/x/sync v0.20.0
golang.org/x/sync v0.23.0
)

require (
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.21 // indirect
golang.org/x/sys v0.43.0 // indirect
github.com/mattn/go-colorable v0.1.15 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
golang.org/x/sys v0.48.0 // indirect
)
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk=
golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
Loading