Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | # |
| 3 | # git-subtree.sh: split/join git repositories in subdirectories of this one |
| 4 | # |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 5 | # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com> |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 6 | # |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 7 | if [ $# -eq 0 ]; then |
| 8 | set -- -h |
| 9 | fi |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 10 | OPTS_SPEC="\ |
Avery Pennarun | f4f2955 | 2009-05-30 01:10:14 -0400 | [diff] [blame] | 11 | git subtree add --prefix=<prefix> <commit> |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 12 | git subtree merge --prefix=<prefix> <commit> |
| 13 | git subtree pull --prefix=<prefix> <repository> <refspec...> |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 14 | git subtree push --prefix=<prefix> <repository> <refspec...> |
Avery Pennarun | f4f2955 | 2009-05-30 01:10:14 -0400 | [diff] [blame] | 15 | git subtree split --prefix=<prefix> <commit...> |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 16 | -- |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 17 | h,help show the help |
| 18 | q quiet |
Avery Pennarun | 942dce5 | 2009-04-26 18:06:08 -0400 | [diff] [blame] | 19 | d show debug messages |
Jakub Suder | 6e25f79 | 2010-01-12 22:38:21 +0100 | [diff] [blame] | 20 | P,prefix= the name of the subdir to split out |
Jakub Suder | 2da0969 | 2010-01-09 19:55:35 +0100 | [diff] [blame] | 21 | m,message= use the given message as the commit message for the merge commit |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 22 | options for 'split' |
Avery Pennarun | d0eb1b1 | 2009-04-26 08:59:12 -0400 | [diff] [blame] | 23 | annotate= add a prefix to commit message of new commits |
Avery Pennarun | 43a3951 | 2009-05-30 01:05:43 -0400 | [diff] [blame] | 24 | b,branch= create a new branch from the split subtree |
| 25 | ignore-joins ignore prior --rejoin commits |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 26 | onto= try connecting new tree to an existing one |
| 27 | rejoin merge the new branch back into HEAD |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 28 | options for 'add', 'merge', 'pull' and 'push' |
Avery Pennarun | 8e79043 | 2009-05-30 00:48:07 -0400 | [diff] [blame] | 29 | squash merge subtree changes as a single commit |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 30 | " |
Cole Stanfield | 11f1511 | 2010-09-13 13:16:57 -0600 | [diff] [blame] | 31 | eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)" |
Avery Pennarun | 9c632ea | 2010-06-24 01:53:05 -0400 | [diff] [blame] | 32 | |
Avery Pennarun | df2302d | 2010-06-24 16:57:58 -0400 | [diff] [blame] | 33 | PATH=$PATH:$(git --exec-path) |
Avery Pennarun | 33aaa69 | 2009-08-26 10:41:03 -0400 | [diff] [blame] | 34 | . git-sh-setup |
Avery Pennarun | 9c632ea | 2010-06-24 01:53:05 -0400 | [diff] [blame] | 35 | |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 36 | require_work_tree |
| 37 | |
| 38 | quiet= |
Avery Pennarun | 43a3951 | 2009-05-30 01:05:43 -0400 | [diff] [blame] | 39 | branch= |
Avery Pennarun | 942dce5 | 2009-04-26 18:06:08 -0400 | [diff] [blame] | 40 | debug= |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 41 | command= |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 42 | onto= |
| 43 | rejoin= |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 44 | ignore_joins= |
Avery Pennarun | d0eb1b1 | 2009-04-26 08:59:12 -0400 | [diff] [blame] | 45 | annotate= |
Avery Pennarun | 8e79043 | 2009-05-30 00:48:07 -0400 | [diff] [blame] | 46 | squash= |
Jakub Suder | 2da0969 | 2010-01-09 19:55:35 +0100 | [diff] [blame] | 47 | message= |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 48 | |
| 49 | debug() |
| 50 | { |
Avery Pennarun | 942dce5 | 2009-04-26 18:06:08 -0400 | [diff] [blame] | 51 | if [ -n "$debug" ]; then |
| 52 | echo "$@" >&2 |
| 53 | fi |
| 54 | } |
| 55 | |
| 56 | say() |
| 57 | { |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 58 | if [ -z "$quiet" ]; then |
| 59 | echo "$@" >&2 |
| 60 | fi |
| 61 | } |
| 62 | |
Avery Pennarun | 2573354 | 2009-04-24 14:24:38 -0400 | [diff] [blame] | 63 | assert() |
| 64 | { |
| 65 | if "$@"; then |
| 66 | : |
| 67 | else |
| 68 | die "assertion failed: " "$@" |
| 69 | fi |
| 70 | } |
| 71 | |
| 72 | |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 73 | #echo "Options: $*" |
| 74 | |
| 75 | while [ $# -gt 0 ]; do |
| 76 | opt="$1" |
| 77 | shift |
| 78 | case "$opt" in |
| 79 | -q) quiet=1 ;; |
Avery Pennarun | 942dce5 | 2009-04-26 18:06:08 -0400 | [diff] [blame] | 80 | -d) debug=1 ;; |
Avery Pennarun | d0eb1b1 | 2009-04-26 08:59:12 -0400 | [diff] [blame] | 81 | --annotate) annotate="$1"; shift ;; |
| 82 | --no-annotate) annotate= ;; |
Avery Pennarun | 43a3951 | 2009-05-30 01:05:43 -0400 | [diff] [blame] | 83 | -b) branch="$1"; shift ;; |
Jakub Suder | 6e25f79 | 2010-01-12 22:38:21 +0100 | [diff] [blame] | 84 | -P) prefix="$1"; shift ;; |
Jakub Suder | 2da0969 | 2010-01-09 19:55:35 +0100 | [diff] [blame] | 85 | -m) message="$1"; shift ;; |
Avery Pennarun | 9a8821f | 2009-04-24 22:57:14 -0400 | [diff] [blame] | 86 | --no-prefix) prefix= ;; |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 87 | --onto) onto="$1"; shift ;; |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 88 | --no-onto) onto= ;; |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 89 | --rejoin) rejoin=1 ;; |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 90 | --no-rejoin) rejoin= ;; |
| 91 | --ignore-joins) ignore_joins=1 ;; |
| 92 | --no-ignore-joins) ignore_joins= ;; |
Avery Pennarun | 8e79043 | 2009-05-30 00:48:07 -0400 | [diff] [blame] | 93 | --squash) squash=1 ;; |
| 94 | --no-squash) squash= ;; |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 95 | --) break ;; |
Avery Pennarun | 43a3951 | 2009-05-30 01:05:43 -0400 | [diff] [blame] | 96 | *) die "Unexpected option: $opt" ;; |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 97 | esac |
| 98 | done |
| 99 | |
| 100 | command="$1" |
| 101 | shift |
| 102 | case "$command" in |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 103 | add|merge|pull) default= ;; |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 104 | split|push) default="--default HEAD" ;; |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 105 | *) die "Unknown command '$command'" ;; |
| 106 | esac |
| 107 | |
Avery Pennarun | 9a8821f | 2009-04-24 22:57:14 -0400 | [diff] [blame] | 108 | if [ -z "$prefix" ]; then |
| 109 | die "You must provide the --prefix option." |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 110 | fi |
Win Treese | ec54f0d | 2010-02-05 22:02:43 -0500 | [diff] [blame] | 111 | |
Avery Pennarun | 77ba305 | 2010-02-08 15:00:42 -0500 | [diff] [blame] | 112 | case "$command" in |
| 113 | add) [ -e "$prefix" ] && |
| 114 | die "prefix '$prefix' already exists." ;; |
| 115 | *) [ -e "$prefix" ] || |
| 116 | die "'$prefix' does not exist; use 'git subtree add'" ;; |
| 117 | esac |
Win Treese | ec54f0d | 2010-02-05 22:02:43 -0500 | [diff] [blame] | 118 | |
Avery Pennarun | 6f2012c | 2009-10-02 15:22:15 -0400 | [diff] [blame] | 119 | dir="$(dirname "$prefix/.")" |
Avery Pennarun | 9a8821f | 2009-04-24 22:57:14 -0400 | [diff] [blame] | 120 | |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 121 | if [ "$command" != "pull" -a "$command" != "add" -a "$command" != "push" ]; then |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 122 | revs=$(git rev-parse $default --revs-only "$@") || exit $? |
| 123 | dirs="$(git rev-parse --no-revs --no-flags "$@")" || exit $? |
| 124 | if [ -n "$dirs" ]; then |
| 125 | die "Error: Use --prefix instead of bare filenames." |
| 126 | fi |
Avery Pennarun | 9a8821f | 2009-04-24 22:57:14 -0400 | [diff] [blame] | 127 | fi |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 128 | |
| 129 | debug "command: {$command}" |
| 130 | debug "quiet: {$quiet}" |
| 131 | debug "revs: {$revs}" |
| 132 | debug "dir: {$dir}" |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 133 | debug "opts: {$*}" |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 134 | debug |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 135 | |
| 136 | cache_setup() |
| 137 | { |
Avery Pennarun | 2573354 | 2009-04-24 14:24:38 -0400 | [diff] [blame] | 138 | cachedir="$GIT_DIR/subtree-cache/$$" |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 139 | rm -rf "$cachedir" || die "Can't delete old cachedir: $cachedir" |
| 140 | mkdir -p "$cachedir" || die "Can't create new cachedir: $cachedir" |
| 141 | debug "Using cachedir: $cachedir" >&2 |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | cache_get() |
| 145 | { |
| 146 | for oldrev in $*; do |
| 147 | if [ -r "$cachedir/$oldrev" ]; then |
| 148 | read newrev <"$cachedir/$oldrev" |
| 149 | echo $newrev |
| 150 | fi |
| 151 | done |
| 152 | } |
| 153 | |
| 154 | cache_set() |
| 155 | { |
| 156 | oldrev="$1" |
| 157 | newrev="$2" |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 158 | if [ "$oldrev" != "latest_old" \ |
| 159 | -a "$oldrev" != "latest_new" \ |
| 160 | -a -e "$cachedir/$oldrev" ]; then |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 161 | die "cache for $oldrev already exists!" |
| 162 | fi |
| 163 | echo "$newrev" >"$cachedir/$oldrev" |
| 164 | } |
| 165 | |
Avery Pennarun | 43a3951 | 2009-05-30 01:05:43 -0400 | [diff] [blame] | 166 | rev_exists() |
| 167 | { |
| 168 | if git rev-parse "$1" >/dev/null 2>&1; then |
| 169 | return 0 |
| 170 | else |
| 171 | return 1 |
| 172 | fi |
| 173 | } |
| 174 | |
Jakub Suder | 0a56294 | 2010-01-09 19:56:05 +0100 | [diff] [blame] | 175 | rev_is_descendant_of_branch() |
| 176 | { |
| 177 | newrev="$1" |
| 178 | branch="$2" |
| 179 | branch_hash=$(git rev-parse $branch) |
Jakub Suder | 6bd910a | 2010-01-12 23:34:52 +0100 | [diff] [blame] | 180 | match=$(git rev-list -1 $branch_hash ^$newrev) |
Jakub Suder | 0a56294 | 2010-01-09 19:56:05 +0100 | [diff] [blame] | 181 | |
Jakub Suder | 6bd910a | 2010-01-12 23:34:52 +0100 | [diff] [blame] | 182 | if [ -z "$match" ]; then |
Jakub Suder | 0a56294 | 2010-01-09 19:56:05 +0100 | [diff] [blame] | 183 | return 0 |
| 184 | else |
| 185 | return 1 |
| 186 | fi |
| 187 | } |
| 188 | |
Avery Pennarun | b9de535 | 2009-04-25 00:06:45 -0400 | [diff] [blame] | 189 | # if a commit doesn't have a parent, this might not work. But we only want |
| 190 | # to remove the parent from the rev-list, and since it doesn't exist, it won't |
| 191 | # be there anyway, so do nothing in that case. |
| 192 | try_remove_previous() |
| 193 | { |
Avery Pennarun | 43a3951 | 2009-05-30 01:05:43 -0400 | [diff] [blame] | 194 | if rev_exists "$1^"; then |
Avery Pennarun | b9de535 | 2009-04-25 00:06:45 -0400 | [diff] [blame] | 195 | echo "^$1^" |
| 196 | fi |
| 197 | } |
| 198 | |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 199 | find_latest_squash() |
| 200 | { |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 201 | debug "Looking for latest squash ($dir)..." |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 202 | dir="$1" |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 203 | sq= |
| 204 | main= |
| 205 | sub= |
Avery Pennarun | 6f2012c | 2009-10-02 15:22:15 -0400 | [diff] [blame] | 206 | git log --grep="^git-subtree-dir: $dir/*\$" \ |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 207 | --pretty=format:'START %H%n%s%n%n%b%nEND%n' HEAD | |
| 208 | while read a b junk; do |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 209 | debug "$a $b $junk" |
| 210 | debug "{{$sq/$main/$sub}}" |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 211 | case "$a" in |
| 212 | START) sq="$b" ;; |
| 213 | git-subtree-mainline:) main="$b" ;; |
| 214 | git-subtree-split:) sub="$b" ;; |
| 215 | END) |
| 216 | if [ -n "$sub" ]; then |
| 217 | if [ -n "$main" ]; then |
| 218 | # a rejoin commit? |
| 219 | # Pretend its sub was a squash. |
| 220 | sq="$sub" |
| 221 | fi |
| 222 | debug "Squash found: $sq $sub" |
| 223 | echo "$sq" "$sub" |
| 224 | break |
| 225 | fi |
| 226 | sq= |
| 227 | main= |
| 228 | sub= |
| 229 | ;; |
| 230 | esac |
| 231 | done |
| 232 | } |
| 233 | |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 234 | find_existing_splits() |
| 235 | { |
| 236 | debug "Looking for prior splits..." |
| 237 | dir="$1" |
| 238 | revs="$2" |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 239 | main= |
| 240 | sub= |
Avery Pennarun | 6f2012c | 2009-10-02 15:22:15 -0400 | [diff] [blame] | 241 | git log --grep="^git-subtree-dir: $dir/*\$" \ |
Avery Pennarun | 1a8c36d | 2009-05-30 03:33:39 -0400 | [diff] [blame] | 242 | --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs | |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 243 | while read a b junk; do |
| 244 | case "$a" in |
Avery Pennarun | 2275f70 | 2009-10-02 16:09:09 -0400 | [diff] [blame] | 245 | START) sq="$b" ;; |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 246 | git-subtree-mainline:) main="$b" ;; |
| 247 | git-subtree-split:) sub="$b" ;; |
Avery Pennarun | 7ee9eef | 2009-05-30 01:28:20 -0400 | [diff] [blame] | 248 | END) |
Avery Pennarun | 2275f70 | 2009-10-02 16:09:09 -0400 | [diff] [blame] | 249 | debug " Main is: '$main'" |
Avery Pennarun | 1a8c36d | 2009-05-30 03:33:39 -0400 | [diff] [blame] | 250 | if [ -z "$main" -a -n "$sub" ]; then |
| 251 | # squash commits refer to a subtree |
Avery Pennarun | 2275f70 | 2009-10-02 16:09:09 -0400 | [diff] [blame] | 252 | debug " Squash: $sq from $sub" |
Avery Pennarun | 1a8c36d | 2009-05-30 03:33:39 -0400 | [diff] [blame] | 253 | cache_set "$sq" "$sub" |
| 254 | fi |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 255 | if [ -n "$main" -a -n "$sub" ]; then |
| 256 | debug " Prior: $main -> $sub" |
| 257 | cache_set $main $sub |
Pelle Wessman | 39f5fff | 2010-05-20 22:40:09 +0200 | [diff] [blame] | 258 | cache_set $sub $sub |
Avery Pennarun | b9de535 | 2009-04-25 00:06:45 -0400 | [diff] [blame] | 259 | try_remove_previous "$main" |
| 260 | try_remove_previous "$sub" |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 261 | fi |
Avery Pennarun | 7ee9eef | 2009-05-30 01:28:20 -0400 | [diff] [blame] | 262 | main= |
| 263 | sub= |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 264 | ;; |
| 265 | esac |
| 266 | done |
| 267 | } |
| 268 | |
Avery Pennarun | fd9500e | 2009-04-24 14:45:02 -0400 | [diff] [blame] | 269 | copy_commit() |
| 270 | { |
Avery Pennarun | f96bc79 | 2009-05-30 00:47:59 -0400 | [diff] [blame] | 271 | # We're going to set some environment vars here, so |
Avery Pennarun | fd9500e | 2009-04-24 14:45:02 -0400 | [diff] [blame] | 272 | # do it in a subshell to get rid of them safely later |
Avery Pennarun | a64f3a7 | 2009-04-26 16:53:57 -0400 | [diff] [blame] | 273 | debug copy_commit "{$1}" "{$2}" "{$3}" |
Avery Pennarun | fd9500e | 2009-04-24 14:45:02 -0400 | [diff] [blame] | 274 | git log -1 --pretty=format:'%an%n%ae%n%ad%n%cn%n%ce%n%cd%n%s%n%n%b' "$1" | |
| 275 | ( |
| 276 | read GIT_AUTHOR_NAME |
| 277 | read GIT_AUTHOR_EMAIL |
| 278 | read GIT_AUTHOR_DATE |
| 279 | read GIT_COMMITTER_NAME |
| 280 | read GIT_COMMITTER_EMAIL |
| 281 | read GIT_COMMITTER_DATE |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 282 | export GIT_AUTHOR_NAME \ |
| 283 | GIT_AUTHOR_EMAIL \ |
| 284 | GIT_AUTHOR_DATE \ |
| 285 | GIT_COMMITTER_NAME \ |
| 286 | GIT_COMMITTER_EMAIL \ |
| 287 | GIT_COMMITTER_DATE |
Avery Pennarun | d0eb1b1 | 2009-04-26 08:59:12 -0400 | [diff] [blame] | 288 | (echo -n "$annotate"; cat ) | |
Avery Pennarun | fd9500e | 2009-04-24 14:45:02 -0400 | [diff] [blame] | 289 | git commit-tree "$2" $3 # reads the rest of stdin |
| 290 | ) || die "Can't copy commit $1" |
| 291 | } |
| 292 | |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 293 | add_msg() |
| 294 | { |
| 295 | dir="$1" |
| 296 | latest_old="$2" |
| 297 | latest_new="$3" |
Jakub Suder | 2da0969 | 2010-01-09 19:55:35 +0100 | [diff] [blame] | 298 | if [ -n "$message" ]; then |
| 299 | commit_message="$message" |
| 300 | else |
| 301 | commit_message="Add '$dir/' from commit '$latest_new'" |
| 302 | fi |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 303 | cat <<-EOF |
Jakub Suder | 2da0969 | 2010-01-09 19:55:35 +0100 | [diff] [blame] | 304 | $commit_message |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 305 | |
| 306 | git-subtree-dir: $dir |
| 307 | git-subtree-mainline: $latest_old |
| 308 | git-subtree-split: $latest_new |
| 309 | EOF |
| 310 | } |
| 311 | |
Jakub Suder | 2da0969 | 2010-01-09 19:55:35 +0100 | [diff] [blame] | 312 | add_squashed_msg() |
| 313 | { |
| 314 | if [ -n "$message" ]; then |
| 315 | echo "$message" |
| 316 | else |
| 317 | echo "Merge commit '$1' as '$2'" |
| 318 | fi |
| 319 | } |
| 320 | |
Avery Pennarun | 7ee9eef | 2009-05-30 01:28:20 -0400 | [diff] [blame] | 321 | rejoin_msg() |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 322 | { |
| 323 | dir="$1" |
| 324 | latest_old="$2" |
| 325 | latest_new="$3" |
Jakub Suder | 2da0969 | 2010-01-09 19:55:35 +0100 | [diff] [blame] | 326 | if [ -n "$message" ]; then |
| 327 | commit_message="$message" |
| 328 | else |
| 329 | commit_message="Split '$dir/' into commit '$latest_new'" |
| 330 | fi |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 331 | cat <<-EOF |
Jakub Suder | 1262916 | 2010-01-12 22:38:34 +0100 | [diff] [blame] | 332 | $commit_message |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 333 | |
| 334 | git-subtree-dir: $dir |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 335 | git-subtree-mainline: $latest_old |
| 336 | git-subtree-split: $latest_new |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 337 | EOF |
| 338 | } |
| 339 | |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 340 | squash_msg() |
| 341 | { |
| 342 | dir="$1" |
| 343 | oldsub="$2" |
| 344 | newsub="$3" |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 345 | newsub_short=$(git rev-parse --short "$newsub") |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 346 | |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 347 | if [ -n "$oldsub" ]; then |
| 348 | oldsub_short=$(git rev-parse --short "$oldsub") |
| 349 | echo "Squashed '$dir/' changes from $oldsub_short..$newsub_short" |
| 350 | echo |
| 351 | git log --pretty=tformat:'%h %s' "$oldsub..$newsub" |
| 352 | git log --pretty=tformat:'REVERT: %h %s' "$newsub..$oldsub" |
| 353 | else |
| 354 | echo "Squashed '$dir/' content from commit $newsub_short" |
| 355 | fi |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 356 | |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 357 | echo |
| 358 | echo "git-subtree-dir: $dir" |
| 359 | echo "git-subtree-split: $newsub" |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 360 | } |
| 361 | |
Avery Pennarun | 210d083 | 2009-04-24 21:49:19 -0400 | [diff] [blame] | 362 | toptree_for_commit() |
Avery Pennarun | 768d6d1 | 2009-04-24 17:53:10 -0400 | [diff] [blame] | 363 | { |
Avery Pennarun | 210d083 | 2009-04-24 21:49:19 -0400 | [diff] [blame] | 364 | commit="$1" |
| 365 | git log -1 --pretty=format:'%T' "$commit" -- || exit $? |
| 366 | } |
| 367 | |
| 368 | subtree_for_commit() |
| 369 | { |
| 370 | commit="$1" |
| 371 | dir="$2" |
| 372 | git ls-tree "$commit" -- "$dir" | |
Avery Pennarun | 768d6d1 | 2009-04-24 17:53:10 -0400 | [diff] [blame] | 373 | while read mode type tree name; do |
| 374 | assert [ "$name" = "$dir" ] |
Pelle Wessman | 8ac5eca | 2009-09-30 14:29:42 +0200 | [diff] [blame] | 375 | assert [ "$type" = "tree" ] |
Avery Pennarun | 768d6d1 | 2009-04-24 17:53:10 -0400 | [diff] [blame] | 376 | echo $tree |
| 377 | break |
| 378 | done |
| 379 | } |
| 380 | |
| 381 | tree_changed() |
| 382 | { |
| 383 | tree=$1 |
| 384 | shift |
| 385 | if [ $# -ne 1 ]; then |
| 386 | return 0 # weird parents, consider it changed |
| 387 | else |
Avery Pennarun | 210d083 | 2009-04-24 21:49:19 -0400 | [diff] [blame] | 388 | ptree=$(toptree_for_commit $1) |
Avery Pennarun | 768d6d1 | 2009-04-24 17:53:10 -0400 | [diff] [blame] | 389 | if [ "$ptree" != "$tree" ]; then |
| 390 | return 0 # changed |
| 391 | else |
| 392 | return 1 # not changed |
| 393 | fi |
| 394 | fi |
| 395 | } |
| 396 | |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 397 | new_squash_commit() |
| 398 | { |
| 399 | old="$1" |
| 400 | oldsub="$2" |
| 401 | newsub="$3" |
| 402 | tree=$(toptree_for_commit $newsub) || exit $? |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 403 | if [ -n "$old" ]; then |
| 404 | squash_msg "$dir" "$oldsub" "$newsub" | |
| 405 | git commit-tree "$tree" -p "$old" || exit $? |
| 406 | else |
| 407 | squash_msg "$dir" "" "$newsub" | |
| 408 | git commit-tree "$tree" || exit $? |
| 409 | fi |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 410 | } |
| 411 | |
Avery Pennarun | d691265 | 2009-04-24 22:05:30 -0400 | [diff] [blame] | 412 | copy_or_skip() |
| 413 | { |
| 414 | rev="$1" |
| 415 | tree="$2" |
| 416 | newparents="$3" |
| 417 | assert [ -n "$tree" ] |
| 418 | |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 419 | identical= |
Avery Pennarun | 49cf822 | 2009-04-26 17:07:16 -0400 | [diff] [blame] | 420 | nonidentical= |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 421 | p= |
Avery Pennarun | a64f3a7 | 2009-04-26 16:53:57 -0400 | [diff] [blame] | 422 | gotparents= |
Avery Pennarun | d691265 | 2009-04-24 22:05:30 -0400 | [diff] [blame] | 423 | for parent in $newparents; do |
| 424 | ptree=$(toptree_for_commit $parent) || exit $? |
Avery Pennarun | a64f3a7 | 2009-04-26 16:53:57 -0400 | [diff] [blame] | 425 | [ -z "$ptree" ] && continue |
Avery Pennarun | d691265 | 2009-04-24 22:05:30 -0400 | [diff] [blame] | 426 | if [ "$ptree" = "$tree" ]; then |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 427 | # an identical parent could be used in place of this rev. |
| 428 | identical="$parent" |
Avery Pennarun | 49cf822 | 2009-04-26 17:07:16 -0400 | [diff] [blame] | 429 | else |
| 430 | nonidentical="$parent" |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 431 | fi |
Avery Pennarun | a64f3a7 | 2009-04-26 16:53:57 -0400 | [diff] [blame] | 432 | |
| 433 | # sometimes both old parents map to the same newparent; |
| 434 | # eliminate duplicates |
| 435 | is_new=1 |
| 436 | for gp in $gotparents; do |
| 437 | if [ "$gp" = "$parent" ]; then |
| 438 | is_new= |
| 439 | break |
| 440 | fi |
| 441 | done |
| 442 | if [ -n "$is_new" ]; then |
| 443 | gotparents="$gotparents $parent" |
Avery Pennarun | d691265 | 2009-04-24 22:05:30 -0400 | [diff] [blame] | 444 | p="$p -p $parent" |
| 445 | fi |
| 446 | done |
| 447 | |
Avery Pennarun | 795e730 | 2009-04-26 17:44:18 -0400 | [diff] [blame] | 448 | if [ -n "$identical" ]; then |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 449 | echo $identical |
| 450 | else |
| 451 | copy_commit $rev $tree "$p" || exit $? |
| 452 | fi |
Avery Pennarun | d691265 | 2009-04-24 22:05:30 -0400 | [diff] [blame] | 453 | } |
| 454 | |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 455 | ensure_clean() |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 456 | { |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 457 | if ! git diff-index HEAD --exit-code --quiet 2>&1; then |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 458 | die "Working tree has modifications. Cannot add." |
| 459 | fi |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 460 | if ! git diff-index --cached HEAD --exit-code --quiet 2>&1; then |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 461 | die "Index has modifications. Cannot add." |
| 462 | fi |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 463 | } |
| 464 | |
| 465 | cmd_add() |
| 466 | { |
| 467 | if [ -e "$dir" ]; then |
| 468 | die "'$dir' already exists. Cannot add." |
| 469 | fi |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 470 | |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 471 | ensure_clean |
| 472 | |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 473 | if [ $# -eq 1 ]; then |
| 474 | "cmd_add_commit" "$@" |
| 475 | elif [ $# -eq 2 ]; then |
| 476 | "cmd_add_repository" "$@" |
| 477 | else |
| 478 | say "error: parameters were '$@'" |
| 479 | die "Provide either a refspec or a repository and refspec." |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 480 | fi |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 481 | } |
| 482 | |
| 483 | cmd_add_repository() |
| 484 | { |
| 485 | echo "git fetch" "$@" |
| 486 | repository=$1 |
| 487 | refspec=$2 |
| 488 | git fetch "$@" || exit $? |
| 489 | revs=FETCH_HEAD |
| 490 | set -- $revs |
| 491 | cmd_add_commit "$@" |
| 492 | } |
| 493 | |
| 494 | cmd_add_commit() |
| 495 | { |
| 496 | revs=$(git rev-parse $default --revs-only "$@") || exit $? |
| 497 | set -- $revs |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 498 | rev="$1" |
| 499 | |
| 500 | debug "Adding $dir as '$rev'..." |
| 501 | git read-tree --prefix="$dir" $rev || exit $? |
Avery Pennarun | 227f781 | 2009-08-26 10:43:43 -0400 | [diff] [blame] | 502 | git checkout -- "$dir" || exit $? |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 503 | tree=$(git write-tree) || exit $? |
| 504 | |
| 505 | headrev=$(git rev-parse HEAD) || exit $? |
| 506 | if [ -n "$headrev" -a "$headrev" != "$rev" ]; then |
| 507 | headp="-p $headrev" |
| 508 | else |
| 509 | headp= |
| 510 | fi |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 511 | |
| 512 | if [ -n "$squash" ]; then |
| 513 | rev=$(new_squash_commit "" "" "$rev") || exit $? |
Jakub Suder | 2da0969 | 2010-01-09 19:55:35 +0100 | [diff] [blame] | 514 | commit=$(add_squashed_msg "$rev" "$dir" | |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 515 | git commit-tree $tree $headp -p "$rev") || exit $? |
| 516 | else |
| 517 | commit=$(add_msg "$dir" "$headrev" "$rev" | |
| 518 | git commit-tree $tree $headp -p "$rev") || exit $? |
| 519 | fi |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 520 | git reset "$commit" || exit $? |
Avery Pennarun | d713e2d | 2009-05-30 04:11:43 -0400 | [diff] [blame] | 521 | |
| 522 | say "Added dir '$dir'" |
Avery Pennarun | eb7b590 | 2009-04-24 23:28:30 -0400 | [diff] [blame] | 523 | } |
| 524 | |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 525 | cmd_split() |
| 526 | { |
| 527 | debug "Splitting $dir..." |
| 528 | cache_setup || exit $? |
| 529 | |
Avery Pennarun | 33ff583 | 2009-04-24 17:05:14 -0400 | [diff] [blame] | 530 | if [ -n "$onto" ]; then |
Avery Pennarun | 847e868 | 2009-04-24 21:35:50 -0400 | [diff] [blame] | 531 | debug "Reading history for --onto=$onto..." |
Avery Pennarun | 33ff583 | 2009-04-24 17:05:14 -0400 | [diff] [blame] | 532 | git rev-list $onto | |
| 533 | while read rev; do |
| 534 | # the 'onto' history is already just the subdir, so |
| 535 | # any parent we find there can be used verbatim |
Avery Pennarun | 2c71b7c | 2009-04-24 17:42:33 -0400 | [diff] [blame] | 536 | debug " cache: $rev" |
Avery Pennarun | 33ff583 | 2009-04-24 17:05:14 -0400 | [diff] [blame] | 537 | cache_set $rev $rev |
| 538 | done |
| 539 | fi |
| 540 | |
Avery Pennarun | 96db2c0 | 2009-04-24 22:36:06 -0400 | [diff] [blame] | 541 | if [ -n "$ignore_joins" ]; then |
| 542 | unrevs= |
| 543 | else |
| 544 | unrevs="$(find_existing_splits "$dir" "$revs")" |
| 545 | fi |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 546 | |
Avery Pennarun | 1f73862 | 2009-04-26 15:54:42 -0400 | [diff] [blame] | 547 | # We can't restrict rev-list to only $dir here, because some of our |
| 548 | # parents have the $dir contents the root, and those won't match. |
| 549 | # (and rev-list --follow doesn't seem to solve this) |
Jesse Greenwald | 6f4f84f | 2010-11-09 08:34:49 -0600 | [diff] [blame^] | 550 | grl='git rev-list --topo-order --reverse --parents $revs $unrevs' |
Avery Pennarun | 942dce5 | 2009-04-26 18:06:08 -0400 | [diff] [blame] | 551 | revmax=$(eval "$grl" | wc -l) |
| 552 | revcount=0 |
| 553 | createcount=0 |
| 554 | eval "$grl" | |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 555 | while read rev parents; do |
Avery Pennarun | 942dce5 | 2009-04-26 18:06:08 -0400 | [diff] [blame] | 556 | revcount=$(($revcount + 1)) |
Avery Pennarun | e2d0a45 | 2010-02-02 10:30:11 -0500 | [diff] [blame] | 557 | say -n "$revcount/$revmax ($createcount)
" |
Avery Pennarun | 2c71b7c | 2009-04-24 17:42:33 -0400 | [diff] [blame] | 558 | debug "Processing commit: $rev" |
| 559 | exists=$(cache_get $rev) |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 560 | if [ -n "$exists" ]; then |
| 561 | debug " prior: $exists" |
| 562 | continue |
| 563 | fi |
Avery Pennarun | 942dce5 | 2009-04-26 18:06:08 -0400 | [diff] [blame] | 564 | createcount=$(($createcount + 1)) |
Avery Pennarun | 2c71b7c | 2009-04-24 17:42:33 -0400 | [diff] [blame] | 565 | debug " parents: $parents" |
| 566 | newparents=$(cache_get $parents) |
| 567 | debug " newparents: $newparents" |
Avery Pennarun | 8b4a77f | 2009-04-24 16:48:08 -0400 | [diff] [blame] | 568 | |
Avery Pennarun | 210d083 | 2009-04-24 21:49:19 -0400 | [diff] [blame] | 569 | tree=$(subtree_for_commit $rev "$dir") |
Avery Pennarun | 768d6d1 | 2009-04-24 17:53:10 -0400 | [diff] [blame] | 570 | debug " tree is: $tree" |
Avery Pennarun | 7ee9eef | 2009-05-30 01:28:20 -0400 | [diff] [blame] | 571 | |
| 572 | # ugly. is there no better way to tell if this is a subtree |
| 573 | # vs. a mainline commit? Does it matter? |
Jakub Suder | da949cc | 2010-01-09 23:01:39 +0100 | [diff] [blame] | 574 | if [ -z $tree ]; then |
Pelle Wessman | 39f5fff | 2010-05-20 22:40:09 +0200 | [diff] [blame] | 575 | if [ -n "$newparents" ]; then |
| 576 | cache_set $rev $rev |
| 577 | fi |
Jakub Suder | da949cc | 2010-01-09 23:01:39 +0100 | [diff] [blame] | 578 | continue |
| 579 | fi |
Avery Pennarun | 768d6d1 | 2009-04-24 17:53:10 -0400 | [diff] [blame] | 580 | |
Avery Pennarun | d691265 | 2009-04-24 22:05:30 -0400 | [diff] [blame] | 581 | newrev=$(copy_or_skip "$rev" "$tree" "$newparents") || exit $? |
Avery Pennarun | 768d6d1 | 2009-04-24 17:53:10 -0400 | [diff] [blame] | 582 | debug " newrev is: $newrev" |
| 583 | cache_set $rev $newrev |
| 584 | cache_set latest_new $newrev |
| 585 | cache_set latest_old $rev |
Avery Pennarun | 2573354 | 2009-04-24 14:24:38 -0400 | [diff] [blame] | 586 | done || exit $? |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 587 | latest_new=$(cache_get latest_new) |
| 588 | if [ -z "$latest_new" ]; then |
Avery Pennarun | e25a6bf | 2009-04-24 14:52:27 -0400 | [diff] [blame] | 589 | die "No new revisions were found" |
| 590 | fi |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 591 | |
| 592 | if [ -n "$rejoin" ]; then |
| 593 | debug "Merging split branch into HEAD..." |
| 594 | latest_old=$(cache_get latest_old) |
| 595 | git merge -s ours \ |
Avery Pennarun | 7ee9eef | 2009-05-30 01:28:20 -0400 | [diff] [blame] | 596 | -m "$(rejoin_msg $dir $latest_old $latest_new)" \ |
Avery Pennarun | ea28d67 | 2009-04-30 21:57:32 -0400 | [diff] [blame] | 597 | $latest_new >&2 || exit $? |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 598 | fi |
Avery Pennarun | 43a3951 | 2009-05-30 01:05:43 -0400 | [diff] [blame] | 599 | if [ -n "$branch" ]; then |
Jakub Suder | 0a56294 | 2010-01-09 19:56:05 +0100 | [diff] [blame] | 600 | if rev_exists "refs/heads/$branch"; then |
| 601 | if ! rev_is_descendant_of_branch $latest_new $branch; then |
| 602 | die "Branch '$branch' is not an ancestor of commit '$latest_new'." |
| 603 | fi |
| 604 | action='Updated' |
| 605 | else |
| 606 | action='Created' |
| 607 | fi |
| 608 | git update-ref -m 'subtree split' "refs/heads/$branch" $latest_new || exit $? |
| 609 | say "$action branch '$branch'" |
Avery Pennarun | 43a3951 | 2009-05-30 01:05:43 -0400 | [diff] [blame] | 610 | fi |
Avery Pennarun | b77172f | 2009-04-24 15:48:41 -0400 | [diff] [blame] | 611 | echo $latest_new |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 612 | exit 0 |
| 613 | } |
| 614 | |
| 615 | cmd_merge() |
| 616 | { |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 617 | revs=$(git rev-parse $default --revs-only "$@") || exit $? |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 618 | ensure_clean |
| 619 | |
| 620 | set -- $revs |
| 621 | if [ $# -ne 1 ]; then |
| 622 | die "You must provide exactly one revision. Got: '$revs'" |
| 623 | fi |
| 624 | rev="$1" |
| 625 | |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 626 | if [ -n "$squash" ]; then |
| 627 | first_split="$(find_latest_squash "$dir")" |
| 628 | if [ -z "$first_split" ]; then |
| 629 | die "Can't squash-merge: '$dir' was never added." |
| 630 | fi |
| 631 | set $first_split |
| 632 | old=$1 |
| 633 | sub=$2 |
Avery Pennarun | eb4fb91 | 2009-05-30 03:33:17 -0400 | [diff] [blame] | 634 | if [ "$sub" = "$rev" ]; then |
| 635 | say "Subtree is already at commit $rev." |
| 636 | exit 0 |
| 637 | fi |
Avery Pennarun | 1cc2cff | 2009-05-30 03:18:27 -0400 | [diff] [blame] | 638 | new=$(new_squash_commit "$old" "$sub" "$rev") || exit $? |
| 639 | debug "New squash commit: $new" |
| 640 | rev="$new" |
| 641 | fi |
Pelle Wessman | 448e71e | 2010-05-07 21:21:25 +0200 | [diff] [blame] | 642 | |
| 643 | version=$(git version) |
| 644 | if [ "$version" \< "git version 1.7" ]; then |
| 645 | if [ -n "$message" ]; then |
| 646 | git merge -s subtree --message="$message" $rev |
| 647 | else |
| 648 | git merge -s subtree $rev |
| 649 | fi |
Avery Pennarun | 349a70d | 2010-02-06 15:05:17 -0500 | [diff] [blame] | 650 | else |
Pelle Wessman | 448e71e | 2010-05-07 21:21:25 +0200 | [diff] [blame] | 651 | if [ -n "$message" ]; then |
| 652 | git merge -Xsubtree="$prefix" --message="$message" $rev |
| 653 | else |
| 654 | git merge -Xsubtree="$prefix" $rev |
| 655 | fi |
Avery Pennarun | 349a70d | 2010-02-06 15:05:17 -0500 | [diff] [blame] | 656 | fi |
Avery Pennarun | 0ca71b3 | 2009-04-24 14:13:34 -0400 | [diff] [blame] | 657 | } |
| 658 | |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 659 | cmd_pull() |
| 660 | { |
| 661 | ensure_clean |
Avery Pennarun | e31d1e2 | 2009-10-02 18:23:54 -0400 | [diff] [blame] | 662 | git fetch "$@" || exit $? |
| 663 | revs=FETCH_HEAD |
Wayne Walter | c00d1d1 | 2010-02-13 14:32:21 -0500 | [diff] [blame] | 664 | set -- $revs |
| 665 | cmd_merge "$@" |
| 666 | } |
| 667 | |
| 668 | cmd_push() |
| 669 | { |
| 670 | if [ $# -ne 2 ]; then |
| 671 | die "You must provide <repository> <refspec>" |
| 672 | fi |
| 673 | if [ -e "$dir" ]; then |
| 674 | repository=$1 |
| 675 | refspec=$2 |
| 676 | echo "git push using: " $repository $refspec |
| 677 | git push $repository $(git subtree split --prefix=$prefix):refs/heads/$refspec |
| 678 | else |
| 679 | die "'$dir' must already exist. Try 'git subtree add'." |
| 680 | fi |
Avery Pennarun | 13648af | 2009-04-24 23:41:19 -0400 | [diff] [blame] | 681 | } |
| 682 | |
| 683 | "cmd_$command" "$@" |