rebasing-merge: Added --cherry and --dry-run options
[git/jnareb-git.git] / share / msysGit / rebasing-merge.sh
blob3d2bb6d504cc92e1f527260f73066aaf2483527c
1 #!/bin/sh
3 # Rebase 'devel' on top of an upstream branch (defaults to 'junio/next').
4 # This merges the old state of 'devel' using the merge strategy 'ours'
5 # to enable a fast-forward.
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=t
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 -*)
40 echo "Unknown option: $1" >&2
41 exit 1
44 break
46 esac
47 shift
48 done
50 TO=${1:-junio/next}
52 if test -z "$force" && test -z "$(git rev-list .."$TO")"
53 then
54 echo "Nothing new in $TO; To force a rebase, use the --force, Luke!" >&2
55 exit 1
58 TODO_EXTRA="$(git rev-parse --git-dir)/todo-extra"
60 case "$(git rev-parse --symbolic-full-name HEAD)" in
61 refs/heads/devel)
62 UPSTREAM=$(git rev-parse --symbolic-full-name HEAD@{u}) || {
63 echo "Not tracking any remote branch!" >&2
64 exit 1
66 test "$(git rev-parse HEAD)" = "$(git rev-parse $UPSTREAM)" ||
67 test "$(git rev-parse devel@{1})" = "$(git rev-parse $UPSTREAM)" || {
68 echo "Your 'devel' is not up-to-date!" >&2
69 exit 1
71 ;; # okay
72 HEAD) ;; # okay
74 echo "Not on 'devel'!" >&2
75 exit 1
77 esac
79 is_ours_merge () {
80 test "$(git rev-parse $1:)" = "$(git rev-parse "$1^:")"
83 list_merges () {
84 git rev-list --parents "$@" | sed -n 's/ .* .*//p'
87 # Find old rebasing merge, if any
89 PREVIOUS_REBASING=
90 for commit in $(list_merges $TO..)
92 if is_ours_merge $commit
93 then
94 PREVIOUS_REBASING=$commit
95 break
97 done
99 TO_SHA1=$(git rev-parse --short $TO)
100 MESSAGE="Rebasing merge to $TO ($TO_SHA1)"
101 RANGE=$TO.. &&
102 if test -n "$PREVIOUS_REBASING"
103 then
104 MESSAGE="$(printf "%s\n\n%s" "$MESSAGE" \
105 "Previous rebasing merge: $PREVIOUS_REBASING")"
106 RANGE="$RANGE ^$PREVIOUS_REBASING^2"
107 for commit in $(list_merges $RANGE)
109 test $commit != $PREVIOUS_REBASING &&
110 is_ours_merge $commit &&
111 RANGE="$RANGE ^$commit"
112 done
115 if test -n "$dryrun"
116 then
117 git log --oneline $graph $cherry --boundary $RANGE
118 exit
121 ORIG_HEAD=$(git rev-parse HEAD)
122 # Get commits to rebase
123 git rev-list --format='pick %h %s (%an)' --reverse --no-merges $RANGE |
124 grep -v '^commit ' > "$TODO_EXTRA" &&
125 TMP_EDITOR="$(git rev-parse --git-dir)/rebasing-editor.sh" &&
126 cat > "$TMP_EDITOR" << EOF &&
127 #!/bin/sh
128 case "\$1" in
129 */git-rebase-todo)
130 sed -e '/^[^#]/d' < "\$1" >> "$TODO_EXTRA" &&
131 mv "$TODO_EXTRA" "\$1"
132 esac &&
133 exec "$(git var GIT_EDITOR)" "\$@"
135 chmod a+x "$TMP_EDITOR" &&
136 if GIT_EDITOR="$TMP_EDITOR" git rebase --autosquash -i --onto $TO HEAD^
137 then
138 git merge -s ours -m "$MESSAGE" $ORIG_HEAD
139 else
140 FINISH="$(git rev-parse --git-dir)/finish-rebasing-merge.sh"
141 cat > "$FINISH" << EOF
142 git merge -s ours -m '$MESSAGE' $ORIG_HEAD
144 chmod a+x "$FINISH"
145 cat << EOF
147 After the rebase, call '$FINISH' manually