git-trim 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +18 -0
- data/.github/workflows/release.yml +65 -0
- data/Gemfile.lock +17 -16
- data/README.md +29 -6
- data/bin/git-trim +1 -1
- data/git-trim.gemspec +2 -2
- data/lib/git-trim/version.rb +1 -1
- data/lib/git-trim.rb +51 -2
- metadata +8 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 14a8db7d9bf6cca92301a221f4e096d633882d103f9f7ea4b68e4ce5a6187ce5
|
|
4
|
+
data.tar.gz: 26a4e8614638c39d3692815c34aee4d4358088e62aa13ebb3d6ff0372d1ee3f7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3915fb4d49379edebb0928cde8f4c7f2774c429f437ee67381edfd263b567c32b3d6f7ae5c922b7c1d963079859ea844b3916d62f7a3a5712a899f2e0a6d75e
|
|
7
|
+
data.tar.gz: 4e604a55e748caa6af8537b929d6bdde5d50b352c6e5a73cb38950133e9f796f0df855e620b45173928c5ef535b311f8dd28ae8a40d3b5e94c26239815cdbe44
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: build
|
|
2
|
+
on: pull_request
|
|
3
|
+
jobs:
|
|
4
|
+
build:
|
|
5
|
+
runs-on: ubuntu-latest
|
|
6
|
+
steps:
|
|
7
|
+
- uses: actions/checkout@v6
|
|
8
|
+
- uses: ruby/setup-ruby@v1
|
|
9
|
+
with:
|
|
10
|
+
ruby-version: ruby
|
|
11
|
+
bundler-cache: true
|
|
12
|
+
|
|
13
|
+
- name: Run specs
|
|
14
|
+
run: |
|
|
15
|
+
git config --global user.email "ci@example.com"
|
|
16
|
+
git config --global user.name "CI"
|
|
17
|
+
git config --global init.defaultBranch main
|
|
18
|
+
bundle exec rake spec
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
version:
|
|
7
|
+
description: "Version to release (e.g. 0.2.0)"
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
contents: write
|
|
16
|
+
id-token: write
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v6
|
|
19
|
+
|
|
20
|
+
- uses: ruby/setup-ruby@v1
|
|
21
|
+
with:
|
|
22
|
+
ruby-version: "3.3"
|
|
23
|
+
bundler-cache: true
|
|
24
|
+
|
|
25
|
+
- name: Run specs
|
|
26
|
+
run: bundle exec rake spec
|
|
27
|
+
|
|
28
|
+
- name: Update version
|
|
29
|
+
run: |
|
|
30
|
+
VERSION="${{ inputs.version }}"
|
|
31
|
+
sed -i "s/VERSION = \".*\"/VERSION = \"$VERSION\"/" lib/git-trim/version.rb
|
|
32
|
+
echo "Updated version to $VERSION"
|
|
33
|
+
cat lib/git-trim/version.rb
|
|
34
|
+
|
|
35
|
+
# bundler-cache sets frozen/deployment mode, which rejects the now
|
|
36
|
+
# out-of-date lockfile entry for git-trim itself. Re-lock so the
|
|
37
|
+
# release commit keeps the gemspec and lockfile in sync.
|
|
38
|
+
- name: Update Gemfile.lock
|
|
39
|
+
run: |
|
|
40
|
+
bundle config unset deployment
|
|
41
|
+
bundle config unset frozen
|
|
42
|
+
BUNDLE_FROZEN=false BUNDLE_DEPLOYMENT=false bundle lock
|
|
43
|
+
|
|
44
|
+
- name: Commit version bump
|
|
45
|
+
run: |
|
|
46
|
+
VERSION="${{ inputs.version }}"
|
|
47
|
+
git config user.name "github-actions[bot]"
|
|
48
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
49
|
+
git add lib/git-trim/version.rb Gemfile.lock
|
|
50
|
+
git commit -m "Release v$VERSION"
|
|
51
|
+
|
|
52
|
+
# Builds the gem into pkg/, tags v$VERSION, pushes the commit and
|
|
53
|
+
# tag, and publishes to RubyGems via OIDC trusted publishing.
|
|
54
|
+
- name: Release to RubyGems
|
|
55
|
+
uses: rubygems/release-gem@v1
|
|
56
|
+
|
|
57
|
+
- name: Create GitHub Release
|
|
58
|
+
env:
|
|
59
|
+
GH_TOKEN: ${{ github.token }}
|
|
60
|
+
run: |
|
|
61
|
+
VERSION="${{ inputs.version }}"
|
|
62
|
+
gh release create "v$VERSION" \
|
|
63
|
+
--title "v$VERSION" \
|
|
64
|
+
--generate-notes \
|
|
65
|
+
pkg/git-trim-*.gem
|
data/Gemfile.lock
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
git-trim (0.
|
|
4
|
+
git-trim (0.2.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
-
diff-lcs (1.
|
|
10
|
-
rake (13.
|
|
11
|
-
rspec (3.
|
|
12
|
-
rspec-core (~> 3.
|
|
13
|
-
rspec-expectations (~> 3.
|
|
14
|
-
rspec-mocks (~> 3.
|
|
15
|
-
rspec-core (3.
|
|
16
|
-
rspec-support (~> 3.
|
|
17
|
-
rspec-expectations (3.
|
|
9
|
+
diff-lcs (1.6.2)
|
|
10
|
+
rake (13.4.2)
|
|
11
|
+
rspec (3.13.2)
|
|
12
|
+
rspec-core (~> 3.13.0)
|
|
13
|
+
rspec-expectations (~> 3.13.0)
|
|
14
|
+
rspec-mocks (~> 3.13.0)
|
|
15
|
+
rspec-core (3.13.6)
|
|
16
|
+
rspec-support (~> 3.13.0)
|
|
17
|
+
rspec-expectations (3.13.5)
|
|
18
18
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
19
|
-
rspec-support (~> 3.
|
|
20
|
-
rspec-mocks (3.
|
|
19
|
+
rspec-support (~> 3.13.0)
|
|
20
|
+
rspec-mocks (3.13.8)
|
|
21
21
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
22
|
-
rspec-support (~> 3.
|
|
23
|
-
rspec-support (3.7
|
|
22
|
+
rspec-support (~> 3.13.0)
|
|
23
|
+
rspec-support (3.13.7)
|
|
24
24
|
|
|
25
25
|
PLATFORMS
|
|
26
|
+
arm64-darwin-25
|
|
26
27
|
ruby
|
|
27
28
|
|
|
28
29
|
DEPENDENCIES
|
|
29
|
-
bundler (
|
|
30
|
+
bundler (>= 1.16)
|
|
30
31
|
git-trim!
|
|
31
32
|
rake (~> 13.0)
|
|
32
33
|
rspec (~> 3.0)
|
|
33
34
|
|
|
34
35
|
BUNDLED WITH
|
|
35
|
-
|
|
36
|
+
2.5.3
|
data/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# git trim
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
|
3
|
+
Deletes local branches — and the [linked worktrees](https://git-scm.com/docs/git-worktree) that hold them — once they are fully merged into `main`. Run it after a round of PRs merge and it cleans up everything that's done, while refusing to touch anything that still has work in it.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
@@ -22,7 +20,28 @@ Or install it yourself as:
|
|
|
22
20
|
|
|
23
21
|
## Usage
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
Run `git trim` from anywhere inside a repository. It fetches (with prune), then removes every local branch that is fully merged into `main`, unless the branch is:
|
|
24
|
+
|
|
25
|
+
- `main` itself,
|
|
26
|
+
- the branch you currently have checked out, or
|
|
27
|
+
- listed in a `.git-protected-branches` file.
|
|
28
|
+
|
|
29
|
+
If no local `main` exists (common in bare-repo + worktrees layouts), it compares against `origin/main` instead.
|
|
30
|
+
|
|
31
|
+
### Worktrees
|
|
32
|
+
|
|
33
|
+
If a merged branch is checked out in a linked worktree, `git trim` removes the worktree first and then deletes the branch. Worktrees with uncommitted changes or untracked files are left alone, along with their branch:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
$ git trim
|
|
37
|
+
Removed worktree /Users/you/src/project/feature-a
|
|
38
|
+
Deleted branch feature-a (was fa68cf94).
|
|
39
|
+
Skipping branch 'feature-b': worktree at /Users/you/src/project/feature-b has local changes
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Commit or stash the local changes and run `git trim` again to clean up the rest.
|
|
43
|
+
|
|
44
|
+
### Protected branches
|
|
26
45
|
|
|
27
46
|
The `.git-protected-branches` file can reside in the current directory or any parent directory. Branch names are each listed on a line in the file. For example:
|
|
28
47
|
|
|
@@ -32,9 +51,13 @@ staging
|
|
|
32
51
|
production
|
|
33
52
|
```
|
|
34
53
|
|
|
54
|
+
## Releasing
|
|
55
|
+
|
|
56
|
+
Releases are cut from the GitHub Actions **Release** workflow (Actions → Release → Run workflow → enter a version like `0.2.0`). The workflow runs the specs, bumps `lib/git-trim/version.rb`, tags `v<version>`, publishes to RubyGems via [trusted publishing](https://guides.rubygems.org/trusted-publishing/) (no API key), and creates a GitHub release.
|
|
57
|
+
|
|
35
58
|
## Contributing
|
|
36
59
|
|
|
37
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
60
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/cpetersen/git-trim. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
38
61
|
|
|
39
62
|
## License
|
|
40
63
|
|
|
@@ -42,4 +65,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
|
42
65
|
|
|
43
66
|
## Code of Conduct
|
|
44
67
|
|
|
45
|
-
Everyone interacting in the Git::Trim project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
|
68
|
+
Everyone interacting in the Git::Trim project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/cpetersen/git-trim/blob/main/CODE_OF_CONDUCT.md).
|
data/bin/git-trim
CHANGED
data/git-trim.gemspec
CHANGED
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
|
11
11
|
|
|
12
12
|
spec.summary = %q{A script to remove all merged branches that aren't protected.}
|
|
13
13
|
spec.description = %q{A script to remove all merged branches that aren't specified in the .git-protected-branches file.}
|
|
14
|
-
spec.homepage = "https://github.com/
|
|
14
|
+
spec.homepage = "https://github.com/cpetersen/git-trim"
|
|
15
15
|
spec.license = "MIT"
|
|
16
16
|
|
|
17
17
|
# Specify which files should be added to the gem when it is released.
|
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
|
23
23
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
24
24
|
spec.require_paths = ["lib", "bin"]
|
|
25
25
|
|
|
26
|
-
spec.add_development_dependency "bundler", "
|
|
26
|
+
spec.add_development_dependency "bundler", ">= 1.16"
|
|
27
27
|
spec.add_development_dependency "rake", "~> 13.0"
|
|
28
28
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
29
29
|
end
|
data/lib/git-trim/version.rb
CHANGED
data/lib/git-trim.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "git-trim/version"
|
|
2
|
+
require "shellwords"
|
|
2
3
|
|
|
3
4
|
class GitTrim
|
|
4
5
|
def run(argv=nil)
|
|
@@ -10,11 +11,59 @@ class GitTrim
|
|
|
10
11
|
protected_branches ||= []
|
|
11
12
|
protected_branches << "main"
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
base = base_ref
|
|
15
|
+
unless base
|
|
16
|
+
warn "git-trim: neither 'main' nor 'origin/main' exists; nothing to trim against"
|
|
17
|
+
return 1
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
branches = %x{git branch --merged #{Shellwords.escape(base)} --format='%(refname:short)'}.split("\n").collect(&:strip)
|
|
14
21
|
branches -= protected_branches
|
|
22
|
+
branches -= [current_branch]
|
|
23
|
+
|
|
24
|
+
worktrees = linked_worktrees
|
|
15
25
|
|
|
16
26
|
branches.each do |branch|
|
|
17
|
-
|
|
27
|
+
if (path = worktrees[branch])
|
|
28
|
+
output = %x{git worktree remove #{Shellwords.escape(path)} 2>&1}
|
|
29
|
+
unless $?.success?
|
|
30
|
+
if output.include?("contains modified or untracked files")
|
|
31
|
+
puts "Skipping branch '#{branch}': worktree at #{path} has local changes"
|
|
32
|
+
else
|
|
33
|
+
puts "Skipping branch '#{branch}': could not remove worktree at #{path}"
|
|
34
|
+
puts output
|
|
35
|
+
end
|
|
36
|
+
next
|
|
37
|
+
end
|
|
38
|
+
puts "Removed worktree #{path}"
|
|
39
|
+
end
|
|
40
|
+
puts %x{git branch -d #{Shellwords.escape(branch)}}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
0
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def current_branch
|
|
47
|
+
%x{git branch --show-current}.strip
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Local main when it exists; otherwise origin/main (e.g. bare-repo +
|
|
51
|
+
# worktrees layouts where no local main is checked out). Nil if neither.
|
|
52
|
+
def base_ref
|
|
53
|
+
["main", "origin/main"].find do |ref|
|
|
54
|
+
%x{git rev-parse --verify --quiet #{Shellwords.escape(ref)}}
|
|
55
|
+
$?.success?
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Maps branch name => worktree path for linked worktrees. The first entry
|
|
60
|
+
# in `git worktree list` is the main worktree, which is never removable.
|
|
61
|
+
def linked_worktrees
|
|
62
|
+
entries = %x{git worktree list --porcelain}.split("\n\n")
|
|
63
|
+
entries.drop(1).each_with_object({}) do |entry, map|
|
|
64
|
+
path = entry[/^worktree (.+)$/, 1]
|
|
65
|
+
branch = entry[/^branch refs\/heads\/(.+)$/, 1]
|
|
66
|
+
map[branch] = path if path && branch
|
|
18
67
|
end
|
|
19
68
|
end
|
|
20
69
|
|
metadata
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: git-trim
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Christopher Petersen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-06-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '1.16'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.16'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
@@ -61,6 +61,8 @@ executables:
|
|
|
61
61
|
extensions: []
|
|
62
62
|
extra_rdoc_files: []
|
|
63
63
|
files:
|
|
64
|
+
- ".github/workflows/ci.yml"
|
|
65
|
+
- ".github/workflows/release.yml"
|
|
64
66
|
- ".gitignore"
|
|
65
67
|
- ".rspec"
|
|
66
68
|
- ".travis.yml"
|
|
@@ -74,7 +76,7 @@ files:
|
|
|
74
76
|
- git-trim.gemspec
|
|
75
77
|
- lib/git-trim.rb
|
|
76
78
|
- lib/git-trim/version.rb
|
|
77
|
-
homepage: https://github.com/
|
|
79
|
+
homepage: https://github.com/cpetersen/git-trim
|
|
78
80
|
licenses:
|
|
79
81
|
- MIT
|
|
80
82
|
metadata: {}
|
|
@@ -94,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
94
96
|
- !ruby/object:Gem::Version
|
|
95
97
|
version: '0'
|
|
96
98
|
requirements: []
|
|
97
|
-
rubygems_version: 3.
|
|
99
|
+
rubygems_version: 3.5.22
|
|
98
100
|
signing_key:
|
|
99
101
|
specification_version: 4
|
|
100
102
|
summary: A script to remove all merged branches that aren't protected.
|