From: "Jörg Sommer" <joerg@alea.gnuu.de>
To: git@vger.kernel.org
Cc: gitster@pobox.com, Johannes.Schindelin@gmx.de,
"Jörg Sommer" <joerg@alea.gnuu.de>
Subject: [PATCH/RFC 10/10] Do rebase with preserve merges with advanced TODO list
Date: Thu, 10 Apr 2008 01:58:41 +0200 [thread overview]
Message-ID: <1207785521-27742-11-git-send-email-joerg@alea.gnuu.de> (raw)
In-Reply-To: <1207785521-27742-10-git-send-email-joerg@alea.gnuu.de>
---
git-rebase--interactive.sh | 248 ++++++++++++++++++++++++-----------------
t/t3404-rebase-interactive.sh | 34 ++++++
2 files changed, 181 insertions(+), 101 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 060b40f..27bd87e 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -22,12 +22,10 @@ TODO="$DOTEST"/git-rebase-todo
DONE="$DOTEST"/done
MSG="$DOTEST"/message
SQUASH_MSG="$DOTEST"/message-squash
-REWRITTEN="$DOTEST"/rewritten
MARKS="$DOTEST"/marks
PRESERVE_MERGES=
STRATEGY=
VERBOSE=
-test -d "$REWRITTEN" && PRESERVE_MERGES=t
test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
test -f "$DOTEST"/verbose && VERBOSE=t
@@ -137,8 +135,6 @@ pick_one () {
no_ff=
case "$1" in -n) sha1=$2; no_ff=t ;; *) sha1=$1 ;; esac
output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
- test -d "$REWRITTEN" &&
- pick_one_preserving_merges "$@" && return
parent_sha1=$(git rev-parse --verify $sha1^) ||
die "Could not get the parent of $sha1"
current_sha1=$(git rev-parse --verify HEAD)
@@ -152,66 +148,6 @@ pick_one () {
fi
}
-pick_one_preserving_merges () {
- case "$1" in -n) sha1=$2 ;; *) sha1=$1 ;; esac
- sha1=$(git rev-parse $sha1)
-
- if test -f "$DOTEST"/current-commit
- then
- current_commit=$(cat "$DOTEST"/current-commit) &&
- git rev-parse HEAD > "$REWRITTEN"/$current_commit &&
- rm "$DOTEST"/current-commit ||
- die "Cannot write current commit's replacement sha1"
- fi
-
- # rewrite parents; if none were rewritten, we can fast-forward.
- fast_forward=t
- preserve=t
- new_parents=
- for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
- do
- if test -f "$REWRITTEN"/$p
- then
- preserve=f
- new_p=$(cat "$REWRITTEN"/$p)
- test $p != $new_p && fast_forward=f
- case "$new_parents" in
- *$new_p*)
- ;; # do nothing; that parent is already there
- *)
- new_parents="$new_parents $new_p"
- ;;
- esac
- fi
- done
- case $fast_forward in
- t)
- output warn "Fast forward to $sha1"
- test $preserve = f || echo $sha1 > "$REWRITTEN"/$sha1
- ;;
- f)
- test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
-
- first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
- # detach HEAD to current parent
- output git checkout $first_parent 2> /dev/null ||
- die "Cannot move HEAD to $first_parent"
-
- echo $sha1 > "$DOTEST"/current-commit
- case "$new_parents" in
- ' '*' '*)
- # No point in merging the first parent, that's HEAD
- redo_merge $sha1 ${new_parents# $first_parent}
- ;;
- *)
- output git cherry-pick "$@" ||
- die_with_patch $sha1 "Could not pick $sha1"
- ;;
- esac
- ;;
- esac
-}
-
nth_string () {
case "$1" in
*1[0-9]|*[04-9]) echo "$1"th;;
@@ -410,20 +346,7 @@ do_next () {
HEADNAME=$(cat "$DOTEST"/head-name) &&
OLDHEAD=$(cat "$DOTEST"/head) &&
SHORTONTO=$(git rev-parse --short $(cat "$DOTEST"/onto)) &&
- if test -d "$REWRITTEN"
- then
- test -f "$DOTEST"/current-commit &&
- current_commit=$(cat "$DOTEST"/current-commit) &&
- git rev-parse HEAD > "$REWRITTEN"/$current_commit
- if test -f "$REWRITTEN"/$OLDHEAD
- then
- NEWHEAD=$(cat "$REWRITTEN"/$OLDHEAD)
- else
- NEWHEAD=$OLDHEAD
- fi
- else
- NEWHEAD=$(git rev-parse HEAD)
- fi &&
+ NEWHEAD=$(git rev-parse HEAD) &&
case $HEADNAME in
refs/*)
message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
@@ -448,6 +371,138 @@ do_rest () {
done
}
+sha1_to_mark() {
+ # args: "sha1" " sha1#mark sha1#mark"
+ local tmp
+ case "$2" in
+ *" $1#"*)
+ tmp="${2#* $1#}"
+ echo "${tmp%% *}"
+ ;;
+ *)
+ return 1
+ ;;
+ esac
+}
+
+insert_sha1_with_mark_in_list() {
+ # args: "sha1" "mark" " sha1#mark sha1#mark"
+ case "$3" in
+ *" $1#"*)
+ echo "$3"
+ return 1
+ ;;
+ *)
+ echo "$3 $1#$2"
+ ;;
+ esac
+}
+
+create_extended_todo_list() {
+ (
+ while IFS=_ read commit parents subject
+ do
+ if test "${last_parent:-$commit}" != "$commit"
+ then
+ if test t = "${delayed_mark:-f}"
+ then
+ case "${marked_commits:-} " in
+ *" $last_parent ")
+ ;;
+ *)
+ marked_commits="${marked_commits:-} $last_parent"
+ ;;
+ esac
+ delayed_mark=f
+ fi
+ test "$last_parent" = $SHORTUPSTREAM && \
+ last_parent=$SHORTONTO
+ echo "reset $last_parent"
+ fi
+ last_parent="${parents%% *}"
+
+ case "${marked_commits:-} " in
+ *" $commit "*)
+ echo mark
+ ;;
+ esac
+
+ case "$parents" in
+ *' '*)
+ delayed_mark=t
+ new_parents=
+ for p in ${parents#* }
+ do
+ case "${marked_commits:-} " in
+ *" $p ")
+ ;;
+ *)
+ marked_commits="${marked_commits:-} $p"
+ ;;
+ esac
+ if test "$p" = $SHORTUPSTREAM
+ then
+ new_parents="$new_parents $SHORTONTO"
+ else
+ new_parents="$new_parents $p"
+ fi
+ done
+ unset p
+ echo merge $commit $new_parents
+ unset new_parents
+ ;;
+ *)
+ echo "pick $commit $subject"
+ ;;
+ esac
+ done
+ test -n "${last_parent:-}" -a "${last_parent:-}" != $SHORTUPSTREAM && \
+ echo reset $last_parent
+ ) | \
+ tac | \
+ while read cmd args
+ do
+ : ${commit_mark_list:=} ${last_commit:=000}
+ case "$cmd" in
+ pick)
+ last_commit="${args%% *}"
+ ;;
+ mark)
+ : ${next_mark:=0}
+ if commit_mark_list=$(insert_sha1_with_mark_in_list \
+ $last_commit $next_mark "$commit_mark_list")
+ then
+ args="#$next_mark"
+ next_mark=$(($next_mark + 1))
+ else
+ die "Internal error: two marks for the same commit"
+ fi
+ ;;
+ reset)
+ if tmp=$(sha1_to_mark $args "$commit_mark_list")
+ then
+ args="#$tmp"
+ fi
+ ;;
+ merge)
+ new_args=
+ for i in ${args#* }
+ do
+ if tmp=$(sha1_to_mark $i "$commit_mark_list")
+ then
+ new_args="$new_args #$tmp"
+ else
+ new_args="$new_args $i"
+ fi
+ done
+ last_commit="${args%% *}"
+ args="$last_commit ${new_args# }"
+ ;;
+ esac
+ echo "$cmd $args"
+ done
+}
+
while test $# != 0
do
case "$1" in
@@ -580,33 +635,24 @@ do
echo $ONTO > "$DOTEST"/onto
test -z "$STRATEGY" || echo "$STRATEGY" > "$DOTEST"/strategy
test t = "$VERBOSE" && : > "$DOTEST"/verbose
- if test t = "$PRESERVE_MERGES"
- then
- # $REWRITTEN contains 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.)
- mkdir "$REWRITTEN" &&
- for c in $(git merge-base --all $HEAD $UPSTREAM)
- do
- echo $ONTO > "$REWRITTEN"/$c ||
- die "Could not init rewritten commits"
- done
- MERGES_OPTION=
- else
- MERGES_OPTION=--no-merges
- fi
SHORTUPSTREAM=$(git rev-parse --short=7 $UPSTREAM)
SHORTHEAD=$(git rev-parse --short=7 $HEAD)
SHORTONTO=$(git rev-parse --short=7 $ONTO)
- git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
- --abbrev=7 --reverse --left-right --cherry-pick \
- $UPSTREAM...$HEAD | \
- sed -n "s/^>/pick /p" > "$TODO"
+ common_rev_parse_opts="--abbrev-commit
+ --abbrev=7 --left-right --cherry-pick
+ $UPSTREAM...$HEAD"
+ if test t = "$PRESERVE_MERGES"
+ then
+ git rev-list --pretty='format:%h_%p_%s' \
+ --topo-order $common_rev_parse_opts | \
+ grep -v ^commit | \
+ create_extended_todo_list
+ else
+ git rev-list --no-merges --reverse --pretty=oneline \
+ $common_rev_parse_opts | sed -n "s/^>/pick /p"
+ fi > "$TODO"
+
cat >> "$TODO" << EOF
# Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index be26a78..af7d818 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -245,7 +245,41 @@ test_expect_success 'preserve merges with -p' '
test $(git show HEAD~2:file1) = B
'
+test_expect_success 'rebase with preserve merge forth and back is a noop' '
+ git checkout -b big-branch-1 master &&
+ : > bb1a &&
+ git add bb1a &&
+ git commit -m "big branch commit 1" &&
+ : > bb1b &&
+ git add bb1b &&
+ git commit -m "big branch commit 2" &&
+ : > bb1c &&
+ git add bb1c &&
+ git commit -m "big branch commit 3" &&
+ git checkout -b big-branch-2 master &&
+ : > bb2a &&
+ git add bb2a &&
+ git commit -m "big branch commit 4" &&
+ : > bb2b &&
+ git add bb2b &&
+ git commit -m "big branch commit 5" &&
+ git merge big-branch-1~1 &&
+ git merge to-be-preserved &&
+ tbp_merge=$(git rev-parse HEAD) &&
+ : > bb2c &&
+ git add bb2c &&
+ git commit -m "big branch commit 6" &&
+ git merge big-branch-1 &&
+ head=$(git rev-parse HEAD) &&
+ FAKE_LINES="16 6 19 20 4 1 2 5 22" \
+ git rebase -i -p --onto dead-end master &&
+ FAKE_LINES="3 7 mark#10 8 9 5 1 2 merge$tbp_merge~1/#10 merge$tbp_merge/to-be-preserved 6 11" \
+ git rebase -i -p --onto master dead-end &&
+ test "$head" = "$(git rev-parse HEAD)"
+'
+
test_expect_success '--continue tries to commit' '
+ git checkout to-be-rebased &&
test_tick &&
! git rebase -i --onto new-branch1 HEAD^ &&
echo resolved > file1 &&
--
1.5.4.5
next prev parent reply other threads:[~2008-04-10 0:04 UTC|newest]
Thread overview: 104+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-23 21:42 [PATCH 1/4] Move redo merge code in a function Jörg Sommer
2008-03-23 21:42 ` [PATCH 2/4] Rework redo_merge Jörg Sommer
2008-03-23 21:42 ` [PATCH 3/4] Add a function for get the parents of a commit Jörg Sommer
2008-03-23 21:42 ` [PATCH 4/4] git-rebase -i: New option to support rebase with merges Jörg Sommer
2008-03-23 22:41 ` Johannes Schindelin
2008-03-24 11:14 ` Jörg Sommer
2008-03-24 13:08 ` Johannes Schindelin
2008-03-24 23:40 ` Jörg Sommer
2008-03-24 18:35 ` Junio C Hamano
2008-03-24 23:30 ` Junio C Hamano
2008-03-25 10:13 ` Jörg Sommer
2008-03-26 8:02 ` Junio C Hamano
2008-04-09 23:58 ` Teach rebase interactive more commands to do better preserve merges Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 01/10] Teach rebase interactive the mark command Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 02/10] Teach rebase interactive the reset command Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 03/10] Teach rebase interactive the merge command Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 04/10] Move redo merge code in a function Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 05/10] Rework redo_merge Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 06/10] Unify the lenght of $SHORT* and the commits in the TODO list Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 07/10] fake-editor: output TODO list if unchanged Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 08/10] Don't append default merge message to -m message Jörg Sommer
2008-04-09 23:58 ` [PATCH/RFC 09/10] Select all lines with fake-editor Jörg Sommer
2008-04-09 23:58 ` Jörg Sommer [this message]
2008-04-12 0:00 ` [PATCH/RFC 06/10] Unify the lenght of $SHORT* and the commits in the TODO list Junio C Hamano
2008-04-12 9:13 ` Jörg Sommer
2008-04-13 6:20 ` Junio C Hamano
2008-04-13 16:39 ` Jörg Sommer
2008-04-14 1:06 ` Tarmigan
2008-04-11 23:56 ` [PATCH/RFC 02/10] Teach rebase interactive the reset command Junio C Hamano
2008-04-12 9:37 ` Jörg Sommer
2008-04-10 9:33 ` [PATCH/RFC 01/10] Teach rebase interactive the mark command Mike Ralphson
2008-04-12 10:17 ` Jörg Sommer
2008-04-11 23:48 ` Junio C Hamano
2008-04-12 10:11 ` Jörg Sommer
2008-04-13 3:56 ` Shawn O. Pearce
2008-04-13 16:50 ` Jörg Sommer
2008-04-14 6:24 ` Shawn O. Pearce
2008-04-14 6:54 ` Junio C Hamano
2008-04-14 10:06 ` Jörg Sommer
2008-04-14 0:20 ` [PATCH v2 01/13] fake-editor: output TODO list if unchanged Jörg Sommer
2008-04-14 0:20 ` [PATCH v2 02/13] Don't append default merge message to -m message Jörg Sommer
2008-04-14 0:20 ` [PATCH v2 03/13] Move cleanup code into it's own function Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 04/13] Teach rebase interactive the mark command Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 05/13] Teach rebase interactive the reset command Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 06/13] Move redo merge code in a function Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 07/13] Teach rebase interactive the merge command Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 08/13] Unify the lenght of $SHORT* and the commits in the TODO list Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 09/13] Select all lines with fake-editor Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 10/13] Do rebase with preserve merges with advanced TODO list Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 11/13] Add option --first-parent Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 12/13] Teach rebase interactive the tag command Jörg Sommer
2008-04-14 0:21 ` [PATCH v2 13/13] Add option --preserve-tags Jörg Sommer
2008-04-22 5:32 ` [PATCH v2 04/13] Teach rebase interactive the mark command Junio C Hamano
2008-04-22 8:13 ` Junio C Hamano
2008-04-22 8:52 ` Johannes Schindelin
2008-04-22 9:55 ` Jörg Sommer
2008-04-22 10:31 ` Johannes Schindelin
2008-04-22 16:56 ` Junio C Hamano
2008-04-22 17:12 ` Johannes Schindelin
2008-04-29 0:25 ` Junio C Hamano
2008-04-29 0:39 ` Johannes Schindelin
2008-04-29 5:17 ` Junio C Hamano
2008-04-29 7:12 ` Johannes Sixt
2008-04-29 10:52 ` Johannes Schindelin
2008-04-29 21:16 ` Junio C Hamano
2008-04-29 21:25 ` Johannes Schindelin
2008-04-29 22:23 ` Junio C Hamano
2008-04-29 22:55 ` Johannes Schindelin
2008-04-29 23:06 ` Junio C Hamano
2008-04-29 23:31 ` Johannes Schindelin
2008-04-30 1:23 ` Junio C Hamano
2008-04-30 6:25 ` Johannes Sixt
2008-04-30 7:10 ` Junio C Hamano
2008-04-30 8:47 ` Johannes Schindelin
2008-04-30 9:19 ` Junio C Hamano
2008-04-30 10:29 ` Johannes Sixt
2008-04-30 11:56 ` Johannes Schindelin
2008-05-01 19:04 ` Junio C Hamano
2008-05-03 12:45 ` Johannes Schindelin
2008-05-03 17:09 ` Junio C Hamano
2008-05-04 9:38 ` Johannes Schindelin
2008-05-04 12:52 ` Jörg Sommer
2008-04-30 13:06 ` Dmitry Potapov
2008-05-01 12:59 ` Johannes Schindelin
2008-04-22 18:04 ` Junio C Hamano
2008-04-25 9:11 ` Jörg Sommer
2008-04-25 9:44 ` [PATCH v2.2] " Jörg Sommer
2008-04-27 6:13 ` Junio C Hamano
2008-04-27 8:28 ` Jörg Sommer
2008-04-14 10:39 ` [PATCH v2.1] " Jörg Sommer
2008-04-14 23:29 ` Shawn O. Pearce
2008-04-20 23:44 ` mark parsing in fast-import Jörg Sommer
2008-04-21 0:26 ` Shawn O. Pearce
2008-04-21 8:41 ` Jörg Sommer
2008-04-21 23:59 ` Shawn O. Pearce
2008-04-22 9:39 ` Jörg Sommer
2008-04-22 23:15 ` Shawn O. Pearce
2008-04-25 9:04 ` [PATCH v2] Make mark parsing much more restrictive Jörg Sommer
2008-04-20 16:52 ` [PATCH v2 02/13] Don't append default merge message to -m message Junio C Hamano
2008-04-21 0:17 ` Jörg Sommer
2008-04-22 5:27 ` Junio C Hamano
2008-03-23 22:33 ` [PATCH 3/4] Add a function for get the parents of a commit Johannes Schindelin
2008-03-23 22:29 ` [PATCH 2/4] Rework redo_merge Johannes Schindelin
2008-03-23 22:26 ` [PATCH 1/4] Move redo merge code in a function Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1207785521-27742-11-git-send-email-joerg@alea.gnuu.de \
--to=joerg@alea.gnuu.de \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).