-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit-subtree-push
More file actions
executable file
·110 lines (103 loc) · 3.07 KB
/
git-subtree-push
File metadata and controls
executable file
·110 lines (103 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/bin/sh
# git-subtree-push: Use git to publish a monorepo's git subtrees.
#
# Syntax:
#
# ```sh
# git-subtree-push
# git-subtree-push --force
# ```
#
# ## Setup
#
# For each subtree, create a marker file:
#
# ```sh
# touch my_monorepo/my_project_1/.git-subtree-push
# touch my_monorepo/my_project_2/.git-subtree-push
# ```
#
# For each subtree, add a remote:
#
# ```sh
# git remote add my_project_1 git@github.com:my_user_name/my_project_1.git
# git remote add my_project_2 git@github.com:my_user_name/my_project_2.git
# ```
#
# Notes:
#
# - The target repos must exist first (create them empty, no README, .gitignore, etc.)
# - `git subtree push` rewrites history so only commits touching that prefix are included
# - For large repos, the first push can be slow since it replays the entire history
# - To re-run later after new commits, just repeat the `git subtree push` commands
#
# ## git-subtree push --force
#
# The winning pattern for force-pushing subtrees is:
#
# ```sh
# git subtree split --prefix=<local-subdirectory> --branch <temporary-local-branch-name>
# git push <remote> <temporary-local-branch-name>:<remote-branch-name> --force
# git branch -D <temporary-local-branch-name>
# ```
#
# The `--branch` flag is the important step because it creates a temporary local
# branch from the split, bypassing any stale cache that could cause an error
# such as the error message "no new revisions found".
#
# ## Tracking
#
# - Package: git-subtree-push
# - Version: 1.0.0
# - Created: 2026-03-15T20:51:39Z
# - Updated: 2026-03-26T12:46:01Z
# - License: MIT or Apache-2.0 or GPL-2.0 or GPL-3.0 or contact us for more
# - Contact: Joel Parker Henderson <joel@joelparkerhenderson.com>
set -euf
top="$(git rev-parse --show-toplevel)"
branch="main"
help(){
cat << HERE
git-subtree-push: Use git to publish a git monorepo's git subtrees.
Syntax:
git-subtree-push
git-subtree-push --force
HERE
}
# Return all subdirectories that contain indicator file `.git-subtree-push`.
subdirectories() (
pos=$(( ${#top} + 2 ))
find "$top" -name .git-subtree-push | xargs dirname | cut -c $pos-
)
case $# in
0)
for subdirectory in $(subdirectories); do
remote=$(basename "$subdirectory")
set -x
git subtree push --prefix="$subdirectory" "$remote" "$branch"
{ set +x; } 2>/dev/null
done
;;
1)
case "$1" in
-h|--help)
help; exit 0
;;
-f|--force)
for subdirectory in $(subdirectories); do
remote=$(basename "$subdirectory")
git_subtree_push_branch="git-subtree-push-$remote"
set -x
git subtree split --prefix="$subdirectory" --branch "$git_subtree_push_branch" && git push "$remote" "$git_subtree_push_branch:$branch" --force && git branch -D "$git_subtree_push_branch"
{ set +x; } 2>/dev/null
done
;;
*)
help; exit 1
;;
esac
;;
*)
help; exit 1
;;
esac