Skip to content

cchitsiang/patch-repo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

patch-repo

Manage custom changes to cloned git repositories without maintaining forks.

patch-repo captures your uncommitted changes as .patch files, stores them locally, and re-applies them after pulling latest upstream. Think patch-package, but for entire repositories.

Install

Homebrew (macOS/Linux)

brew tap cchitsiang/tap
brew install patch-repo

Go

go install github.com/cchitsiang/patch-repo@latest

From source

git clone https://github.com/cchitsiang/patch-repo.git
cd patch-repo
go build -o patch-repo .

Quick Start

# Clone a repo you want to customize
git clone https://github.com/someone/cool-project.git
cd cool-project

# Initialize patch-repo (creates .patch-repo/, updates global gitignore)
patch-repo init

# Make your changes (don't commit them)
vim src/config.go

# Save changes as a named patch
patch-repo create fix-auth-timeout

# Later, pull latest upstream and re-apply your patches
patch-repo sync

Commands

patch-repo init

Sets up .patch-repo/ in the current git repo and adds it to your global gitignore so patches are never committed upstream.

patch-repo create <name>

Captures all uncommitted changes (tracked and untracked files) as a sequenced patch file.

$ patch-repo create fix-auth-timeout
Created 001-fix-auth-timeout.patch
  Files: src/config.go

Name must be lowercase alphanumeric and hyphens only.

patch-repo apply

Applies all patches in sequence order. Uses 3-way merge when a patch doesn't apply cleanly, leaving conflict markers instead of refusing entirely.

$ patch-repo apply
Applied 001-fix-auth-timeout.patch
Applied 002-add-logging.patch
All 2 patches applied successfully

patch-repo list

Shows all stored patches with affected files.

$ patch-repo list
001 | fix-auth-timeout     | src/config.go
002 | add-logging          | src/server.go, src/middleware.go

patch-repo remove <name-or-number>

Deletes a patch by name or sequence number. Remaining patches are renumbered to stay contiguous.

$ patch-repo remove 1
Removed 001-fix-auth-timeout.patch
Remaining patches:
  001-add-logging.patch

patch-repo diff [name-or-number]

Shows the full diff contents of stored patches. Without arguments, shows all patches. With an argument, shows a specific patch by name or number.

$ patch-repo diff
=== 001-fix-auth-timeout.patch ===
diff --git a/src/config.go b/src/config.go
...

$ patch-repo diff 1
=== 001-fix-auth-timeout.patch ===
...

patch-repo refresh <name>

Clears all existing patches and creates one fresh patch from all current uncommitted changes. Useful after resolving conflicts or when patches have gotten messy.

$ patch-repo refresh my-customizations
Cleared 3 existing patches
Created 001-my-customizations.patch
  Files: src/config.go, src/server.go

patch-repo sync

Discards all uncommitted changes, pulls latest from upstream, and re-applies all patches. Uses 3-way merge for conflict resolution. Prompts for confirmation before proceeding.

$ patch-repo sync
This will discard all uncommitted changes and pull latest. Continue? [y/N] y
Discarding uncommitted changes...
Pulling latest...
Applying patches...
Applied 001-fix-auth-timeout.patch
Sync complete: pulled latest and applied 1 patches

How It Works

  • Patches are standard git diff output stored in .patch-repo/ inside the repo root
  • Files are named NNN-<name>.patch (e.g. 001-fix-auth-timeout.patch)
  • .patch-repo/ is added to your global gitignore on init, so patches never pollute the upstream repo
  • All git operations use the git binary on your PATH

When a Patch Conflicts

If upstream changes conflict with a patch during apply or sync, 3-way merge creates standard conflict markers in the affected files:

$ patch-repo apply
Applied 001-fix-auth-timeout.patch with CONFLICTS in:
  - src/config.go

Some patches have conflicts. Resolve them, then recreate the patch:
  1. Edit the conflicted files (look for <<<<<<< markers)
  2. patch-repo remove <name>
  3. patch-repo create <name>

Or use refresh to start clean:

# Resolve the conflict markers in your editor, then:
patch-repo refresh my-customizations

Requirements

  • Go 1.21+ (for building)
  • git on PATH

License

MIT

About

Manage custom changes to cloned git repos without maintaining forks. Like patch-package, but for entire repositories.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages