--force: Propagate to shears.sh
[msysgit.git] / share / msysGit / merging-rebase.sh
blob02a04e517dde1748ee1c6f04022aae35ff40b61b
1 #!/bin/sh
3 # Rebase 'master' on top of an upstream branch (defaults to 'junio/next'),
4 # retaining "fast-forwardability" by "merging" (with the "ours" strategy) the
5 # previous state on top of the current upstream state.
7 # options:
8 # --dry-run
9 # do not perform the rebase but only display the revisions selected
11 # --graph
12 # as for dry-run but display the commits as a graph
14 # --cherry
15 # as for --dry-run but display the commits using cherry notation to mark
16 # commits that are suitable for upstream consideration.
18 force=
19 dryrun=
20 graph=
21 cherry=
22 while test $# -gt 0
24 case "$1" in
25 -f|--force)
26 force=--force
28 -s|--show|-d|--dry-run)
29 dryrun=t
31 -g|--graph)
32 dryrun=t
33 graph=--graph
35 -c|--cherry)
36 dryrun=t
37 cherry=--cherry
39 -h|--help)
40 cat >&2 << EOF
41 Usage: $0 [options] [<upstream>]
43 Options:
44 -s|--show show which commits would be cherry-picked
45 -g|--graph like --show, but with the commit graph
46 -c|--cherry try to leave out commits that were applied upstream
47 EOF
48 exit 1
50 -*)
51 echo "Unknown option: $1" >&2
52 exit 1
55 break
57 esac
58 shift
59 done
61 TO=${1:-junio/next}
63 if test -z "$force" && test -z "$(git rev-list .."$TO")"
64 then
65 echo "Nothing new in $TO; To force a rebase, use the --force, Luke!" >&2
66 exit 1
69 HEAD_NAME="$(git rev-parse --symbolic-full-name HEAD)"
70 case "$HEAD_NAME" in
71 refs/heads/*)
72 UPSTREAM=$(git rev-parse --symbolic-full-name HEAD@{u}) || {
73 echo "Not tracking any remote branch!" >&2
74 exit 1
76 test "$(git rev-parse HEAD)" = "$(git rev-parse $UPSTREAM)" ||
77 test "$(git rev-parse $HEAD_NAME@{1})" = "$(git rev-parse $UPSTREAM)" || {
78 echo "Your '$HEAD_NAME' is not up-to-date!" >&2
79 exit 1
81 ;; # okay
82 HEAD) ;; # okay
84 echo "Not on any branch!" >&2
85 exit 1
87 esac
88 FROM_SHA1=$(git rev-parse --short HEAD)
89 TO_SHA1=$(git rev-parse --short $TO)
91 is_ours_merge () {
92 test "$(git rev-parse $1:)" = "$(git rev-parse "$1^:")"
95 list_merges () {
96 git rev-list --parents "$@" | sed -n 's/ .* .*//p'
99 # Find old merging rebase, if any
101 REBASING_BASE=
102 for commit in $(list_merges $TO..)
104 if is_ours_merge $commit
105 then
106 subject="$(git show -s --format=%s $commit)"
107 case "$subject" in
108 *merging-rebase*) ;;
110 printf "%s\n\n%s\n%s\n\n(y/n) " \
111 "Is this the latest merging rebase?" \
112 $commit "$subject"
113 read answer
114 case "$answer" in
115 y*|Y*) ;;
116 *) continue;;
117 esac;;
118 esac
119 REBASING_BASE=$commit
120 break
122 done
124 BASE_MESSAGE=
125 if test -n "$REBASING_BASE"
126 then
127 BASE_MESSAGE="using $REBASING_BASE as base."
128 MESSAGE="$(git cat-file commit $REBASING_BASE |
129 sed '1,/^$/d')"
130 # old style rebasing merge?
131 case "$MESSAGE" in
132 "Rebasing merge to "*)
133 BASE_MESSAGE="using the rebasing merge $REBASING_BASE."
134 # Fake a commit such that 'git log <commit>..' shows all the
135 # commits we want to rebase
136 PREVIOUS_REBASING="$(git rev-parse $REBASING_BASE^2)"
137 PREVIOUS_ONTO="$(echo "$MESSAGE" |
138 sed -n '1s/Rebasing merge .*(\(.*\))/\1/p')"
139 # To avoid checking out unneeded files/file versions, the
140 # throw-away base points to the tree we want to rebase onto
141 REBASING_BASE="$(echo Dummy |
142 git commit-tree $TO_SHA1: \
143 -p $PREVIOUS_ONTO -p $PREVIOUS_REBASING)"
145 esac
148 RANGE=$REBASING_BASE..
149 if test -n "$dryrun"
150 then
151 git log --oneline $graph $cherry --boundary $RANGE
152 exit
155 exec "$(dirname "$0")"/shears.sh $force --merging --onto=$TO ${REBASING_BASE:-$TO}