Initial commit
This commit is contained in:
217
README.md
Normal file
217
README.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# gitlocal
|
||||
|
||||
A CLI tool for managing nested git repositories by converting `.git` directories to `.gitlocal`, allowing parent repos to track nested project files.
|
||||
|
||||
## Problem
|
||||
|
||||
When you have a parent git repository (like a knowledge base or personal monorepo) that contains nested projects with their own `.git` directories, Git and GUI tools like GitKraken won't let you commit those nested directories. Git treats them as submodules or gitlinks.
|
||||
|
||||
## Solution
|
||||
|
||||
`gitlocal` renames `.git` → `.gitlocal` in nested projects, which:
|
||||
- Allows the parent repo to track all files normally
|
||||
- Preserves the nested repo's git history in `.gitlocal`
|
||||
- Lets you use git commands locally via the `git-local` alias
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go install git.membo.co.uk/dtomlinson/gitlocal@latest
|
||||
```
|
||||
|
||||
Make sure `$HOME/go/bin` is in your `PATH`.
|
||||
|
||||
## Commands
|
||||
|
||||
### Convert a single repository
|
||||
|
||||
```bash
|
||||
# Convert .git → .gitlocal in current directory
|
||||
gitlocal convert
|
||||
|
||||
# Convert specific directory
|
||||
gitlocal convert /path/to/nested/repo
|
||||
```
|
||||
|
||||
### Convert all nested repositories
|
||||
|
||||
```bash
|
||||
# Recursively find and convert all nested .git directories
|
||||
gitlocal convert --recursive
|
||||
|
||||
# Dry run to see what would be converted
|
||||
gitlocal convert --recursive --dry-run
|
||||
```
|
||||
|
||||
### Revert back to .git
|
||||
|
||||
```bash
|
||||
# Revert .gitlocal → .git in current directory
|
||||
gitlocal revert
|
||||
|
||||
# Revert all tracked repositories
|
||||
gitlocal revert --all
|
||||
```
|
||||
|
||||
### Show converted repositories
|
||||
|
||||
```bash
|
||||
gitlocal status
|
||||
```
|
||||
|
||||
Example output:
|
||||
```
|
||||
Converted Repositories (2):
|
||||
|
||||
/Users/you/tembo/work/2026/03_March/midnight_season_1_tanking_summaries
|
||||
Converted: 2 days ago
|
||||
Remote: git@github.com:user/repo.git
|
||||
Branch: main
|
||||
|
||||
/Users/you/tembo/work/2025/12_December/trilium_next_theme/Trilium
|
||||
Converted: 2 days ago
|
||||
Remote: https://github.com/trilium/trilium.git
|
||||
Branch: master
|
||||
```
|
||||
|
||||
## Using git with .gitlocal
|
||||
|
||||
Add this alias to your `.zshrc` or `.bashrc`:
|
||||
|
||||
```bash
|
||||
alias git-local='git --git-dir=.gitlocal --work-tree=.'
|
||||
```
|
||||
|
||||
Then use `git-local` instead of `git` in converted repos:
|
||||
|
||||
```bash
|
||||
cd /path/to/converted/repo
|
||||
git-local status
|
||||
git-local log
|
||||
git-local commit -am "Update"
|
||||
git-local push
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
`gitlocal` tracks converted repositories in `~/.gitlocal.yml`:
|
||||
|
||||
```yaml
|
||||
version: "1"
|
||||
repos:
|
||||
- path: /absolute/path/to/repo
|
||||
converted_at: 2026-04-07T14:30:00Z
|
||||
original_remote: git@github.com:user/repo.git
|
||||
original_branch: main
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Requirements
|
||||
- Go 1.19 or later
|
||||
- Git (for running tests)
|
||||
|
||||
### Building from Source
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://git.membo.co.uk/dtomlinson/gitlocal.git
|
||||
cd gitlocal
|
||||
|
||||
# Install dependencies
|
||||
go mod download
|
||||
|
||||
# Build the binary
|
||||
go build -o gitlocal
|
||||
|
||||
# Or install directly to $GOPATH/bin
|
||||
go install
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
go test ./...
|
||||
|
||||
# Run tests with verbose output
|
||||
go test -v ./...
|
||||
|
||||
# Run tests with coverage
|
||||
go test -coverprofile=coverage.out ./...
|
||||
go tool cover -func=coverage.out
|
||||
|
||||
# View coverage in browser
|
||||
go tool cover -html=coverage.out
|
||||
|
||||
# Run tests for a specific package
|
||||
go test ./internal/git
|
||||
go test -v ./cmd
|
||||
```
|
||||
|
||||
### Test Coverage
|
||||
|
||||
Current test coverage: **71%**
|
||||
|
||||
- `internal/git`: 94.7%
|
||||
- `internal/scanner`: 86.4%
|
||||
- `internal/config`: 80.6%
|
||||
- `cmd`: 60.0%
|
||||
|
||||
Tests use temporary directories and real git operations to ensure correctness.
|
||||
|
||||
## Workflow Example
|
||||
|
||||
1. You have a knowledge base at `~/kb/` with nested projects:
|
||||
```
|
||||
~/kb/
|
||||
├── .git/ # Parent repo
|
||||
├── projects/
|
||||
│ ├── my-app/
|
||||
│ │ └── .git/ # Nested repo - can't commit!
|
||||
│ └── another-project/
|
||||
│ └── .git/ # Nested repo - can't commit!
|
||||
```
|
||||
|
||||
2. Convert all nested repos:
|
||||
```bash
|
||||
cd ~/kb
|
||||
gitlocal convert --recursive
|
||||
```
|
||||
|
||||
3. Now the structure is:
|
||||
```
|
||||
~/kb/
|
||||
├── .git/ # Parent repo
|
||||
├── projects/
|
||||
│ ├── my-app/
|
||||
│ │ └── .gitlocal/ # Can commit from parent!
|
||||
│ └── another-project/
|
||||
│ └── .gitlocal/ # Can commit from parent!
|
||||
```
|
||||
|
||||
4. Commit from parent repo:
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Add nested projects"
|
||||
git push
|
||||
```
|
||||
|
||||
5. Work on nested project:
|
||||
```bash
|
||||
cd ~/kb/projects/my-app
|
||||
git-local status
|
||||
git-local commit -am "Update feature"
|
||||
```
|
||||
|
||||
6. If you need to use GitKraken on a nested project:
|
||||
```bash
|
||||
cd ~/kb/projects/my-app
|
||||
gitlocal revert
|
||||
# Use GitKraken
|
||||
gitlocal convert
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
Reference in New Issue
Block a user