From c42abfe785729587643dec5e7bba414dc3943817 Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Mon, 28 May 2018 14:34:19 +0200 Subject: [PATCH] rebase: introduce a dedicated backend for --preserve-merges This duplicates git-rebase--interactive.sh to git-rebase--preserve-merges.sh. This is done to split -p from -i. No modifications are made to this file here, but any code that is not used by -p will be stripped in the next commit. Signed-off-by: Alban Gruin --- .gitignore | 1 + Makefile | 2 + git-rebase--preserve-merges.sh | 1069 ++++++++++++++++++++++++++++++++ 3 files changed, 1072 insertions(+) create mode 100644 git-rebase--preserve-merges.sh diff --git a/.gitignore b/.gitignore index 833ef3b0b7..ef4925485b 100644 --- a/.gitignore +++ b/.gitignore @@ -117,6 +117,7 @@ /git-rebase--helper /git-rebase--interactive /git-rebase--merge +/git-rebase--preserve-merges /git-receive-pack /git-reflog /git-remote diff --git a/Makefile b/Makefile index 50da82b016..810a0d0f46 100644 --- a/Makefile +++ b/Makefile @@ -582,6 +582,7 @@ SCRIPT_LIB += git-mergetool--lib SCRIPT_LIB += git-parse-remote SCRIPT_LIB += git-rebase--am SCRIPT_LIB += git-rebase--interactive +SCRIPT_LIB += git-rebase--preserve-merges SCRIPT_LIB += git-rebase--merge SCRIPT_LIB += git-sh-setup SCRIPT_LIB += git-sh-i18n @@ -2271,6 +2272,7 @@ LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H) LOCALIZED_SH = $(SCRIPT_SH) LOCALIZED_SH += git-parse-remote.sh LOCALIZED_SH += git-rebase--interactive.sh +LOCALIZED_SH += git-rebase--preserve-merges.sh LOCALIZED_SH += git-sh-setup.sh LOCALIZED_PERL = $(SCRIPT_PERL) diff --git a/git-rebase--preserve-merges.sh b/git-rebase--preserve-merges.sh new file mode 100644 index 0000000000..2f4941d0fc --- /dev/null +++ b/git-rebase--preserve-merges.sh @@ -0,0 +1,1069 @@ +# This shell script fragment is sourced by git-rebase to implement +# its interactive mode. "git rebase --interactive" makes it easy +# to fix up commits in the middle of a series and rearrange commits. +# +# Copyright (c) 2006 Johannes E. Schindelin +# +# The original idea comes from Eric W. Biederman, in +# https://public-inbox.org/git/m1odwkyuf5.fsf_-_@ebiederm.dsl.xmission.com/ +# +# The file containing rebase commands, comments, and empty lines. +# This file is created by "git rebase -i" then edited by the user. As +# the lines are processed, they are removed from the front of this +# file and written to the tail of $done. +todo="$state_dir"/git-rebase-todo + +# The rebase command lines that have already been processed. A line +# is moved here when it is first handled, before any associated user +# actions. +done="$state_dir"/done + +# The commit message that is planned to be used for any changes that +# need to be committed following a user interaction. +msg="$state_dir"/message + +# The file into which is accumulated the suggested commit message for +# squash/fixup commands. When the first of a series of squash/fixups +# is seen, the file is created and the commit message from the +# previous commit and from the first squash/fixup commit are written +# to it. The commit message for each subsequent squash/fixup commit +# is appended to the file as it is processed. +# +# The first line of the file is of the form +# # This is a combination of $count commits. +# where $count is the number of commits whose messages have been +# written to the file so far (including the initial "pick" commit). +# Each time that a commit message is processed, this line is read and +# updated. It is deleted just before the combined commit is made. +squash_msg="$state_dir"/message-squash + +# If the current series of squash/fixups has not yet included a squash +# command, then this file exists and holds the commit message of the +# original "pick" commit. (If the series ends without a "squash" +# command, then this can be used as the commit message of the combined +# commit without opening the editor.) +fixup_msg="$state_dir"/message-fixup + +# $rewritten is the name of a directory containing files for each +# commit that is reachable by at least one merge base of $head and +# $upstream. They are not necessarily rewritten, but their children +# might be. This ensures that commits on merged, but otherwise +# unrelated side branches are left alone. (Think "X" in the man page's +# example.) +rewritten="$state_dir"/rewritten + +dropped="$state_dir"/dropped + +end="$state_dir"/end +msgnum="$state_dir"/msgnum + +# A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and +# GIT_AUTHOR_DATE that will be used for the commit that is currently +# being rebased. +author_script="$state_dir"/author-script + +# When an "edit" rebase command is being processed, the SHA1 of the +# commit to be edited is recorded in this file. When "git rebase +# --continue" is executed, if there are any staged changes then they +# will be amended to the HEAD commit, but only provided the HEAD +# commit is still the commit to be edited. When any other rebase +# command is processed, this file is deleted. +amend="$state_dir"/amend + +# For the post-rewrite hook, we make a list of rewritten commits and +# their new sha1s. The rewritten-pending list keeps the sha1s of +# commits that have been processed, but not committed yet, +# e.g. because they are waiting for a 'squash' command. +rewritten_list="$state_dir"/rewritten-list +rewritten_pending="$state_dir"/rewritten-pending + +# Work around Git for Windows' Bash whose "read" does not strip CRLF +# and leaves CR at the end instead. +cr=$(printf "\015") + +strategy_args=${strategy:+--strategy=$strategy} +test -n "$strategy_opts" && +eval ' + for strategy_opt in '"$strategy_opts"' + do + strategy_args="$strategy_args -X$(git rev-parse --sq-quote "${strategy_opt#--}")" + done +' + +GIT_CHERRY_PICK_HELP="$resolvemsg" +export GIT_CHERRY_PICK_HELP + +comment_char=$(git config --get core.commentchar 2>/dev/null) +case "$comment_char" in +'' | auto) + comment_char="#" + ;; +?) + ;; +*) + comment_char=$(echo "$comment_char" | cut -c1) + ;; +esac + +warn () { + printf '%s\n' "$*" >&2 +} + +# Output the commit message for the specified commit. +commit_message () { + git cat-file commit "$1" | sed "1,/^$/d" +} + +orig_reflog_action="$GIT_REFLOG_ACTION" + +comment_for_reflog () { + case "$orig_reflog_action" in + ''|rebase*) + GIT_REFLOG_ACTION="rebase -i ($1)" + export GIT_REFLOG_ACTION + ;; + esac +} + +last_count= +mark_action_done () { + sed -e 1q < "$todo" >> "$done" + sed -e 1d < "$todo" >> "$todo".new + mv -f "$todo".new "$todo" + new_count=$(( $(git stripspace --strip-comments <"$done" | wc -l) )) + echo $new_count >"$msgnum" + total=$(($new_count + $(git stripspace --strip-comments <"$todo" | wc -l))) + echo $total >"$end" + if test "$last_count" != "$new_count" + then + last_count=$new_count + eval_gettext "Rebasing (\$new_count/\$total)"; printf "\r" + test -z "$verbose" || echo + fi +} + +# Put the last action marked done at the beginning of the todo list +# again. If there has not been an action marked done yet, leave the list of +# items on the todo list unchanged. +reschedule_last_action () { + tail -n 1 "$done" | cat - "$todo" >"$todo".new + sed -e \$d <"$done" >"$done".new + mv -f "$todo".new "$todo" + mv -f "$done".new "$done" +} + +append_todo_help () { + gettext " +Commands: +p, pick = use commit +r, reword = use commit, but edit the commit message +e, edit = use commit, but stop for amending +s, squash = use commit, but meld into previous commit +f, fixup = like \"squash\", but discard this commit's log message +x, exec = run command (the rest of the line) using shell +d, drop = remove commit +l, label