@@ -1058,3 +1058,111 @@ git_rebase__interactive () {
1058
1058
1059
1059
complete_action
1060
1060
}
1061
+
1062
+ git_rebase__interactive__preserve_merges () {
1063
+ initiate_action " $action "
1064
+ ret=$?
1065
+ if test $ret = 0; then
1066
+ return 0
1067
+ fi
1068
+
1069
+ setup_reflog_action
1070
+ init_basic_state
1071
+
1072
+ if test t = " $preserve_merges "
1073
+ then
1074
+ if test -z " $rebase_root "
1075
+ then
1076
+ mkdir " $rewritten " &&
1077
+ for c in $( git merge-base --all $orig_head $upstream )
1078
+ do
1079
+ echo $onto > " $rewritten " /$c ||
1080
+ die " $( gettext " Could not init rewritten commits" ) "
1081
+ done
1082
+ else
1083
+ mkdir " $rewritten " &&
1084
+ echo $onto > " $rewritten " /root ||
1085
+ die " $( gettext " Could not init rewritten commits" ) "
1086
+ fi
1087
+ # No cherry-pick because our first pass is to determine
1088
+ # parents to rewrite and skipping dropped commits would
1089
+ # prematurely end our probe
1090
+ merges_option=
1091
+ else
1092
+ merges_option=" --no-merges --cherry-pick"
1093
+ fi
1094
+
1095
+ init_revisions_and_shortrevisions
1096
+
1097
+ if test t ! = " $preserve_merges "
1098
+ then
1099
+ git rebase--helper --make-script ${keep_empty: +--keep-empty} \
1100
+ $revisions ${restrict_revision+^$restrict_revision } > " $todo " ||
1101
+ die " $( gettext " Could not generate todo list" ) "
1102
+ else
1103
+ format=$( git config --get rebase.instructionFormat)
1104
+ # the 'rev-list .. | sed' requires %m to parse; the instruction requires %H to parse
1105
+ git rev-list $merges_option --format=" %m%H ${format:-% s} " \
1106
+ --reverse --left-right --topo-order \
1107
+ $revisions ${restrict_revision+^$restrict_revision } | \
1108
+ sed -n " s/^>//p" |
1109
+ while read -r sha1 rest
1110
+ do
1111
+
1112
+ if test -z " $keep_empty " && is_empty_commit $sha1 && ! is_merge_commit $sha1
1113
+ then
1114
+ comment_out=" $comment_char "
1115
+ else
1116
+ comment_out=
1117
+ fi
1118
+
1119
+ if test -z " $rebase_root "
1120
+ then
1121
+ preserve=t
1122
+ for p in $( git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
1123
+ do
1124
+ if test -f " $rewritten " /$p
1125
+ then
1126
+ preserve=f
1127
+ fi
1128
+ done
1129
+ else
1130
+ preserve=f
1131
+ fi
1132
+ if test f = " $preserve "
1133
+ then
1134
+ touch " $rewritten " /$sha1
1135
+ printf ' %s\n' " ${comment_out} pick $sha1 $rest " >> " $todo "
1136
+ fi
1137
+ done
1138
+ fi
1139
+
1140
+ # Watch for commits that been dropped by --cherry-pick
1141
+ if test t = " $preserve_merges "
1142
+ then
1143
+ mkdir " $dropped "
1144
+ # Save all non-cherry-picked changes
1145
+ git rev-list $revisions --left-right --cherry-pick | \
1146
+ sed -n " s/^>//p" > " $state_dir " /not-cherry-picks
1147
+ # Now all commits and note which ones are missing in
1148
+ # not-cherry-picks and hence being dropped
1149
+ git rev-list $revisions |
1150
+ while read rev
1151
+ do
1152
+ if test -f " $rewritten " /$rev &&
1153
+ ! sane_grep " $rev " " $state_dir " /not-cherry-picks > /dev/null
1154
+ then
1155
+ # Use -f2 because if rev-list is telling us this commit is
1156
+ # not worthwhile, we don't want to track its multiple heads,
1157
+ # just the history of its first-parent for others that will
1158
+ # be rebasing on top of it
1159
+ git rev-list --parents -1 $rev | cut -d' ' -s -f2 > " $dropped " /$rev
1160
+ sha1=$( git rev-list -1 $rev )
1161
+ sane_grep -v " ^[a-z][a-z]* $sha1 " < " $todo " > " ${todo} 2" ; mv " ${todo} 2" " $todo "
1162
+ rm " $rewritten " /$rev
1163
+ fi
1164
+ done
1165
+ fi
1166
+
1167
+ complete_action
1168
+ }
0 commit comments