3 # git-subtree.sh: split/join git repositories in subdirectories of this one
5 # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>
8 git subtree split [--rejoin] [--onto rev] <commit...> -- <path>
11 git subtree does foo and bar!
16 onto= existing subtree revision to connect, if any
17 rejoin merge the new branch back into HEAD
19 eval $
(echo "$OPTS_SPEC" | git rev-parse
--parseopt -- "$@" ||
echo exit $?
)
30 if [ -z "$quiet" ]; then
40 die
"assertion failed: " "$@"
47 while [ $# -gt 0 ]; do
53 --onto) onto
="$1"; shift ;;
63 *) die
"Unknown command '$command'" ;;
66 revs
=$
(git rev-parse
--default HEAD
--revs-only "$@") ||
exit $?
67 dirs="$(git rev-parse --sq --no-revs --no-flags "$@
")" ||
exit $?
69 #echo "dirs is {$dirs}"
70 eval $
(echo set -- $dirs)
71 if [ "$#" -ne 1 ]; then
72 die
"Must provide exactly one subtree dir (got $#)"
76 debug
"command: {$command}"
77 debug
"quiet: {$quiet}"
83 cachedir
="$GIT_DIR/subtree-cache/$$"
84 rm -rf "$cachedir" || die
"Can't delete old cachedir: $cachedir"
85 mkdir
-p "$cachedir" || die
"Can't create new cachedir: $cachedir"
86 debug
"Using cachedir: $cachedir" >&2
92 if [ -r "$cachedir/$oldrev" ]; then
93 read newrev
<"$cachedir/$oldrev"
103 if [ "$oldrev" != "latest_old" \
104 -a "$oldrev" != "latest_new" \
105 -a -e "$cachedir/$oldrev" ]; then
106 die
"cache for $oldrev already exists!"
108 echo "$newrev" >"$cachedir/$oldrev"
113 # We're doing to set some environment vars here, so
114 # do it in a subshell to get rid of them safely later
115 git log
-1 --pretty=format
:'%an%n%ae%n%ad%n%cn%n%ce%n%cd%n%s%n%n%b' "$1" |
118 read GIT_AUTHOR_EMAIL
120 read GIT_COMMITTER_NAME
121 read GIT_COMMITTER_EMAIL
122 read GIT_COMMITTER_DATE
123 export GIT_AUTHOR_NAME \
127 GIT_COMMITTER_EMAIL \
129 git commit-tree
"$2" $3 # reads the rest of stdin
130 ) || die
"Can't copy commit $1"
139 Split changes from '$dir/' into commit '$latest_new'
141 git-subtree-dir: $dir
142 git-subtree-includes: $latest_old
148 debug
"Splitting $dir..."
149 cache_setup ||
exit $?
151 git rev-list
--reverse --parents $revs -- "$dir" |
152 while read rev parents
; do
153 newparents
=$
(cache_get
$parents)
155 debug
"Processing commit: $rev / $newparents"
157 git ls-tree
$rev -- "$dir" |
158 while read mode
type tree name
; do
159 assert
[ "$name" = "$dir" ]
160 debug
" tree is: $tree"
162 for parent
in $newparents; do
166 newrev
=$
(copy_commit
$rev $tree "$p") ||
exit $?
167 debug
" newrev is: $newrev"
168 cache_set
$rev $newrev
169 cache_set latest_new
$newrev
170 cache_set latest_old
$rev
173 latest_new
=$
(cache_get latest_new
)
174 if [ -z "$latest_new" ]; then
175 die
"No new revisions were found"
178 if [ -n "$rejoin" ]; then
179 debug
"Merging split branch into HEAD..."
180 latest_old
=$
(cache_get latest_old
)
182 -m "$(merge_msg $dir $latest_old $latest_new)" \
191 die
"merge command not implemented yet"