Guilt v0.37-rc1
[guilt.git] / guilt-rebase
bloba1714a08a2a71a829fcaef85f7467464bf6cdae4
1 #!/bin/sh
3 # Copyright (c) Josef "Jeff" Sipek, 2007-2013
5 # Heavily based on the long removed sh version of git-cherry
8 USAGE="<upstream>"
9 if [ -z "$GUILT_VERSION" ]; then
10 echo "Invoking `basename "$0"` directly is no longer supported." >&2
11 exit 1
14 _main() {
16 disp "Beware, rebase is currently EXPERIMENTAL."
17 disp "In other words, it might eat your patches."
18 _disp "Do you wish to proceed? [y/N] "
19 read n
20 if [ "$n" != "y" -a "$n" != "Y" ]; then
21 disp "Aborted."
22 exit 0
25 case "$#" in
26 1)
27 upstream=`git rev-parse --verify "$1"` &&
28 ours=`git rev-parse --verify HEAD` || usage
29 limit="$upstream"
32 usage
34 esac
36 # make sure that there are no unapplied changes
37 if ! must_commit_first; then
38 die "Uncommited changes detected. Refresh first."
39 elif [ `wc -l < "$applied"` -eq 0 ]; then
40 die "Nothing to rebase. First, you need to push patches onto the stack."
43 # Note that these list commits in reverse order;
44 # not that the order in inup matters...
45 inup=`git rev-list ^$ours $upstream` &&
46 ours=`git rev-list $ours ^$limit` || exit
48 rebase_dir="$GUILT_DIR/$branch/.rebase.$$"
49 mkdir "$rebase_dir"
52 # calculate the patch ids for all the commits in upstream
54 for c in $inup ; do
55 git diff-tree -p $c
56 done | git patch-id | while read id name ; do
57 echo "$name" >> "$rebase_dir/$id"
58 done
60 # backup the status file, so we don't have to do more work to figure out all
61 # the patches that were pushed before we started rebasing
62 cp "$applied" "$rebase_dir/status"
64 disp "First, poping all patches..."
65 pop_all_patches
66 git merge --no-commit $upstream > /dev/null 2> /dev/null
68 disp ""
69 log=`git log -1 --no-decorate --pretty=oneline`
70 disp "HEAD is now at `echo $log | cut -c 1-7`... `echo "$log" | cut -c 41-`"
73 # For each previously applied patch:
74 # 1) calculate the patchid
75 # 2) if the patchid matches any of the upstream commits' patchids...
76 # a) comment out the patch from the series file
77 # 3) else
78 # a) push the patch onto the stack
80 IFS=":"
81 cat "$rebase_dir/status" | while read hash name; do
82 disp ""
83 IFS=" "
84 cat "$GUILT_DIR/$branch/$name" | git patch-id |
85 while read patchid commitid ; do
86 disp "Applying '$name'"
87 if [ -f "$rebase_dir/$patchid" ]; then
88 realcommit=`head_n 1 "$rebase_dir/$patchid"`
89 disp "Matches upstream commit $realcommit"
90 series_rename_patch "$name" "###rebased###$name"
91 disp "Patch removed from series."
92 else
93 # FIXME: use a guilt function instead
94 guilt-push > /dev/null
95 disp "Patch applied."
97 done
98 IFS=":"
99 done
101 rm -rf "$rebase_dir"
103 disp ""
104 disp "Done."